Merge pull request #485 from WandererFan/January

TechDraw January Upgrade
This commit is contained in:
wwmayer
2017-01-30 13:58:43 +01:00
committed by GitHub
91 changed files with 5509 additions and 1481 deletions

View File

@@ -31,6 +31,7 @@
#include "DrawViewSymbol.h"
#include "DrawViewClip.h"
#include "DrawHatch.h"
#include "DrawGeomHatch.h"
#include "DrawViewDraft.h"
#include "DrawViewArch.h"
#include "DrawViewSpreadsheet.h"
@@ -84,6 +85,7 @@ PyMODINIT_FUNC initTechDraw()
TechDraw::DrawViewClip ::init();
TechDraw::DrawHatch ::init();
TechDraw::DrawGeomHatch ::init();
TechDraw::DrawViewDraft ::init();
TechDraw::DrawViewArch ::init();
TechDraw::DrawViewImage ::init();

View File

@@ -37,6 +37,7 @@ generate_from_xml(DrawViewSymbolPy)
generate_from_xml(DrawViewClipPy)
generate_from_xml(DrawViewDimensionPy)
generate_from_xml(DrawHatchPy)
generate_from_xml(DrawGeomHatchPy)
generate_from_xml(DrawViewCollectionPy)
generate_from_xml(DrawProjGroupPy)
generate_from_xml(DrawProjGroupItemPy)
@@ -74,6 +75,8 @@ SET(Draw_SRCS
DrawViewSection.h
DrawHatch.cpp
DrawHatch.h
DrawGeomHatch.cpp
DrawGeomHatch.h
DrawViewDraft.cpp
DrawViewDraft.h
DrawViewArch.cpp
@@ -92,6 +95,8 @@ SET(TechDraw_SRCS
DrawUtil.h
Cube.cpp
Cube.h
HatchLine.cpp
HatchLine.h
PreCompiled.cpp
PreCompiled.h
EdgeWalker.cpp
@@ -128,6 +133,8 @@ SET(Python_SRCS
DrawViewDimensionPyImp.cpp
DrawHatchPy.xml
DrawHatchPyImp.cpp
DrawGeomHatchPy.xml
DrawGeomHatchPyImp.cpp
DrawViewCollectionPy.xml
DrawViewCollectionPyImp.cpp
DrawProjGroupPy.xml
@@ -150,6 +157,10 @@ SET(TechDraw_Templates
Templates/A4_Portrait_ISO7200TD.svg
)
SET(TechDraw_PATFile
PAT/FCPAT.pat
)
if(MSVC)
#add_definitions(-D_PreComp_)
#GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" TechDrawCPP_SRCS ${TechDraw_SRCS} ${Draw_SRCS} )
@@ -175,6 +186,11 @@ fc_target_copy_resource(TechDraw
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/TechDraw
${TechDraw_Templates})
fc_target_copy_resource(TechDraw
${CMAKE_SOURCE_DIR}/src/Mod/TechDraw
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/TechDraw
${TechDraw_PATFile})
SET_BIN_DIR(TechDraw TechDraw /Mod/TechDraw)
SET_PYTHON_PREFIX_SUFFIX(TechDraw)

View File

@@ -0,0 +1,435 @@
/***************************************************************************
* Copyright (c) 2015 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#include <iomanip>
#include <cmath>
# include <QFile>
# include <QFileInfo>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <Standard_PrimitiveTypes.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopExp.hxx>
#endif
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/FileInfo.h>
#include <Base/Parameter.h>
#include "HatchLine.h"
#include "DrawUtil.h"
#include "Geometry.h"
#include "DrawViewPart.h"
#include "DrawViewSection.h"
#include "DrawGeomHatch.h"
#include <Mod/TechDraw/App/DrawGeomHatchPy.h> // generated from DrawGeomHatchPy.xml
using namespace TechDraw;
using namespace TechDrawGeometry;
using namespace std;
PROPERTY_SOURCE(TechDraw::DrawGeomHatch, App::DocumentObject)
DrawGeomHatch::DrawGeomHatch(void)
{
static const char *vgroup = "GeomHatch";
ADD_PROPERTY_TYPE(Source,(0),vgroup,(App::PropertyType)(App::Prop_None),"The View + Face to be crosshatched");
ADD_PROPERTY_TYPE(FilePattern ,(""),vgroup,App::Prop_None,"The crosshatch pattern file for this area");
ADD_PROPERTY_TYPE(NamePattern,(""),vgroup,App::Prop_None,"The name of the pattern");
ADD_PROPERTY_TYPE(ScalePattern,(1.0),vgroup,App::Prop_None,"GeomHatch pattern size adjustment");
getParameters();
}
DrawGeomHatch::~DrawGeomHatch()
{
}
void DrawGeomHatch::onChanged(const App::Property* prop)
{
if (prop == &Source ) {
if (!isRestoring()) {
DrawGeomHatch::execute();
}
}
if (prop == &FilePattern ||
prop == &NamePattern ) {
if ((!FilePattern.isEmpty()) &&
(!NamePattern.isEmpty())) {
std::vector<HatchLine> specs = getDecodedSpecsFromFile();
m_lineSets.clear();
for (auto& hl: specs) {
//hl.dump("hl from file");
LineSet ls;
ls.setHatchLine(hl);
m_lineSets.push_back(ls);
}
}
}
App::DocumentObject::onChanged(prop);
}
short DrawGeomHatch::mustExecute() const
{
short result = 0;
if (!isRestoring()) {
result = (Source.isTouched() ||
FilePattern.isTouched() ||
NamePattern.isTouched() );
}
if (result) {
return result;
}
return App::DocumentObject::mustExecute();
}
App::DocumentObjectExecReturn *DrawGeomHatch::execute(void)
{
return App::DocumentObject::StdReturn;
}
DrawViewPart* DrawGeomHatch::getSourceView(void) const
{
App::DocumentObject* obj = Source.getValue();
DrawViewPart* result = dynamic_cast<DrawViewPart*>(obj);
return result;
}
std::vector<HatchLine> DrawGeomHatch::getDecodedSpecsFromFile()
{
std::string fileSpec = FilePattern.getValue();
std::string myPattern = NamePattern.getValue();
return getDecodedSpecsFromFile(fileSpec,myPattern);
}
//!get all the specification lines and decode them into HatchLine structures
/*static*/
std::vector<HatchLine> DrawGeomHatch::getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern)
{
std::vector<HatchLine> result;
Base::FileInfo fi(fileSpec);
if (!fi.isReadable()) {
Base::Console().Error("DrawGeomHatch::getDecodedSpecsFromFile not able to open %s!\n",fileSpec.c_str());
return result;
}
result = HatchLine::getSpecsForPattern(fileSpec,myPattern);
return result;
}
std::vector<LineSet> DrawGeomHatch::getDrawableLines(int i) //get the drawable lines for face i
{
std::vector<LineSet> result;
DrawViewPart* source = getSourceView();
if (!source ||
!source->hasGeometry()) {
Base::Console().Message("TRACE - DC::getDrawableLines - no source geometry\n");
return result;
}
return getDrawableLines(source, m_lineSets,i, ScalePattern.getValue());
}
/* static */
std::vector<LineSet> DrawGeomHatch::getDrawableLines(DrawViewPart* source, std::vector<LineSet> lineSets, int iface, double scale )
{
std::vector<LineSet> result;
//is source is a section?
DrawViewSection* section = dynamic_cast<DrawViewSection*>(source);
bool usingSection = false;
if (section != nullptr) {
usingSection = true;
}
if (lineSets.empty()) {
Base::Console().Log("INFO - DC::getDrawableLines - no LineSets!\n");
return result;
}
std::vector<TopoDS_Wire> faceWires;
if (usingSection) {
faceWires = section->getWireForFace(iface);
} else {
faceWires = source->getWireForFace(iface);
}
//build face(s) from geometry
gp_Pnt gOrg(0.0,0.0,0.0);
gp_Dir gDir(0.0,0.0,1.0);
gp_Pln plane(gOrg,gDir);
BRepBuilderAPI_MakeFace mkFace(plane, faceWires.front(), true);
std::vector<TopoDS_Wire>::iterator itWire = ++faceWires.begin(); //starting with second wire
for (; itWire != faceWires.end(); itWire++) {
mkFace.Add(*itWire);
}
if (!mkFace.IsDone()) {
Base::Console().Log("INFO - DC::getDrawableLines - face creation failed\n");
return result;
}
TopoDS_Face face = mkFace.Face();
Bnd_Box bBox;
BRepBndLib::Add(face, bBox);
bBox.SetGap(0.0);
for (auto& ls: lineSets) {
HatchLine hl = ls.getHatchLine();
std::vector<TopoDS_Edge> candidates = DrawGeomHatch::makeEdgeOverlay(hl, bBox, scale);
//make Compound for this linespec
BRep_Builder builder;
TopoDS_Compound Comp;
builder.MakeCompound(Comp);
for (auto& c: candidates) {
builder.Add(Comp, c);
}
//Common Compound with Face
BRepAlgoAPI_Common mkCommon(face, Comp);
if ((!mkCommon.IsDone()) ||
(mkCommon.Shape().IsNull()) ) {
Base::Console().Log("INFO - DC::getDrawableLines - Common creation failed\n");
return result;
}
TopoDS_Shape common = mkCommon.Shape();
//Save edges from Common
std::vector<TopoDS_Edge> resultEdges;
std::vector<TechDrawGeometry::BaseGeom*> resultGeoms;
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(common, TopAbs_EDGE, mapOfEdges);
for ( int i = 1 ; i <= mapOfEdges.Extent() ; i++ ) {
const TopoDS_Edge& edge = TopoDS::Edge(mapOfEdges(i));
if (edge.IsNull()) {
Base::Console().Log("INFO - DC::getDrawableLines - edge: %d is NULL\n",i);
continue;
}
TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(edge);
if (base == nullptr) {
Base::Console().Log("FAIL - DC::getDrawableLines - baseFactory failed for edge: %d\n",i);
throw Base::Exception("GeometryObject::addGeomFromCompound - baseFactory failed");
}
resultGeoms.push_back(base);
resultEdges.push_back(edge);
}
ls.setEdges(resultEdges);
ls.setGeoms(resultGeoms);
result.push_back(ls);
}
return result;
}
/* static */
std::vector<TopoDS_Edge> DrawGeomHatch::makeEdgeOverlay(HatchLine hl, Bnd_Box b, double scale)
{
std::vector<TopoDS_Edge> result;
double minX,maxX,minY,maxY,minZ,maxZ;
b.Get(minX,minY,minZ,maxX,maxY,maxZ);
Base::Vector3d start;
Base::Vector3d end;
Base::Vector3d origin = hl.getOrigin();
// double interval = hl.getInterval() * ScalePattern.getValue();
double interval = hl.getInterval() * scale;
double angle = hl.getAngle();
//only dealing with angles -180:180 for now
if (angle > 90.0) {
angle = -(180.0 - angle);
} else if (angle < -90.0) {
angle = (180 + angle);
}
angle = -angle; //not sure why this is required? inverted Y?
double slope = tan(angle * M_PI/180.0);
if (angle == 0.0) { //odd case 1: horizontal lines
double y = origin.y;
double x1 = minX;
double x2 = maxX;
start = Base::Vector3d(x1,y,0);
end = Base::Vector3d(x2,y,0);
int repeatUp = (int) ceil(((maxY - y)/interval) + 1);
int repeatDown = (int) ceil(((y - minY)/interval) + 1);
// make up repeats
int i;
for (i = 1; i < repeatUp; i++) {
Base::Vector3d newStart(minX,y + float(i)*interval,0);
Base::Vector3d newEnd(maxX,y + float(i)*interval,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make down repeats
for (i = 1; i < repeatDown; i++) {
Base::Vector3d newStart(minX, y - float(i)*interval,0);
Base::Vector3d newEnd(maxX, y - float(i)*interval,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else if (angle > 0) { //bottomleft - topright
double xRightAtom = origin.x + ((maxY - origin.y)/slope);
double xLeftAtom = origin.x + ((minY - origin.y)/slope);
start = Base::Vector3d(xLeftAtom,minY,0);
end = Base::Vector3d(xRightAtom,maxY,0);
int repeatRight = (int) ceil(((maxX - xLeftAtom)/interval) + 1);
int repeatLeft = (int) ceil(((xRightAtom - minX)/interval) + 1);
// make right repeats
int i;
for (i = 1; i < repeatRight; i++) {
Base::Vector3d newStart(start.x + float(i)*interval,minY,0);
Base::Vector3d newEnd(end.x + float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make left repeats
for (i = 1; i < repeatLeft; i++) {
Base::Vector3d newStart(start.x - float(i)*interval,minY,0);
Base::Vector3d newEnd(end.x - float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else { //topleft - bottomright
double x2 = origin.x + (maxY - origin.y)/slope;
double x1 = origin.x + (minY - origin.y)/slope;
start = Base::Vector3d(x2,maxY,0);
end = Base::Vector3d(x1,minY,0);
int repeatRight = (int) ceil(((maxX - start.x)/interval) + 1);
int repeatLeft = (int) ceil(((end.x - minX)/interval) + 1);
// make right repeats
int i;
for (i = 1; i < repeatRight; i++) {
Base::Vector3d newStart(start.x + float(i)*interval,maxY,0);
Base::Vector3d newEnd(end.x + float(i)*interval,minY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make left repeats
for (i = 1; i < repeatLeft; i++) {
Base::Vector3d newStart(start.x - float(i)*interval,maxY,0);
Base::Vector3d newEnd(end.x - float(i)*interval,minY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
}
//atom is centre line in a set of pattern lines.
TopoDS_Edge atom = makeLine(start,end);
result.push_back(atom);
return result;
}
TopoDS_Edge DrawGeomHatch::makeLine(Base::Vector3d s, Base::Vector3d e)
{
TopoDS_Edge result;
gp_Pnt start(s.x,s.y,0.0);
gp_Pnt end(e.x,e.y,0.0);
TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(start);
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(end);
BRepBuilderAPI_MakeEdge makeEdge1(v1,v2);
result = makeEdge1.Edge();
return result;
}
void DrawGeomHatch::getParameters(void)
{
//this is probably "/build/data/Mod/TechDraw/PAT"
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
std::string defaultDir = App::Application::getResourceDir() + "Mod/TechDraw/PAT/";
std::string defaultFileName = defaultDir + "FCPAT.pat";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FilePattern",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}
QFileInfo tfi(patternFileName);
if (tfi.isReadable()) {
FilePattern.setValue(patternFileName.toUtf8().constData());
} else {
Base::Console().Error("DrawGeomHatch: PAT file: %s Not Found\n",patternFileName.toUtf8().constData());
}
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
std::string defaultNamePattern = "Diamond";
NamePattern.setValue(hGrp->GetASCII("NamePattern",defaultNamePattern.c_str()));
}
PyObject *DrawGeomHatch::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {
PythonObject = Py::Object(new DrawGeomHatchPy(this),true);
}
return Py::new_reference_to(PythonObject);
}
// Python Drawing feature ---------------------------------------------------------
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(TechDraw::DrawGeomHatchPython, TechDraw::DrawGeomHatch)
template<> const char* TechDraw::DrawGeomHatchPython::getViewProviderName(void) const {
return "TechDrawGui::ViewProviderGeomHatch";
}
/// @endcond
// explicit template instantiation
template class TechDrawExport FeaturePythonT<TechDraw::DrawGeomHatch>;
}

View File

@@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (c) 2017 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef _TechDraw_DrawGeomHatch_h_
#define _TechDraw_DrawGeomHatch_h_
# include <App/DocumentObject.h>
# include <App/FeaturePython.h>
# include <App/PropertyLinks.h>
#include <App/PropertyFile.h>
class TopoDS_Edge;
class Bnd_Box;
namespace TechDrawGeometry
{
class BaseGeom;
}
namespace TechDraw
{
class DrawViewPart;
class HatchLine;
class LineSet;
class DashSet;
class TechDrawExport DrawGeomHatch : public App::DocumentObject
{
PROPERTY_HEADER(TechDraw::DrawGeomHatch);
public:
DrawGeomHatch();
virtual ~DrawGeomHatch();
App::PropertyLinkSub Source; //the dvX & face(s) this crosshatch belongs to
App::PropertyFile FilePattern;
App::PropertyString NamePattern;
App::PropertyFloat ScalePattern;
virtual short mustExecute() const;
virtual App::DocumentObjectExecReturn *execute(void);
virtual void onChanged(const App::Property* prop);
virtual const char* getViewProviderName(void) const {
return "TechDrawGui::ViewProviderGeomHatch";
}
virtual PyObject *getPyObject(void);
DrawViewPart* getSourceView(void) const;
std::vector<LineSet> getDrawableLines(int i = 0);
static std::vector<LineSet> getDrawableLines(DrawViewPart* dvp, std::vector<LineSet> lineSets, int iface, double scale);
static std::vector<TopoDS_Edge> makeEdgeOverlay(HatchLine hl, Bnd_Box bBox, double scale);
static TopoDS_Edge makeLine(Base::Vector3d s, Base::Vector3d e);
static std::vector<HatchLine> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
protected:
void getParameters(void);
std::vector<HatchLine> getDecodedSpecsFromFile();
std::vector<LineSet> m_lineSets;
private:
};
typedef App::FeaturePythonT<DrawGeomHatch> DrawGeomHatchPython;
} //namespace TechDraw
#endif

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="DocumentObjectPy"
Name="DrawGeomHatchPy"
Twin="DrawGeomHatch"
TwinPointer="DrawGeomHatch"
Include="Mod/TechDraw/App/DrawGeomHatch.h"
Namespace="TechDraw"
FatherInclude="App/DocumentObjectPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="WandererFan" EMail="wandererfan@gmail.com" />
<UserDocu>Feature for creating and manipulating Technical Drawing GeomHatch areas</UserDocu>
</Documentation>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,32 @@
#include "PreCompiled.h"
#include "DrawGeomHatch.h"
// inclusion of the generated files (generated out of DrawGeomHatchPy.xml)
#include <Mod/TechDraw/App/DrawGeomHatchPy.h>
#include <Mod/TechDraw/App/DrawGeomHatchPy.cpp>
using namespace TechDraw;
// returns a string which represents the object e.g. when printed in python
std::string DrawGeomHatchPy::representation(void) const
{
return std::string("<DrawGeomHatch object>");
}
PyObject *DrawGeomHatchPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int DrawGeomHatchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -61,13 +61,15 @@ DrawHatch::DrawHatch(void)
ADD_PROPERTY_TYPE(Source,(0),vgroup,(App::PropertyType)(App::Prop_None),"The View + Face to be hatched");
ADD_PROPERTY_TYPE(HatchPattern ,(""),vgroup,App::Prop_None,"The hatch pattern file for this area");
ADD_PROPERTY_TYPE(HatchColor,(fcColor),vgroup,App::Prop_None,"The color of the hatch pattern");
ADD_PROPERTY_TYPE(HatchScale,(1.0),vgroup,App::Prop_None,"Hatch pattern size adjustment");
DirProjection.setStatus(App::Property::ReadOnly,true);
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Files");
std::string defaultDir = App::Application::getResourceDir() + "Mod/Drawing/patterns/";
std::string defaultFileName = defaultDir + "simple.svg";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("PatternFile",defaultFileName.c_str()));
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FileHatch",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}
@@ -84,7 +86,8 @@ DrawHatch::~DrawHatch()
void DrawHatch::onChanged(const App::Property* prop)
{
if (prop == &Source ||
prop == &HatchPattern ||
prop == &HatchPattern || //sb VP property?
prop == &HatchScale ||
prop == &HatchColor) {
if (!isRestoring()) {
DrawHatch::execute();

View File

@@ -44,6 +44,7 @@ public:
App::PropertyLinkSub Source; //the dvp & face this hatch belongs to
App::PropertyFile HatchPattern;
App::PropertyColor HatchColor;
App::PropertyFloat HatchScale;
//short mustExecute() const;

View File

@@ -66,6 +66,7 @@ const char* DrawPage::ProjectionTypeEnums[] = { "First Angle",
DrawPage::DrawPage(void)
{
static const char *group = "Page";
nowDeleting = false;
ADD_PROPERTY_TYPE(Template, (0), group, (App::PropertyType)(App::Prop_None), "Attached Template");
ADD_PROPERTY_TYPE(Views, (0), group, (App::PropertyType)(App::Prop_None), "Attached Views");
@@ -101,11 +102,13 @@ void DrawPage::onBeforeChange(const App::Property* prop)
void DrawPage::onChanged(const App::Property* prop)
{
if (prop == &Template) {
if (!isRestoring()) {
if (!isRestoring() &&
!isDeleting()) {
//TODO: reload if Template prop changes (ie different Template)
}
} else if (prop == &Views) {
if (!isRestoring()) {
if (!isRestoring() &&
!isDeleting() ) {
//TODO: reload if Views prop changes (ie adds/deletes)
}
} else if(prop == &Scale) {
@@ -130,7 +133,7 @@ void DrawPage::onChanged(const App::Property* prop)
// TODO: Also update Template graphic.
}
App::DocumentObject::onChanged(prop);
App::DocumentObject::onChanged(prop); //<<<<
}
App::DocumentObjectExecReturn *DrawPage::execute(void)
@@ -289,6 +292,10 @@ void DrawPage::onDocumentRestored()
if (part != nullptr &&
!part->hasGeometry()) {
part->execute();
// std::vector<App::DocumentObject*> parent = part->getInList();
// for (auto& p: parent) {
// p->touch();
// }
}
}
//second, make sure all the Dimensions have been executed so Measurements have References
@@ -302,3 +309,28 @@ void DrawPage::onDocumentRestored()
recompute();
App::DocumentObject::onDocumentRestored();
}
void DrawPage::unsetupObject()
{
nowDeleting = true;
// Remove the Page's views & template from document
App::Document* doc = getDocument();
std::string docName = doc->getName();
const std::vector<App::DocumentObject*> currViews = Views.getValues();
std::vector<App::DocumentObject*> emptyViews;
std::vector<App::DocumentObject*>::const_iterator it = currViews.begin();
for (; it != currViews.end(); it++) {
std::string viewName = (*it)->getNameInDocument();
Base::Interpreter().runStringArg("App.getDocument(\"%s\").removeObject(\"%s\")",
docName.c_str(), viewName.c_str());
}
Views.setValues(emptyViews);
std::string templateName = Template.getValue()->getNameInDocument();
Base::Interpreter().runStringArg("App.getDocument(\"%s\").removeObject(\"%s\")",
docName.c_str(), templateName.c_str());
Template.setValue(nullptr);
}

View File

@@ -81,14 +81,20 @@ public:
*/
double getPageHeight() const;
const char* getPageOrientation() const;
bool isDeleting(void) { return nowDeleting; }
protected:
void onBeforeChange(const App::Property* prop);
void onChanged(const App::Property* prop);
virtual void onDocumentRestored();
virtual void unsetupObject();
private:
static const char* ProjectionTypeEnums[];
bool nowDeleting;
};
} //namespace TechDraw

View File

@@ -176,7 +176,9 @@ void DrawProjGroup::onChanged(const App::Property* prop)
TechDraw::DrawPage *page = getPage();
if (!isRestoring() && page) {
if ( prop == &Views ) {
recompute();
if (!isDeleting()) {
recompute();
}
} else if (prop == &Scale) {
updateChildren(Scale.getValue());
//resetPositions();
@@ -185,7 +187,8 @@ void DrawProjGroup::onChanged(const App::Property* prop)
App::DocumentObject* sourceObj = Source.getValue();
if (sourceObj != nullptr) {
if (!hasAnchor()) {
addProjection("Front");
// if we have a Source, but no Anchor, make an anchor
Anchor.setValue(addProjection("Front"));
}
} else {
//Source has been changed to null! Why? What to do?
@@ -214,9 +217,9 @@ App::DocumentObjectExecReturn *DrawProjGroup::execute(void)
return DrawViewCollection::execute();
}
docObj = Anchor.getValue(); //must have an anchor, so create one as soon as we have a Page and Source
docObj = Anchor.getValue();
if (docObj == nullptr) {
docObj = addProjection("Front");
return DrawViewCollection::execute();
}
double newScale = Scale.getValue();
@@ -441,8 +444,6 @@ bool DrawProjGroup::hasProjection(const char *viewProjType) const
App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
{
//if this is the first Projection added, it should automatically be the Anchor/front view
// or if viewProjType == "Front" Anchor.setValue(view)
DrawProjGroupItem *view( nullptr );
if ( checkViewProjType(viewProjType) && !hasProjection(viewProjType) ) {
@@ -460,21 +461,8 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
view->Type.setValue( viewProjType );
view->Label.setValue( viewProjType );
view->Source.setValue( Source.getValue() );
if( strcmp(viewProjType,"Front") == 0 ) {
Anchor.setValue(docObj);
view->Direction.setValue(m_frameToStdDir.at("Front")); //just (Base::Vector3d(0.0,-1.0,0.0))
view->RotationVector.setValue(m_frameToStdRot.at("Front"));
} else {
//TODO: really need to check with Cube to get current dir & rot this uses initial values from table
//if (DPGI(front) and DPGI(right) exist) config = front.face + right.face
//
//else
// use start up values (m_frameToStdDir/m_frameToStdRot)
view->Direction.setValue(m_frameToStdDir.at(viewProjType));
view->RotationVector.setValue(m_frameToStdRot.at(viewProjType));
}
view->Direction.setValue(m_frameToStdDir.at(viewProjType));
view->RotationVector.setValue(m_frameToStdRot.at(viewProjType));
addView(view); //from DrawViewCollection - add to ProjGroup Views
moveToCentre();
view->recomputeFeature();
@@ -483,6 +471,7 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
return view;
}
//NOTE: projections can be deleted without using removeProjection - ie regular DocObject deletion process.
int DrawProjGroup::removeProjection(const char *viewProjType)
{
// TODO: shouldn't be able to delete "Front" unless deleting whole group
@@ -508,6 +497,7 @@ int DrawProjGroup::removeProjection(const char *viewProjType)
return -1;
}
//removes all DPGI - used when deleting DPG
int DrawProjGroup::purgeProjections()
{
while (!Views.getValues().empty()) {
@@ -803,7 +793,9 @@ TechDraw::DrawProjGroupItem* DrawProjGroup::getAnchor(void)
App::DocumentObject* docObj = Anchor.getValue();
if (docObj == nullptr) {
//explode! DPG w/o anchor
Base::Console().Error("Error - DPG::getAnchor - DPG has no Anchor!!!\n");
if (!isDeleting()) {
Base::Console().Error("Error - DPG::getAnchor - DPG has no Anchor!!!\n");
}
} else {
result = static_cast<DrawProjGroupItem*>(docObj);
}
@@ -1033,6 +1025,7 @@ void DrawProjGroup::onDocumentRestored()
}
std::string viewRot = Cube::dirToView(rotFront);
std::string config = viewDir + viewRot;
//find(config) or try/catch
try {
config = m_dirRotToConfig.at(config);
setConfig(config);

View File

@@ -140,7 +140,7 @@ double DrawProjGroupItem::getRotateAngle()
gp_Ax2 viewAxis;
Base::Vector3d x = RotationVector.getValue(); //current rotation
Base::Vector3d nx = x;
x.Normalize();
nx.Normalize();
Base::Vector3d na = Direction.getValue();
na.Normalize();
Base::Vector3d org(0.0,0.0,0.0);
@@ -160,6 +160,21 @@ double DrawProjGroupItem::getRotateAngle()
return angle;
}
void DrawProjGroupItem::unsetupObject()
{
if (getGroup() != nullptr) {
if (getGroup()->hasProjection(Type.getValueAsString()) ) {
if ((getGroup()->getAnchor() == this) &&
!getGroup()->isDeleting() ) {
Base::Console().Warning("Warning - DPG (%s/%s) may be corrupt - Anchor deleted\n",
getGroup()->getNameInDocument(),getGroup()->Label.getValue());
getGroup()->Anchor.setValue(nullptr); //this catches situation where DPGI is deleted w/o DPG::removeProjection
}
}
}
DrawViewPart::unsetupObject();
}
PyObject *DrawProjGroupItem::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {

View File

@@ -59,12 +59,8 @@ public:
App::PropertyVector RotationVector;
short mustExecute() const;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
virtual void onDocumentRestored();
// virtual App::DocumentObjectExecReturn *execute(void); // TODO: Delete me too if we take out the implementation
//@}
virtual void unsetupObject();
DrawProjGroup* getGroup(void) const;
double getRotateAngle();

View File

@@ -127,7 +127,7 @@ std::vector<TopoDS_Edge> DrawProjectSplit::getEdgesForWalker(TopoDS_Shape shape,
TechDrawGeometry::GeometryObject* DrawProjectSplit::buildGeometryObject(TopoDS_Shape shape,
const gp_Ax2& viewAxis)
{
TechDrawGeometry::GeometryObject* geometryObject = new TechDrawGeometry::GeometryObject("DrawProjectSplit");
TechDrawGeometry::GeometryObject* geometryObject = new TechDrawGeometry::GeometryObject("DrawProjectSplit",nullptr);
geometryObject->projectShape(shape,
viewAxis);

View File

@@ -277,6 +277,16 @@ std::string DrawUtil::formatVector(const Base::Vector3d& v)
return result;
}
std::string DrawUtil::formatVector(const Base::Vector2d& v)
{
std::string result;
std::stringstream builder;
builder << std::fixed << std::setprecision(3) ;
builder << " (" << v.x << "," << v.y << ") ";
result = builder.str();
return result;
}
//! compare 2 vectors for sorting - true if v1 < v2
bool DrawUtil::vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2)
{
@@ -293,7 +303,6 @@ bool DrawUtil::vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2)
return result;
}
//!convert fromPoint in coordinate system fromSystem to reference coordinate system
Base::Vector3d DrawUtil::toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint)
{

View File

@@ -36,6 +36,7 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <Base/Tools2D.h>
#include <Base/Vector3D.h>
#include <Base/Matrix.h>
@@ -59,6 +60,7 @@ class TechDrawExport DrawUtil {
static bool fpCompare(const double& d1, const double& d2);
static Base::Vector3d vertex2Vector(const TopoDS_Vertex& v);
static std::string formatVector(const Base::Vector3d& v);
static std::string formatVector(const Base::Vector2d& v);
static bool vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2);
static Base::Vector3d toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint);
static bool checkParallel(const Base::Vector3d v1, const Base::Vector3d v2);

View File

@@ -26,6 +26,8 @@
# include <sstream>
#endif
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Exception.h>
@@ -42,6 +44,7 @@ PROPERTY_SOURCE(TechDraw::DrawViewCollection, TechDraw::DrawView)
DrawViewCollection::DrawViewCollection()
{
nowDeleting = false;
static const char *group = "Drawing view";
ADD_PROPERTY_TYPE(Source ,(0), group, App::Prop_None,"Shape to view");
ADD_PROPERTY_TYPE(Views ,(0), group, App::Prop_None,"Attached Views");
@@ -165,6 +168,26 @@ void DrawViewCollection::onChanged(const App::Property* prop)
TechDraw::DrawView::onChanged(prop);
}
void DrawViewCollection::unsetupObject()
{
nowDeleting = true;
// Remove the collection's views from document
App::Document* doc = getDocument();
std::string docName = doc->getName();
const std::vector<App::DocumentObject*> currViews = Views.getValues();
std::vector<App::DocumentObject*> emptyViews;
std::vector<App::DocumentObject*>::const_iterator it = currViews.begin();
for (; it != currViews.end(); it++) {
std::string viewName = (*it)->getNameInDocument();
Base::Interpreter().runStringArg("App.getDocument(\"%s\").removeObject(\"%s\")",
docName.c_str(), viewName.c_str());
}
Views.setValues(emptyViews);
}
App::DocumentObjectExecReturn *DrawViewCollection::execute(void)
{
if (ScaleType.isValue("Page")) {

View File

@@ -50,14 +50,13 @@ public:
int addView(DrawView *view);
int removeView(DrawView *view);
void rebuildViewList(void);
bool isDeleting(void) { return nowDeleting; }
int countChildren();
/** @name methods overide Feature */
//@{
/// recalculate the Feature
virtual void onDocumentRestored();
virtual App::DocumentObjectExecReturn *execute(void);
//@}
virtual void unsetupObject();
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
@@ -67,6 +66,7 @@ public:
protected:
void onChanged(const App::Property* prop);
bool nowDeleting;
};
} //namespace TechDraw

View File

@@ -103,6 +103,7 @@ DrawViewDetail::DrawViewDetail()
ADD_PROPERTY_TYPE(Reference ,("1"),dgroup,App::Prop_None,"An identifier for this detail");
getParameters();
m_fudge = 1.1;
}
DrawViewDetail::~DrawViewDetail()
@@ -165,8 +166,7 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void)
Base::Vector3d anchor = AnchorPoint.getValue(); //this is a 2D point
anchor = Base::Vector3d(anchor.x,anchor.y, 0.0);
double radiusFudge = 1.1;
double radius = Radius.getValue() * radiusFudge;
double radius = getFudgeRadius();
Base::Vector3d dirDetail = dvp->Direction.getValue();
double scale = Scale.getValue();
gp_Ax2 viewAxis = getViewAxis(Base::Vector3d(0.0,0.0,0.0), dirDetail, false);
@@ -204,11 +204,11 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void)
BRepAlgoAPI_Common mkCommon(myShape,tool);
if (!mkCommon.IsDone()) {
Base::Console().Message("TRACE - DVD::execute - mkCommon not done\n");
Base::Console().Log("DVD::execute - mkCommon not done\n");
return new App::DocumentObjectExecReturn("DVD::execute - mkCommon not done");
}
if (mkCommon.Shape().IsNull()) {
Base::Console().Message("TRACE - DVD::execute - mkCommon.Shape is Null\n");
Base::Console().Log("DVD::execute - mkCommon.Shape is Null\n");
return new App::DocumentObjectExecReturn("DVD::execute - mkCommon.Shape is Null");
}
@@ -216,7 +216,7 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void)
TopExp_Explorer xp;
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
if (!(xp.More() == Standard_True)) {
Base::Console().Message("TRACE - DVD::execute - mkCommon.Shape is not a solid!\n");
Base::Console().Log("DVD::execute - mkCommon.Shape is not a solid!\n");
}
TopoDS_Shape detail = mkCommon.Shape();
Bnd_Box testBox;
@@ -267,6 +267,11 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void)
return App::DocumentObject::StdReturn;
}
double DrawViewDetail::getFudgeRadius()
{
return Radius.getValue() * m_fudge;
}
void DrawViewDetail::getParameters()
{
// what parameters are useful?

View File

@@ -69,12 +69,12 @@ public:
}
public:
//int getMattingStyle() const {return m_mattingStyle;}
double getFudgeRadius(void);
protected:
Base::Vector3d toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint);
void getParameters(void);
//int m_mattingStyle;
double m_fudge;
};

View File

@@ -119,6 +119,7 @@ DrawViewDimension::DrawViewDimension(void)
Rotation.setStatus(App::Property::Hidden,true);
measurement = new Measure::Measurement();
//TODO: should have better initial datumLabel position than (0,0) in the DVP?? something closer to the object being measured?
}
DrawViewDimension::~DrawViewDimension()
@@ -131,16 +132,12 @@ void DrawViewDimension::onChanged(const App::Property* prop)
{
if (!isRestoring()) {
if (prop == &MeasureType) {
// Base::Console().Message("TRACE -DVD::onChanged(MeasureType) - MeasureType: %d Measurehas3D: %d thisHas3D: %d\n",
// MeasureType.getValue(),measurement->has3DReferences(),has3DReferences());
if (MeasureType.isValue("True") && !measurement->has3DReferences()) {
Base::Console().Warning("Dimension %s missing Reference to 3D model. Must be Projected.\n", getNameInDocument());
MeasureType.setValue("Projected");
}
}
if (prop == &References3D) { //have to rebuild the Measurement object
// Base::Console().Message("TRACE -DVD::onChanged(References3D) - MeasureType: %d has3D: %d thisHas3D: %d\n",
// MeasureType.getValue(),measurement->has3DReferences(),has3DReferences());
clear3DMeasurements(); //Measurement object
if (!(References3D.getValues()).empty()) {
setAll3DMeasurement();
@@ -189,7 +186,7 @@ App::DocumentObjectExecReturn *DrawViewDimension::execute(void)
return App::DocumentObject::execute();;
}
std::string DrawViewDimension::getFormatedValue() const
std::string DrawViewDimension::getFormatedValue()
{
QString str = QString::fromUtf8(FormatSpec.getStrValue().data(),FormatSpec.getStrValue().size());
double val = std::abs(getDimValue());
@@ -230,16 +227,16 @@ std::string DrawViewDimension::getFormatedValue() const
}
double DrawViewDimension::getDimValue() const
double DrawViewDimension::getDimValue()
{
double result = 0.0;
if (!has2DReferences()) { //happens during Dimension creation
Base::Console().Message("INFO - DVD::getDimValue - Dimension has no References\n");
Base::Console().Log("INFO - DVD::getDimValue - Dimension has no References\n");
return result;
}
if (!getViewPart()->hasGeometry()) { //happens when loading saved document
Base::Console().Message("INFO - DVD::getDimValue ViewPart has no Geometry yet\n");
Base::Console().Log("INFO - DVD::getDimValue ViewPart has no Geometry yet\n");
return result;
}
@@ -273,6 +270,12 @@ double DrawViewDimension::getDimValue() const
// Projected Values
const std::vector<App::DocumentObject*> &objects = References2D.getValues();
const std::vector<std::string> &subElements = References2D.getSubValues();
if (!checkReferences2D()) {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
if ( Type.isValue("Distance") ||
Type.isValue("DistanceX") ||
Type.isValue("DistanceY") ) {
@@ -280,7 +283,14 @@ double DrawViewDimension::getDimValue() const
//TODO: Check for straight line Edge?
int idx = DrawUtil::getIndexFromName(subElements[0]);
TechDrawGeometry::BaseGeom* geom = getViewPart()->getProjEdgeByIndex(idx);
TechDrawGeometry::Generic* gen = static_cast<TechDrawGeometry::Generic*>(geom);
TechDrawGeometry::Generic* gen;
if (geom && geom->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen = static_cast<TechDrawGeometry::Generic*>(geom);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
Base::Vector2d start = gen->points[0];
Base::Vector2d end = gen->points[1];
Base::Vector2d line = end - start;
@@ -296,9 +306,23 @@ double DrawViewDimension::getDimValue() const
int idx0 = DrawUtil::getIndexFromName(subElements[0]);
int idx1 = DrawUtil::getIndexFromName(subElements[1]);
TechDrawGeometry::BaseGeom* geom0 = getViewPart()->getProjEdgeByIndex(idx0);
TechDrawGeometry::Generic* gen0;
if (geom0 && geom0->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen0 = static_cast<TechDrawGeometry::Generic*>(geom0);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
TechDrawGeometry::BaseGeom* geom1 = getViewPart()->getProjEdgeByIndex(idx1);
TechDrawGeometry::Generic* gen0 = static_cast<TechDrawGeometry::Generic*>(geom0);
TechDrawGeometry::Generic* gen1 = static_cast<TechDrawGeometry::Generic*>(geom1);
TechDrawGeometry::Generic* gen1;
if (geom1 && geom1->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen1 = static_cast<TechDrawGeometry::Generic*>(geom1);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
Base::Vector2d s0 = gen0->points[0];
Base::Vector2d e0 = gen0->points[1];
Base::Vector2d s1 = gen1->points[0];
@@ -319,7 +343,13 @@ double DrawViewDimension::getDimValue() const
int idx1 = DrawUtil::getIndexFromName(subElements[1]);
TechDrawGeometry::Vertex* v0 = getViewPart()->getProjVertexByIndex(idx0);
TechDrawGeometry::Vertex* v1 = getViewPart()->getProjVertexByIndex(idx1);
Base::Vector2d start = v0->pnt;
if ((v0 == nullptr) ||
(v1 == nullptr) ) {
Base::Console().Error("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
Base::Vector2d start = v0->pnt; //v0 != nullptr, but v0->pnt is invalid
Base::Vector2d end = v1->pnt;
Base::Vector2d line = end - start;
if (Type.isValue("Distance")) {
@@ -341,6 +371,12 @@ double DrawViewDimension::getDimValue() const
e = getViewPart()->getProjEdgeByIndex(idx1);
v = getViewPart()->getProjVertexByIndex(idx0);
}
if ((v == nullptr) ||
(e == nullptr) ) {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
Base::Vector2d nearPoint = e->nearPoint(v->pnt);
Base::Vector2d line = nearPoint - v->pnt;
if (Type.isValue("Distance")) {
@@ -355,76 +391,99 @@ double DrawViewDimension::getDimValue() const
//only 1 reference for a Radius
int idx = DrawUtil::getIndexFromName(subElements[0]);
TechDrawGeometry::BaseGeom* base = getViewPart()->getProjEdgeByIndex(idx);
TechDrawGeometry::Circle* circle = static_cast<TechDrawGeometry::Circle*> (base);
TechDrawGeometry::Circle* circle;
if( (base && base->geomType == TechDrawGeometry::GeomType::CIRCLE) ||
(base && base->geomType == TechDrawGeometry::GeomType::ARCOFCIRCLE)) {
circle = static_cast<TechDrawGeometry::Circle*> (base);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
result = circle->radius / getViewPart()->Scale.getValue(); //Projected BaseGeom is scaled for drawing
} else if(Type.isValue("Diameter")){
//only 1 reference for a Diameter
int idx = DrawUtil::getIndexFromName(subElements[0]);
TechDrawGeometry::BaseGeom* base = getViewPart()->getProjEdgeByIndex(idx);
TechDrawGeometry::Circle* circle = static_cast<TechDrawGeometry::Circle*> (base);
TechDrawGeometry::Circle* circle;
if ((base && base->geomType == TechDrawGeometry::GeomType::CIRCLE) ||
(base && base->geomType == TechDrawGeometry::GeomType::ARCOFCIRCLE)) {
circle = static_cast<TechDrawGeometry::Circle*> (base);
} else {
return result;
}
result = (circle->radius * 2.0) / getViewPart()->Scale.getValue(); //Projected BaseGeom is scaled for drawing
} else if(Type.isValue("Angle")){
// Must project lines to 2D so cannot use measurement framework this time
//Relcalculate the measurement based on references stored.
//WF: why not use projected geom in GeomObject and Vector2d.GetAngle? intersection pt & direction issues?
//TODO: do we need to distinguish inner vs outer angle? -wf
// if(subElements.size() != 2) {
// throw Base::Exception("FVD - Two references required for angle measurement");
// }
if (getRefType() != twoEdge) {
throw Base::Exception("FVD - Two edge references required for angle measurement");
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
int idx0 = DrawUtil::getIndexFromName(subElements[0]);
int idx1 = DrawUtil::getIndexFromName(subElements[1]);
auto viewPart( dynamic_cast<TechDraw::DrawViewPart *>(objects[0]) );
if( viewPart == nullptr ) {
Base::Console().Message("INFO - DVD::getDimValue - References2D not DrawViewPart\n");
return 0.0;
Base::Console().Log("INFO - DVD::getDimValue - References2D not DrawViewPart\n");
return result;
}
TechDrawGeometry::BaseGeom* edge0 = viewPart->getProjEdgeByIndex(idx0);
TechDrawGeometry::BaseGeom* edge1 = viewPart->getProjEdgeByIndex(idx1);
// Only can find angles with straight line edges
if(edge0->geomType == TechDrawGeometry::GENERIC &&
edge1->geomType == TechDrawGeometry::GENERIC) {
TechDrawGeometry::Generic *gen1 = static_cast<TechDrawGeometry::Generic *>(edge0);
TechDrawGeometry::Generic *gen2 = static_cast<TechDrawGeometry::Generic *>(edge1);
Base::Vector3d p1S(gen1->points.at(0).x, gen1->points.at(0).y, 0.);
Base::Vector3d p1E(gen1->points.at(1).x, gen1->points.at(1).y, 0.);
Base::Vector3d p2S(gen2->points.at(0).x, gen2->points.at(0).y, 0.);
Base::Vector3d p2E(gen2->points.at(1).x, gen2->points.at(1).y, 0.);
Base::Vector3d dir1 = p1E - p1S;
Base::Vector3d dir2 = p2E - p2S;
// Line Intersetion (taken from ViewProviderSketch.cpp)
double det = dir1.x*dir2.y - dir1.y*dir2.x;
if ((det > 0 ? det : -det) < 1e-10)
throw Base::Exception("Invalid selection - Det = 0");
double c1 = dir1.y*gen1->points.at(0).x - dir1.x*gen1->points.at(0).y;
double c2 = dir2.y*gen2->points.at(1).x - dir2.x*gen2->points.at(1).y;
double x = (dir1.x*c2 - dir2.x*c1)/det;
double y = (dir1.y*c2 - dir2.y*c1)/det;
// Intersection point
Base::Vector3d p0 = Base::Vector3d(x,y,0);
Base::Vector3d lPos((double) X.getValue(), (double) Y.getValue(), 0.);
//Base::Vector3d delta = lPos - p0;
// Create vectors point towards intersection always
Base::Vector3d a = -p0, b = -p0;
a += ((p1S - p0).Length() < FLT_EPSILON) ? p1E : p1S;
b += ((p2S - p0).Length() < FLT_EPSILON) ? p2E : p2S;
double angle2 = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );
result = angle2 * 180. / M_PI;
TechDrawGeometry::Generic *gen1;
TechDrawGeometry::Generic *gen2;
if (edge0 && edge0->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen1 = static_cast<TechDrawGeometry::Generic*>(edge0);
} else {
throw Base::Exception("getDimValue() - Unknown Dimension Type (2)");
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
if (edge1 && edge1->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen2 = static_cast<TechDrawGeometry::Generic*>(edge1);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
References2D.setValue(nullptr,"");
return result;
}
Base::Vector3d p1S(gen1->points.at(0).x, gen1->points.at(0).y, 0.);
Base::Vector3d p1E(gen1->points.at(1).x, gen1->points.at(1).y, 0.);
Base::Vector3d p2S(gen2->points.at(0).x, gen2->points.at(0).y, 0.);
Base::Vector3d p2E(gen2->points.at(1).x, gen2->points.at(1).y, 0.);
Base::Vector3d dir1 = p1E - p1S;
Base::Vector3d dir2 = p2E - p2S;
// Line Intersetion (taken from ViewProviderSketch.cpp)
double det = dir1.x*dir2.y - dir1.y*dir2.x;
if ((det > 0 ? det : -det) < 1e-10)
throw Base::Exception("Invalid selection - Det = 0");
double c1 = dir1.y*gen1->points.at(0).x - dir1.x*gen1->points.at(0).y;
double c2 = dir2.y*gen2->points.at(1).x - dir2.x*gen2->points.at(1).y;
double x = (dir1.x*c2 - dir2.x*c1)/det;
double y = (dir1.y*c2 - dir2.y*c1)/det;
// Intersection point
Base::Vector3d p0 = Base::Vector3d(x,y,0);
Base::Vector3d lPos((double) X.getValue(), (double) Y.getValue(), 0.);
//Base::Vector3d delta = lPos - p0;
// Create vectors point towards intersection always
Base::Vector3d a = -p0, b = -p0;
a += ((p1S - p0).Length() < FLT_EPSILON) ? p1E : p1S;
b += ((p2S - p0).Length() < FLT_EPSILON) ? p2E : p2S;
double angle2 = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );
result = angle2 * 180. / M_PI;
} else {
throw Base::Exception("getDimValue() - Unknown Dimension Type (2)");
} //endif Angle
} //endif Projected
return result;
@@ -481,6 +540,33 @@ int DrawViewDimension::getRefType2(const std::string g1, const std::string g2)
return refType;
}
//! validate 2D references - only checks if they exist, not if they are the right type
bool DrawViewDimension::checkReferences2D() const
{
bool result = true;
//const std::vector<App::DocumentObject*> &objects = References2D.getValues();
const std::vector<std::string> &subElements = References2D.getSubValues();
for (auto& s: subElements) {
int idx = DrawUtil::getIndexFromName(s);
if (DrawUtil::getGeomTypeFromName(s) == "Edge") {
TechDrawGeometry::BaseGeom* geom = getViewPart()->getProjEdgeByIndex(idx);
if (geom == nullptr) {
result = false;
break;
}
} else if (DrawUtil::getGeomTypeFromName(s) == "Vertex") {
TechDrawGeometry::Vertex* v = getViewPart()->getProjVertexByIndex(idx);
if (v == nullptr) {
result = false;
break;
}
}
}
return result;
}
//!add Dimension 3D references to measurement
void DrawViewDimension::setAll3DMeasurement()
{
@@ -535,7 +621,7 @@ double DrawViewDimension::dist2Segs(Base::Vector2d s1,
BRepExtrema_DistShapeShape extss(edge1, edge2);
if (!extss.IsDone()) {
throw Base::Exception("FVD - BRepExtrema_DistShapeShape failed");
throw Base::Exception("DVD - BRepExtrema_DistShapeShape failed");
}
int count = extss.NbSolution();
double minDist = 0.0;
@@ -548,7 +634,18 @@ double DrawViewDimension::dist2Segs(Base::Vector2d s1,
bool DrawViewDimension::has2DReferences(void) const
{
return (References2D.getSize() > 0);
bool result = false;
const std::vector<App::DocumentObject*> &objects = References2D.getValues();
const std::vector<std::string> &SubNames = References2D.getSubValues();
if (!objects.empty()) {
App::DocumentObject* testRef = objects.at(0);
if (testRef != nullptr) {
if (!SubNames.empty()) {
result = true;
}
}
}
return result;
}
bool DrawViewDimension::has3DReferences(void) const

View File

@@ -65,9 +65,6 @@ public:
App::PropertyFloat LineWidth;
//App::PropertyBool CentreLines;
//TODO: do we need a property for the actual dimension value? how else to access from Py?
//wf: expose getValue & getFormatedValue
short mustExecute() const;
bool has2DReferences(void) const;
bool has3DReferences(void) const;
@@ -85,8 +82,8 @@ public:
//return PyObject as DrawViewDimensionPy
virtual PyObject *getPyObject(void);
virtual std::string getFormatedValue() const;
virtual double getDimValue() const;
virtual std::string getFormatedValue();
virtual double getDimValue();
DrawViewPart* getViewPart() const;
virtual QRectF getRect() const { return QRectF(0,0,1,1);} //pretend dimensions always fit!
static int getRefType1(const std::string s);
@@ -94,11 +91,11 @@ public:
int getRefType() const; //Vertex-Vertex, Edge, Edge-Edge
void setAll3DMeasurement();
void clear3DMeasurements(void);
bool checkReferences2D(void) const;
protected:
void onChanged(const App::Property* prop);
virtual void onDocumentRestored();
int getIndexFromName(std::string geomName) const;
bool showUnits() const;
protected:

View File

@@ -33,6 +33,7 @@
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepLib.hxx>
#include <BRepLProp_CurveTool.hxx>
#include <BRepLProp_CLProps.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
@@ -57,18 +58,23 @@
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <GeomLib_Tool.hxx>
#endif
#include <limits>
#include <algorithm>
#include <cmath>
#include <GeomLib_Tool.hxx>
#include <App/Application.h>
#include <App/Document.h>
#include <Base/BoundBox.h>
#include <Base/Console.h>
#include <Base/Exception.h>
@@ -78,10 +84,12 @@
#include "DrawUtil.h"
#include "DrawViewSection.h"
#include "DrawProjectSplit.h"
#include "Geometry.h"
#include "GeometryObject.h"
#include "DrawViewPart.h"
#include "DrawHatch.h"
#include "DrawGeomHatch.h"
#include "EdgeWalker.h"
@@ -103,6 +111,7 @@ DrawViewPart::DrawViewPart(void) : geometryObject(0)
static const char *group = "Projection";
static const char *fgroup = "Format";
static const char *sgroup = "Show";
nowDeleting = false;
//properties that affect Geometry
ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"3D Shape to view");
@@ -145,19 +154,17 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
{
App::DocumentObject *link = Source.getValue();
if (!link) {
return new App::DocumentObjectExecReturn("FVP - No Source object linked");
return new App::DocumentObjectExecReturn("DVP - No Source object linked");
}
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
return new App::DocumentObjectExecReturn("FVP - Linked object is not a Part object");
return new App::DocumentObjectExecReturn("DVP - Linked object is not a Part object");
}
TopoDS_Shape shape = static_cast<Part::Feature*>(link)->Shape.getShape().getShape();
if (shape.IsNull()) {
return new App::DocumentObjectExecReturn("FVP - Linked shape object is empty");
return new App::DocumentObjectExecReturn("DVP - Linked shape object is empty");
}
//Base::Console().Message("TRACE - DVP::execute() - %s - %s - dir: %s\n",getNameInDocument(), Label.getValue(),DrawUtil::formatVector(Direction.getValue()).c_str());
(void) DrawView::execute(); //make sure Scale is up to date
@@ -223,7 +230,7 @@ void DrawViewPart::onChanged(const App::Property* prop)
//note: slightly different than routine with same name in DrawProjectSplit
TechDrawGeometry::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape shape, gp_Ax2 viewAxis)
{
TechDrawGeometry::GeometryObject* go = new TechDrawGeometry::GeometryObject(getNameInDocument());
TechDrawGeometry::GeometryObject* go = new TechDrawGeometry::GeometryObject(getNameInDocument(), this);
go->setIsoCount(IsoCount.getValue());
Base::Vector3d baseProjDir = Direction.getValue();
@@ -389,7 +396,6 @@ void DrawViewPart::extractFaces()
}
}
std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
{
std::vector<TechDraw::DrawHatch*> result;
@@ -403,6 +409,19 @@ std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
return result;
}
std::vector<TechDraw::DrawGeomHatch*> DrawViewPart::getGeomHatches() const
{
std::vector<TechDraw::DrawGeomHatch*> result;
std::vector<App::DocumentObject*> children = getInList();
for (std::vector<App::DocumentObject*>::iterator it = children.begin(); it != children.end(); ++it) {
if ((*it)->getTypeId().isDerivedFrom(DrawGeomHatch::getClassTypeId())) {
TechDraw::DrawGeomHatch* geom = dynamic_cast<TechDraw::DrawGeomHatch*>(*it);
result.push_back(geom);
}
}
return result;
}
const std::vector<TechDrawGeometry::Vertex *> & DrawViewPart::getVertexGeometry() const
{
return geometryObject->getVertexGeometry();
@@ -426,7 +445,11 @@ TechDrawGeometry::BaseGeom* DrawViewPart::getProjEdgeByIndex(int idx) const
Base::Console().Log("INFO - getProjEdgeByIndex(%d) - no Edge Geometry. Probably restoring?\n",idx);
return NULL;
}
return geoms[idx];
if ((unsigned)idx >= geoms.size()) {
Base::Console().Log("INFO - getProjEdgeByIndex(%d) - invalid index\n",idx);
return NULL;
}
return geoms.at(idx);
}
//! returns existing geometry of 2D Vertex(idx)
@@ -437,13 +460,20 @@ TechDrawGeometry::Vertex* DrawViewPart::getProjVertexByIndex(int idx) const
Base::Console().Log("INFO - getProjVertexByIndex(%d) - no Vertex Geometry. Probably restoring?\n",idx);
return NULL;
}
return geoms[idx];
if ((unsigned)idx >= geoms.size()) {
Base::Console().Log("INFO - getProjVertexByIndex(%d) - invalid index\n",idx);
return NULL;
}
return geoms.at(idx);
}
//this is never used!!
//! returns existing geometry of 2D Face(idx)
//version 1 Face has 1 wire
std::vector<TechDrawGeometry::BaseGeom*> DrawViewPart::getProjFaceByIndex(int /*idx*/) const
std::vector<TechDrawGeometry::BaseGeom*> DrawViewPart::getProjFaceByIndex(int idx) const
{
(void) idx;
std::vector<TechDrawGeometry::BaseGeom*> result;
const std::vector<TechDrawGeometry::Face *>& faces = getFaceGeometry();
for (auto& f:faces) {
@@ -456,6 +486,29 @@ std::vector<TechDrawGeometry::BaseGeom*> DrawViewPart::getProjFaceByIndex(int /*
return result;
}
std::vector<TopoDS_Wire> DrawViewPart::getWireForFace(int idx) const
{
// Base::Console().Message("TRACE - DVP::getWireForFace(%d)\n",idx);
std::vector<TopoDS_Wire> result;
std::vector<TopoDS_Edge> edges;
const std::vector<TechDrawGeometry::Face *>& faces = getFaceGeometry();
TechDrawGeometry::Face * ourFace = faces.at(idx);
for (auto& w:ourFace->wires) {
edges.clear();
int i = 0;
for (auto& g:w->geoms) {
edges.push_back(g->occEdge);
// DrawUtil::dumpEdge("DVP Face edge",i,g->occEdge);
i++;
}
TopoDS_Wire occwire = EdgeWalker::makeCleanWire(edges);
// BRepLib::BuildCurves3d(occwire); //probably don't need this
result.push_back(occwire);
}
// Base::Console().Message("TRACE - DVP::getWireForFace(%d) returns %d wires\n",idx,result.size());
return result;
}
Base::BoundBox3d DrawViewPart::getBoundingBox() const
{
@@ -559,12 +612,24 @@ const std::vector<TechDrawGeometry::BaseGeom *> DrawViewPart::getVisibleFaceEdg
return geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
}
//is this really the projection plane??
gp_Pln DrawViewPart::getProjPlane() const
{
Base::Vector3d plnPnt(0.0,0.0,0.0);
Base::Vector3d plnNorm = Direction.getValue();
gp_Ax2 viewAxis = getViewAxis(plnPnt,plnNorm,false);
gp_Ax3 viewAxis3(viewAxis);
return gp_Pln(viewAxis3);
}
void DrawViewPart::getRunControl()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
m_sectionEdges = hGrp->GetBool("ShowSectionEdges", 1l);
m_sectionEdges = hGrp->GetBool("ShowSectionEdges", 0l);
m_handleFaces = hGrp->GetBool("HandleFaces", 1l);
//Base::Console().Message("TRACE - DVP::getRunControl - handleFaces: %d\n",m_handleFaces);
}
bool DrawViewPart::handleFaces(void)
@@ -577,6 +642,25 @@ bool DrawViewPart::showSectionEdges(void)
return m_sectionEdges;
}
void DrawViewPart::unsetupObject()
{
nowDeleting = true;
// Remove the View's Hatches from document
App::Document* doc = getDocument();
std::string docName = doc->getName();
std::vector<TechDraw::DrawHatch*> hatches = getHatches();
std::vector<TechDraw::DrawHatch*>::iterator it = hatches.begin();
for (; it != hatches.end(); it++) {
std::string viewName = (*it)->getNameInDocument();
Base::Interpreter().runStringArg("App.getDocument(\"%s\").removeObject(\"%s\")",
docName.c_str(), viewName.c_str());
}
}
PyObject *DrawViewPart::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {

View File

@@ -37,9 +37,14 @@
#include <Base/BoundBox.h>
#include "DrawView.h"
#include "DrawProjectSplit.h"
class gp_Pnt;
class gp_Pln;
class gp_Ax2;
//class TopoDS_Edge;
//class TopoDS_Vertex;
//class TopoDS_Wire;
//class TopoDS_Shape;
namespace TechDrawGeometry
{
@@ -51,6 +56,9 @@ class Face;
namespace TechDraw {
class DrawHatch;
class DrawGeomHatch;
class DrawProjectSplit;
class DrawViewSection;
}
namespace TechDraw
@@ -91,6 +99,7 @@ public:
std::vector<TechDraw::DrawHatch*> getHatches(void) const;
std::vector<TechDraw::DrawGeomHatch*> getGeomHatches(void) const;
//TODO: are there use-cases for Python access to TechDrawGeometry???
@@ -135,12 +144,19 @@ public:
}
//return PyObject as DrawViewPartPy
virtual PyObject *getPyObject(void);
bool isDeleting(void) { return nowDeleting; }
gp_Pln getProjPlane(void) const;
virtual std::vector<TopoDS_Wire> getWireForFace(int idx) const;
protected:
TechDrawGeometry::GeometryObject *geometryObject;
Base::BoundBox3d bbox;
void onChanged(const App::Property* prop);
virtual void unsetupObject();
virtual TechDrawGeometry::GeometryObject* buildGeometryObject(TopoDS_Shape shape, gp_Ax2 viewAxis);
void extractFaces();
@@ -156,6 +172,7 @@ protected:
bool m_handleFaces;
private:
bool nowDeleting;
};

View File

@@ -46,6 +46,7 @@
#include <HLRBRep_Algo.hxx>
#include <HLRAlgo_Projector.hxx>
#include <HLRBRep_HLRToShape.hxx>
#include <ShapeAnalysis.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
@@ -63,20 +64,24 @@
# include <QFileInfo>
#include <App/Application.h>
#include <App/Document.h>
#include <App/Material.h>
#include <Base/BoundBox.h>
#include <Base/Exception.h>
#include <Base/Console.h>
#include <Base/Interpreter.h>
#include <Base/Parameter.h>
#include <Mod/Part/App/PartFeature.h>
#include "Geometry.h"
#include "GeometryObject.h"
#include "HatchLine.h"
#include "EdgeWalker.h"
#include "DrawUtil.h"
#include "DrawProjGroupItem.h"
#include "DrawProjectSplit.h"
#include "DrawGeomHatch.h"
#include "DrawViewSection.h"
using namespace TechDraw;
@@ -110,11 +115,17 @@ DrawViewSection::DrawViewSection()
SectionDirection.setEnums(SectionDirEnums);
ADD_PROPERTY_TYPE(SectionDirection,((long)0),sgroup, App::Prop_None, "Direction in Base View for this Section");
ADD_PROPERTY_TYPE(ShowCutSurface ,(true),fgroup,App::Prop_None,"Shade the cut surface");
ADD_PROPERTY_TYPE(CutSurfaceColor,(0.0,0.0,0.0),fgroup,App::Prop_None,"The color to shade the cut surface");
ADD_PROPERTY_TYPE(HatchCutSurface ,(false),fgroup,App::Prop_None,"Hatch the cut surface");
ADD_PROPERTY_TYPE(HatchPattern ,(""),fgroup,App::Prop_None,"The hatch pattern file for the cut surface");
ADD_PROPERTY_TYPE(HatchColor,(0.0,0.0,0.0),fgroup,App::Prop_None,"The color of the hatch pattern");
ADD_PROPERTY_TYPE(FileHatchPattern ,(""),fgroup,App::Prop_None,"The hatch pattern file for the cut surface");
ADD_PROPERTY_TYPE(NameGeomPattern ,(""),fgroup,App::Prop_None,"The pattern name for geometric hatching");
ADD_PROPERTY_TYPE(HatchScale,(1.0),fgroup,App::Prop_None,"Hatch pattern size adjustment");
// ADD_PROPERTY_TYPE(ShowCutSurface ,(true),fgroup,App::Prop_None,"Show/hide the cut surface");
// ADD_PROPERTY_TYPE(CutSurfaceColor,(0.0,0.0,0.0),fgroup,App::Prop_None,"The color to shade the cut surface");
// ADD_PROPERTY_TYPE(HatchCutSurface ,(false),fgroup,App::Prop_None,"Hatch the cut surface");
// ADD_PROPERTY_TYPE(FileHatchPattern ,(""),fgroup,App::Prop_None,"The hatch pattern file for the cut surface");
// ADD_PROPERTY_TYPE(NameGeomPattern ,(""),fgroup,App::Prop_None,"The pattern name for geometric hatching");
// ADD_PROPERTY_TYPE(HatchColor,(0.0,0.0,0.0),fgroup,App::Prop_None,"The color of the hatch pattern");
getParameters();
@@ -158,6 +169,23 @@ void DrawViewSection::onChanged(const App::Property* prop)
}
}
}
if (prop == &FileHatchPattern ||
prop == &NameGeomPattern ) {
if ((!FileHatchPattern.isEmpty()) &&
(!NameGeomPattern.isEmpty())) {
std::vector<HatchLine> specs =
DrawGeomHatch::getDecodedSpecsFromFile(FileHatchPattern.getValue(),NameGeomPattern.getValue());
m_lineSets.clear();
for (auto& hl: specs) {
//hl.dump("hl from section");
LineSet ls;
ls.setHatchLine(hl);
m_lineSets.push_back(ls);
}
}
}
DrawView::onChanged(prop);
}
@@ -248,10 +276,12 @@ App::DocumentObjectExecReturn *DrawViewSection::execute(void)
inputCenter,
Scale.getValue());
sectionFaceWires.clear();
TopoDS_Compound newFaces;
BRep_Builder builder;
builder.MakeCompound(newFaces);
TopExp_Explorer expl(mirroredSection, TopAbs_FACE);
int idb = 0;
for (; expl.More(); expl.Next()) {
const TopoDS_Face& face = TopoDS::Face(expl.Current());
TopoDS_Face pFace = projectFace(face,
@@ -259,8 +289,9 @@ App::DocumentObjectExecReturn *DrawViewSection::execute(void)
Direction.getValue());
if (!pFace.IsNull()) {
builder.Add(newFaces,pFace);
sectionFaceWires.push_back(ShapeAnalysis::OuterWire(pFace));
}
idb++;
}
sectionFaces = newFaces;
}
@@ -505,6 +536,25 @@ Base::Vector3d DrawViewSection::getSectionVector (const std::string sectionName)
return adjResult;
}
std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
{
std::vector<LineSet> result;
result = DrawGeomHatch::getDrawableLines(this,m_lineSets,i,HatchScale.getValue());
return result;
}
std::vector<TopoDS_Wire> DrawViewSection::getWireForFace(int idx) const
{
std::vector<TopoDS_Wire> result;
result.push_back(sectionFaceWires.at(idx));
return result;
}
void DrawViewSection::unsetupObject()
{
getBaseDVP()->touch();
}
TechDraw::DrawViewPart* DrawViewSection::getBaseDVP()
{
TechDraw::DrawViewPart* baseDVP = nullptr;
@@ -528,26 +578,20 @@ TechDraw::DrawProjGroupItem* DrawViewSection::getBaseDPGI()
void DrawViewSection::getParameters()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
App::Color cutColor = App::Color((uint32_t) hGrp->GetUnsigned("CutSurfaceColor", 0xC8C8C800));
CutSurfaceColor.setValue(cutColor);
App::Color hatchColor = App::Color((uint32_t) hGrp->GetUnsigned("SectionHatchColor", 0x00000000));
HatchColor.setValue(hatchColor);
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw");
std::string defaultDir = App::Application::getResourceDir() + "Mod/Drawing/patterns/";
std::string defaultFileName = defaultDir + "simple.svg";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("PatternFile",defaultFileName.c_str()));
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FileHatch",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}
QFileInfo tfi(patternFileName);
if (tfi.isReadable()) {
HatchPattern.setValue(patternFileName.toUtf8().constData());
FileHatchPattern.setValue(patternFileName.toUtf8().constData());
}
std::string patternName = hGrp->GetASCII("PatternName","Diamond");
NameGeomPattern.setValue(patternName);
}
// Python Drawing feature ---------------------------------------------------------

View File

@@ -45,16 +45,16 @@ class Face;
namespace TechDraw
{
class DrawProjGroupItem;
class DrawGeomHatch;
class HatchLine;
class LineSet;
class DashSet;
/** Base class of all View Features in the drawing module
*/
class TechDrawExport DrawViewSection : public DrawViewPart
{
PROPERTY_HEADER(Part::DrawViewSection);
public:
/// Constructor
DrawViewSection(void);
virtual ~DrawViewSection();
@@ -62,23 +62,16 @@ public:
App::PropertyVector SectionNormal;
App::PropertyVector SectionOrigin;
App::PropertyEnumeration SectionDirection;
App::PropertyBool ShowCutSurface;
App::PropertyColor CutSurfaceColor;
App::PropertyBool HatchCutSurface;
App::PropertyFile HatchPattern;
App::PropertyColor HatchColor;
App::PropertyFile FileHatchPattern;
App::PropertyString NameGeomPattern;
App::PropertyFloat HatchScale;
App::PropertyString SectionSymbol;
virtual short mustExecute() const;
bool isReallyInBox (const Base::Vector3d v, const Base::BoundBox3d bb) const;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
virtual App::DocumentObjectExecReturn *execute(void);
virtual void onChanged(const App::Property* prop);
//@}
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
return "TechDrawGui::ViewProviderViewSection";
}
@@ -88,11 +81,22 @@ public:
Base::Vector3d getSectionVector (const std::string sectionName);
TechDraw::DrawViewPart* getBaseDVP();
TechDraw::DrawProjGroupItem* getBaseDPGI();
virtual void unsetupObject();
virtual std::vector<TopoDS_Wire> getWireForFace(int idx) const;
TopoDS_Compound getSectionFaces() { return sectionFaces;};
std::vector<TopoDS_Wire> getSectionFaceWires(void) { return sectionFaceWires; }
std::vector<LineSet> getDrawableLines(int i = 0);
std::vector<HatchLine> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
static const char* SectionDirEnums[];
protected:
TopoDS_Compound sectionFaces;
std::vector<TopoDS_Wire> sectionFaceWires;
std::vector<LineSet> m_lineSets;
gp_Pln getSectionPlane() const;
TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& shape);

View File

@@ -35,6 +35,7 @@
#include <Base/FileInfo.h>
#include <Base/Console.h>
#include "DrawPage.h"
#include "DrawViewSymbol.h"
using namespace TechDraw;
@@ -117,29 +118,43 @@ App::DocumentObjectExecReturn *DrawViewSymbol::execute(void)
QRectF DrawViewSymbol::getRect() const
{
std::string svg = Symbol.getValue();
double w = 64.0; //must default to something
double h = 64.0;
string::const_iterator begin, end;
begin = svg.begin();
end = svg.end();
boost::match_results<std::string::const_iterator> what;
return (QRectF(0,0,w,h));
// std::string svg = Symbol.getValue();
// string::const_iterator begin, end;
// begin = svg.begin();
// end = svg.end();
// boost::match_results<std::string::const_iterator> what;
boost::regex e1 ("width=\"([0-9.]*?)[a-zA-Z]*?\"");
if (boost::regex_search(begin, end, what, e1)) {
//std::string wText = what[0].str(); //this is the whole match 'width="100"'
std::string wNum = what[1].str(); //this is just the number 100
w = std::stod(wNum);
}
boost::regex e2 ("Height=\"([0-9.]*?)[a-zA-Z]*?\"");
if (boost::regex_search(begin, end, what, e1)) {
//std::string hText = what[0].str();
std::string hNum = what[1].str();
h = std::stod(hNum);
}
return (QRectF(0,0,Scale.getValue() * w,Scale.getValue() * h));
// boost::regex e1 ("width=\"([0-9.]*?)[a-zA-Z]*?\"");
// if (boost::regex_search(begin, end, what, e1)) {
// //std::string wText = what[0].str(); //this is the whole match 'width="100"'
// std::string wNum = what[1].str(); //this is just the number 100
// w = std::stod(wNum);
// }
//
// boost::regex e2 ("height=\"([0-9.]*?)[a-zA-Z]*?\"");
// if (boost::regex_search(begin, end, what, e2)) {
// //std::string hText = what[0].str();
// std::string hNum = what[1].str();
// h = std::stod(hNum);
// }
// return (QRectF(0,0,Scale.getValue() * w,Scale.getValue() * h));
//we now have a w x h, but we don't really know what it means - px,mm,in,...
}
//!Assume all svg files fit the page and/or the user will scale manually
//see getRect() above
bool DrawViewSymbol::checkFit(TechDraw::DrawPage* p) const
{
(void)p;
bool result = true;
return result;
}
// Python Drawing feature ---------------------------------------------------------

View File

@@ -32,6 +32,7 @@
namespace TechDraw
{
class DrawPage;
class TechDrawExport DrawViewSymbol : public TechDraw::DrawView
@@ -57,6 +58,8 @@ public:
return "TechDrawGui::ViewProviderSymbol";
}
virtual QRectF getRect() const;
virtual bool checkFit(TechDraw::DrawPage* p) const override;
protected:
virtual void onChanged(const App::Property* prop);

View File

@@ -265,7 +265,7 @@ std::vector<TopoDS_Wire> EdgeWalker::getResultNoDups()
return fw;
}
//* static *//
//! make a clean wire with sorted, oriented, connected, etc edges
TopoDS_Wire EdgeWalker::makeCleanWire(std::vector<TopoDS_Edge> edges, double tol)
{

View File

@@ -175,7 +175,7 @@ public:
int findUniqueVert(TopoDS_Vertex vx, std::vector<TopoDS_Vertex> &uniqueVert);
std::vector<TopoDS_Wire> sortStrip(std::vector<TopoDS_Wire> fw, bool includeBiggest);
std::vector<TopoDS_Wire> sortWiresBySize(std::vector<TopoDS_Wire>& w, bool reverse = false);
TopoDS_Wire makeCleanWire(std::vector<TopoDS_Edge> edges, double tol = 0.10);
static TopoDS_Wire makeCleanWire(std::vector<TopoDS_Edge> edges, double tol = 0.10);
std::vector<int> getEmbeddingRowIx(int v);
std::vector<edge_t> getEmbeddingRow(int v);

View File

@@ -67,6 +67,7 @@
#include "DrawUtil.h"
#include "GeometryObject.h"
#include "DrawViewPart.h"
#include "DrawViewDetail.h"
using namespace TechDrawGeometry;
using namespace TechDraw;
@@ -77,9 +78,9 @@ struct EdgePoints {
TopoDS_Edge edge;
};
GeometryObject::GeometryObject(const string& parent) :
Scale(1.f),
GeometryObject::GeometryObject(const string& parent, TechDraw::DrawView* parentObj) :
m_parentName(parent),
m_parent(parentObj),
m_isoCount(0)
{
}
@@ -89,12 +90,6 @@ GeometryObject::~GeometryObject()
clear();
}
void GeometryObject::setScale(double value)
{
Scale = value;
}
const std::vector<BaseGeom *> GeometryObject::getVisibleFaceEdges(const bool smooth, const bool seam) const
{
std::vector<BaseGeom *> result;
@@ -157,17 +152,6 @@ void GeometryObject::projectShape(const TopoDS_Shape& input,
// Clear previous Geometry
clear();
//*******
gp_Dir x = viewAxis.XDirection();
gp_Dir y = viewAxis.YDirection();
gp_Dir z = viewAxis.Direction();
Base::Vector3d vx(x.X(),x.Y(),x.Z());
Base::Vector3d vy(y.X(),y.Y(),y.Z());
Base::Vector3d vz(z.X(),z.Y(),z.Z());
// Base::Console().Message("TRACE - GO::projectShape - %s viewAxis x: %s y: %s Z: %s\n",m_parentName.c_str(),
// DrawUtil::formatVector(vx).c_str(), DrawUtil::formatVector(vy).c_str(), DrawUtil::formatVector(vz).c_str());
//*******
auto start = chrono::high_resolution_clock::now();
Handle_HLRBRep_Algo brep_hlr = NULL;
@@ -177,7 +161,8 @@ void GeometryObject::projectShape(const TopoDS_Shape& input,
HLRAlgo_Projector projector( viewAxis );
brep_hlr->Projector(projector);
brep_hlr->Update();
brep_hlr->Hide();
brep_hlr->Hide(); //XXXX: what happens if we don't call Hide()?? and only look at VCompound?
// WF: you get back all the edges in the shape, but very fast!!
}
catch (...) {
Standard_Failure::Raise("GeometryObject::projectShape - error occurred while projecting shape");
@@ -301,6 +286,7 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
edgeGeom.push_back(base);
//add vertices of new edge if not already in list
bool skipDetail = false;
if (visible) {
BaseGeom* lastAdded = edgeGeom.back();
bool v1Add = true, v2Add = true;
@@ -310,9 +296,23 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
TechDrawGeometry::Circle* circle = dynamic_cast<TechDrawGeometry::Circle*>(lastAdded);
TechDrawGeometry::Vertex* c1 = nullptr;
if (circle) {
c1 = new TechDrawGeometry::Vertex(circle->center);
c1->isCenter = true;
c1->visible = true;
// if this is the center of a detail view, skip it
TechDraw::DrawViewDetail* detail = isParentDetail();
if (detail != nullptr) {
double scale = m_parent->Scale.getValue();
if ( ((circle->center - Base::Vector2d(0.0,0.0)).Length() < Precision::Confusion()) &&
(DrawUtil::fpCompare(circle->radius, scale * detail->getFudgeRadius())) ) {
skipDetail = true;
} else {
c1 = new TechDrawGeometry::Vertex(circle->center);
c1->isCenter = true;
c1->visible = true;
}
} else {
c1 = new TechDrawGeometry::Vertex(circle->center);
c1->isCenter = true;
c1->visible = true;
}
}
std::vector<Vertex *>::iterator itVertex = vertexGeom.begin();
@@ -323,7 +323,7 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
if ((*itVertex)->isEqual(v2,Precision::Confusion())) {
v2Add = false;
}
if (circle) {
if (circle && !skipDetail) {
if ((*itVertex)->isEqual(c1,Precision::Confusion())) {
c1Add = false;
}
@@ -343,7 +343,7 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
delete v2;
}
if (circle) {
if (circle && !skipDetail) {
if (c1Add) {
vertexGeom.push_back(c1);
c1->visible = true;
@@ -367,6 +367,18 @@ void GeometryObject::addFaceGeom(Face* f)
faceGeom.push_back(f);
}
TechDraw::DrawViewDetail* GeometryObject::isParentDetail()
{
TechDraw::DrawViewDetail* result = nullptr;
if (m_parent != nullptr) {
TechDraw::DrawViewDetail* detail = dynamic_cast<TechDraw::DrawViewDetail*>(m_parent);
if (detail != nullptr) {
result = detail;
}
}
return result;
}
bool GeometryObject::isWithinArc(double theta, double first,
double last, bool cw) const
@@ -439,16 +451,6 @@ bool GeometryObject::findVertex(Base::Vector2d v)
return found;
}
//"Top" X should == "Front" X for front = [front,rear]
//"Top" X should == "Front" X for front = [right]
//"Top" X should == "Front" -X for front = [left]
//"Top" X should == "Front" X for front = [top,bottom]
//view XAxis == anchor XAxis except
// anchor.ProjDir = (-1,0,0) then
// view XAxis == -Anchor XAxis
/// utility non-class member functions
//! gets a coordinate system that matches view system used in 3D with +Z up (or +Y up if neccessary)
//! used for individual views, but not secondary views in projection groups
@@ -464,9 +466,9 @@ gp_Ax2 TechDrawGeometry::getViewAxis(const Base::Vector3d origin,
}
Base::Vector3d cross = flipDirection;
//special cases
if (flipDirection == stdZ) {
if ((flipDirection - stdZ).Length() < Precision::Confusion()) {
cross = Base::Vector3d(1.0,0.0,0.0);
} else if (flipDirection == (stdZ * -1.0)) {
} else if ((flipDirection - (stdZ * -1.0)).Length() < Precision::Confusion()) {
cross = Base::Vector3d(1.0,0.0,0.0);
} else {
cross.Normalize();

View File

@@ -34,14 +34,20 @@
#include "Geometry.h"
namespace TechDraw
{
class DrawViewPart;
class DrawViewDetail;
class DrawView;
}
namespace TechDrawGeometry
{
class BaseGeom;
class Vector;
class Face;
class Vertex;
//! scales & mirrors a shape about a center
TopoDS_Shape TechDrawExport mirrorShape(const TopoDS_Shape &input,
@@ -66,13 +72,11 @@ class TechDrawExport GeometryObject
{
public:
/// Constructor
GeometryObject(const std::string& parent);
GeometryObject(const std::string& parent, TechDraw::DrawView* parentObj);
virtual ~GeometryObject();
void clear();
void setScale(double value);
//! Returns 2D bounding box
Base::BoundBox3d calcBoundingBox() const;
@@ -104,7 +108,7 @@ protected:
TopoDS_Shape hidIso;
void addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass category, bool visible);
TechDraw::DrawViewDetail* isParentDetail(void);
//similar function in Geometry?
/*!
@@ -120,9 +124,8 @@ protected:
bool findVertex(Base::Vector2d v);
double Scale;
std::string m_parentName;
TechDraw::DrawView* m_parent;
int m_isoCount;
};

View File

@@ -0,0 +1,242 @@
/***************************************************************************
* Copyright (c) 2017 Wandererfan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <sstream>
#include <iomanip>
#include <QFile>
#include <QFileInfo>
#include <stdexcept>
#endif
#include <TopoDS_Edge.hxx>
#include <Base/Console.h>
#include <Base/Vector3D.h>
#include "Geometry.h"
#include "DrawUtil.h"
#include "HatchLine.h"
using namespace TechDraw;
HatchLine::HatchLine()
{
init();
}
HatchLine::HatchLine(std::string& lineSpec)
{
init();
load(lineSpec);
}
HatchLine::~HatchLine()
{
}
void HatchLine::init(void)
{
m_angle = 0.0;
m_origin = Base::Vector3d(0.0,0.0,0.0);
m_interval = 1.0;
m_offset = 0.0;
}
void HatchLine::load(std::string& lineSpec)
{
std::vector<double> values = split(lineSpec);
if (values.size() < 5) {
Base::Console().Message( "HatchLine::load(%s) invalid entry in pattern\n",lineSpec.c_str() );
return;
}
m_angle = values[0];
m_origin = Base::Vector3d(values[1],values[2],0.0);
m_offset = values[3];
m_interval = values[4];
if (values.size() > 5) {
m_dashParms.insert(std::end(m_dashParms), std::begin(values) + 5, std::end(values));
}
}
std::vector<double> HatchLine::split(std::string line)
{
std::vector<double> result;
std::stringstream lineStream(line);
std::string cell;
while(std::getline(lineStream,cell, ','))
{
try {
result.push_back(std::stod(cell));
}
catch (const std::invalid_argument& ia) {
Base::Console().Warning("Invalid number in cell: %s (%s) \n",cell.c_str(),ia.what());
result.push_back(0.0);
}
}
return result;
}
void HatchLine::dump(char* title)
{
Base::Console().Message( "DUMP: %s\n",title);
Base::Console().Message( "Angle: %.3f\n", m_angle);
Base::Console().Message( "Origin: %s\n",DrawUtil::formatVector(m_origin).c_str());
Base::Console().Message( "Offset: %.3f\n",m_offset);
Base::Console().Message( "Interval: %.3f\n",m_interval);
std::stringstream ss;
for (auto& d: m_dashParms) {
ss << d << ", ";
}
ss << "end";
Base::Console().Message( "DashSpec: %s\n",ss.str().c_str());
}
//static class methods
std::vector<HatchLine> HatchLine::getSpecsForPattern(std::string& parmFile, std::string& parmName)
{
std::vector<HatchLine> result;
std::vector<std::string> lineSpecs;
std::ifstream inFile;
inFile.open (parmFile, std::ifstream::in);
if(!inFile.is_open()) {
Base::Console().Message( "Cannot open input file.\n");
return result;
}
//get all the definition lines for this pattern
bool status = findPatternStart(inFile, parmName);
if (status) {
lineSpecs = loadPatternDef(inFile);
} else {
Base::Console().Message( "Could not find pattern: %s\n",parmName.c_str() );
return result;
}
//decode definition lines into HatchLine objects
for (auto& l: lineSpecs) {
HatchLine hl(l);
result.push_back(hl);
}
return result;
}
bool HatchLine::findPatternStart(std::ifstream& inFile, std::string& parmName)
{
bool result = false;
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1);
std::string patternName;
unsigned long int commaPos;
if ((nameTag == ";") ||
(nameTag == " ") ||
(line.empty()) ) { //is cr/lf empty?
continue;
} else if (nameTag == "*") {
commaPos = line.find(",",1);
if (commaPos != std::string::npos) {
patternName = line.substr(1,commaPos-1);
} else {
patternName = line.substr(1);
}
if (patternName == parmName) {
//this is our pattern
result = true;
break;
}
}
} //endwhile
return result;
}
//get the definition lines for this pattern
std::vector<std::string> HatchLine::loadPatternDef(std::ifstream& inFile)
{
std::vector<std::string> result;
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1);
if ((nameTag == ";") ||
(nameTag == " ") ||
(line.empty()) ) { //is cr/lf empty?
continue;
} else if (nameTag == "*") {
break;
} else { //dataline
result.push_back(line);
}
}
return result;
}
std::vector<std::string> HatchLine::getPatternList(std::string& parmFile)
{
std::vector<std::string> result;
std::ifstream inFile;
inFile.open (parmFile, std::ifstream::in);
if(!inFile.is_open()) {
Base::Console().Message( "Cannot open input file.\n");
return result;
}
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1); //dupl code here
unsigned long int commaPos;
if (nameTag == "*") { //found a pattern
commaPos = line.find(",",1);
std::string patternName;
if (commaPos != std::string::npos) {
patternName = line.substr(1,commaPos-1);
} else {
patternName = line.substr(1);
}
result.push_back(patternName);
}
}
return result;
}
//********************************************************
void DashSpec::dump(char* title)
{
std::stringstream ss;
ss << title << ": " ;
for (auto& p: m_parms) {
ss << p << ", ";
}
Base::Console().Message("DUMP - DashSpec - %s\n",ss.str().c_str());
}

View File

@@ -0,0 +1,124 @@
/***************************************************************************
* Copyright (c) 2017 Wandererfan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef _TechDraw_HATCHLINE_H_
#define _TechDraw_HATCHLINE_H_
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <Base/Vector3D.h>
class TopoDS_Edge;
namespace TechDrawGeometry
{
class BaseGeom;
}
namespace TechDraw
{
class DrawViewPart;
class DrawUtil;
// HatchLine is the result of parsing a line from PAT file into accessible parameters
// e /HatchLine/PATSpecLine/
class HatchLine
{
public:
HatchLine();
HatchLine(std::string& lineSpec);
~HatchLine();
void load(std::string& lineSpec);
double getAngle(void) {return m_angle;}
Base::Vector3d getOrigin(void) {return m_origin;}
double getInterval(void) {return m_interval;}
double getOffset(void) {return m_offset;}
std::vector<double> getDashParms(void) {return m_dashParms;};
static std::vector<HatchLine> getSpecsForPattern(std::string& parmFile, std::string& parmName);
static bool findPatternStart(std::ifstream& inFile, std::string& parmName);
static std::vector<std::string> loadPatternDef(std::ifstream& inFile);
static std::vector<std::string> getPatternList(std::string& parmFile);
void dump(char* title);
private:
void init(void);
std::vector<double> split(std::string line);
//PAT line extracted tokens
double m_angle;
Base::Vector3d m_origin;
double m_interval;
double m_offset;
std::vector<double> m_dashParms; //why isn't this a DashSpec object?
};
// a LineSet is all the generated edges for 1 HatchLine for 1 Face
class LineSet
{
public:
LineSet() {}
~LineSet() {}
void setHatchLine(HatchLine s) { m_hatchLine = s; }
void setEdges(std::vector<TopoDS_Edge> e) {m_edges = e;}
void setGeoms(std::vector<TechDrawGeometry::BaseGeom*> g) {m_geoms = g;}
HatchLine getHatchLine(void) { return m_hatchLine; }
std::vector<double> getDashSpec(void) { return m_hatchLine.getDashParms();}
std::vector<TopoDS_Edge> getEdges(void) { return m_edges; }
std::vector<TechDrawGeometry::BaseGeom*> getGeoms(void) { return m_geoms; }
//void clearGeom(void);
private:
std::vector<TopoDS_Edge> m_edges;
std::vector<TechDrawGeometry::BaseGeom*> m_geoms;
HatchLine m_hatchLine;
};
class DashSpec
{
public:
DashSpec() {}
DashSpec(std::vector<double> p) { m_parms = p; }
~DashSpec() {}
double get(int i) {return m_parms.at(i); }
std::vector<double> get(void) {return m_parms;}
bool empty(void) {return m_parms.empty();}
int size(void) {return m_parms.size();}
void dump(char* title);
private:
std::vector<double> m_parms;
};
} //end namespace
#endif

View File

@@ -48,6 +48,7 @@
#include "ViewProviderSymbol.h"
#include "ViewProviderViewClip.h"
#include "ViewProviderHatch.h"
#include "ViewProviderGeomHatch.h"
#include "ViewProviderSpreadsheet.h"
#include "ViewProviderImage.h"
@@ -102,6 +103,7 @@ void TechDrawGuiExport initTechDrawGui()
TechDrawGui::ViewProviderDraft::init();
TechDrawGui::ViewProviderArch::init();
TechDrawGui::ViewProviderHatch::init();
TechDrawGui::ViewProviderGeomHatch::init();
TechDrawGui::ViewProviderSpreadsheet::init();
TechDrawGui::ViewProviderImage::init();

View File

@@ -36,6 +36,7 @@ set(TechDrawGui_MOC_HDRS
TaskLinkDim.h
DlgTemplateField.h
TaskSectionView.h
TaskGeomHatch.h
)
fc_wrap_cpp(TechDrawGui_MOC_SRCS ${TechDrawGui_MOC_HDRS})
@@ -54,6 +55,7 @@ set(TechDrawGui_UIC_SRCS
TaskLinkDim.ui
DlgTemplateField.ui
TaskSectionView.ui
TaskGeomHatch.ui
)
if(BUILD_QT5)
@@ -92,8 +94,13 @@ SET(TechDrawGui_SRCS
TaskSectionView.ui
TaskSectionView.cpp
TaskSectionView.h
TaskGeomHatch.ui
TaskGeomHatch.cpp
TaskGeomHatch.h
DrawGuiUtil.cpp
DrawGuiUtil.h
Rez.cpp
Rez.h
)
SET(TechDrawGuiView_SRCS
MDIViewPage.cpp
@@ -197,6 +204,8 @@ SET(TechDrawGuiViewProvider_SRCS
ViewProviderViewClip.h
ViewProviderHatch.cpp
ViewProviderHatch.h
ViewProviderGeomHatch.cpp
ViewProviderGeomHatch.h
ViewProviderImage.cpp
ViewProviderImage.h
)
@@ -209,6 +218,7 @@ SET(TechDrawGuiTaskDlgs_SRCS
TaskProjGroup.ui
TaskLinkDim.ui
TaskSectionView.ui
TaskGeomHatch.ui
)
SOURCE_GROUP("TaskDialogs" FILES ${TechDrawGuiTaskDlgs_SRCS})

View File

@@ -350,9 +350,12 @@ void CmdTechDrawNewViewSection::activated(int iMsg)
std::string FeatName = getUniqueObjectName("Section");
std::string SourceName = dvp->Source.getValue()->getNameInDocument();
std::string BaseName = (dObj)->getNameInDocument();
doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewSection','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",FeatName.c_str(),SourceName.c_str());
doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),(dObj)->getNameInDocument());
doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),BaseName.c_str());
doCommand(Doc,"App.activeDocument().%s.Scale = App.activeDocument().%s.Scale",FeatName.c_str(),BaseName.c_str());
doCommand(Doc,"App.activeDocument().%s.ScaleType = App.activeDocument().%s.ScaleType",FeatName.c_str(),BaseName.c_str());
doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str());
App::DocumentObject *docObj = getDocument()->getObject(FeatName.c_str());
TechDraw::DrawViewSection* dsv = dynamic_cast<TechDraw::DrawViewSection *>(docObj);
@@ -453,7 +456,7 @@ CmdTechDrawProjGroup::CmdTechDrawProjGroup()
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Projection Group");
sToolTipText = QT_TR_NOOP("Insert 2D Projections of a 3D part into the active drawing");
sToolTipText = QT_TR_NOOP("Insert multiple views of a single part into the active drawing");
sWhatsThis = "TechDraw_ProjGroup";
sStatusTip = sToolTipText;
sPixmap = "actions/techdraw-projgroup";
@@ -478,7 +481,7 @@ void CmdTechDrawProjGroup::activated(int iMsg)
Gui::WaitCursor wc;
openCommand("Create Projection Group");
std::string multiViewName = getUniqueObjectName("cView");
std::string multiViewName = getUniqueObjectName("ProjGroup");
std::string SourceName = (*shapes.begin())->getNameInDocument();
doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawProjGroup','%s')",multiViewName.c_str());
doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),multiViewName.c_str());

View File

@@ -49,12 +49,15 @@
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/Gui/QGVPage.h>
#include "DrawGuiUtil.h"
#include "MDIViewPage.h"
#include "TaskGeomHatch.h"
#include "ViewProviderGeomHatch.h"
#include "ViewProviderPage.h"
using namespace TechDrawGui;
@@ -75,8 +78,8 @@ CmdTechDrawNewHatch::CmdTechDrawNewHatch()
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert a hatched area into a view");
sToolTipText = QT_TR_NOOP("Insert a hatched area into a view");
sMenuText = QT_TR_NOOP("Hatch a Face using image file");
sToolTipText = QT_TR_NOOP("Hatch a Face using image file");
sWhatsThis = "TechDraw_NewHatch";
sStatusTip = sToolTipText;
sPixmap = "actions/techdraw-hatch";
@@ -126,6 +129,73 @@ bool CmdTechDrawNewHatch::isActive(void)
return (havePage && haveView);
}
//===========================================================================
// TechDraw_NewGeomHatch
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawNewGeomHatch);
CmdTechDrawNewGeomHatch::CmdTechDrawNewGeomHatch()
: Command("TechDraw_NewGeomHatch")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Apply geometric hatch to a Face");
sToolTipText = QT_TR_NOOP("Apply geometric hatch to a Face");
sWhatsThis = "TechDraw_NewGeomHatch";
sStatusTip = sToolTipText;
sPixmap = "actions/techdraw-geomhatch";
}
void CmdTechDrawNewGeomHatch::activated(int iMsg)
{
Q_UNUSED(iMsg);
if (!_checkSelectionHatch(this)) { //same requirements as hatch - page, DrawViewXXX, face
return;
}
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if( objFeat == nullptr ) {
return;
}
const std::vector<std::string> &subNames = selection[0].getSubNames();
TechDraw::DrawPage* page = objFeat->findParentPage();
std::string PageName = page->getNameInDocument();
std::string FeatName = getUniqueObjectName("GeomHatch");
std::stringstream featLabel;
featLabel << FeatName << "FX" << TechDraw::DrawUtil::getIndexFromName(subNames.at(0));
openCommand("Create GeomHatch");
doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawGeomHatch','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Label = '%s'",FeatName.c_str(),featLabel.str().c_str());
auto geomhatch( static_cast<TechDraw::DrawGeomHatch *>(getDocument()->getObject(FeatName.c_str())) );
geomhatch->Source.setValue(objFeat, subNames);
Gui::ViewProvider* vp = Gui::Application::Instance->getDocument(getDocument())->getViewProvider(geomhatch);
TechDrawGui::ViewProviderGeomHatch* hvp = dynamic_cast<TechDrawGui::ViewProviderGeomHatch*>(vp);
// if (!hvp) {
// dialog to fill in hatch values
Gui::Control().showDialog(new TaskDlgGeomHatch(geomhatch,hvp));
commitCommand();
//Horrible hack to force Tree update ??still required??
double x = objFeat->X.getValue();
objFeat->X.setValue(x);
getDocument()->recompute();
}
bool CmdTechDrawNewGeomHatch::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_Image
//===========================================================================
@@ -230,6 +300,7 @@ void CreateTechDrawCommandsDecorate(void)
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdTechDrawNewHatch());
rcCmdMgr.addCommand(new CmdTechDrawNewGeomHatch());
rcCmdMgr.addCommand(new CmdTechDrawImage());
rcCmdMgr.addCommand(new CmdTechDrawToggleFrame());
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,351 +7,473 @@
<x>0</x>
<y>0</y>
<width>521</width>
<height>420</height>
<height>463</height>
</rect>
</property>
<property name="windowTitle">
<string>TechDraw 2</string>
</property>
<widget class="QGroupBox" name="gbDim">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>501</width>
<height>161</height>
</rect>
</property>
<property name="title">
<string>Dimensions</string>
</property>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>471</width>
<height>125</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="1,2,1">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="cbShowUnits">
<property name="text">
<string>Show Units</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowUnits</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font Size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsbFontSize">
<property name="decimals">
<number>1</number>
</property>
<property name="value">
<double>4.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>FontSize</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefColorButton" name="colDimColor">
<property name="color">
<color>
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>Color</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Diameter Symbol</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::PrefLineEdit" name="leDiameter">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>⌀</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="prefEntry" stdset="0">
<cstring>DiameterSymbol</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>190</y>
<width>501</width>
<height>201</height>
</rect>
</property>
<property name="title">
<string>Decorations</string>
</property>
<widget class="QWidget" name="gridLayoutWidget_2">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>471</width>
<height>161</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,2,1">
<item row="0" column="2">
<widget class="Gui::PrefComboBox" name="pcbMatting">
<property name="prefEntry" stdset="0">
<cstring>MattingStyle</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>Round</string>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QGroupBox" name="gbDim">
<property name="title">
<string>Dimensions</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" columnstretch="1,2,1">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="cbShowUnits">
<property name="text">
<string>Show Units</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowUnits</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font Size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="dsbFontSize">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="value">
<double>4.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>FontSize</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefColorButton" name="colDimColor">
<property name="color">
<color>
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>Color</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Diameter Symbol</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::PrefLineEdit" name="leDiameter">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>⌀</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="prefEntry" stdset="0">
<cstring>DiameterSymbol</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</item>
<item>
<property name="text">
<string>Square</string>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Section Line Style</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Center Line Style</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Matting Style</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefColorButton" name="colCenterLine">
<property name="color">
<color>
<red>175</red>
<green>175</green>
<blue>175</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterColor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterLine</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Decorations</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,2,1">
<item row="0" column="2">
<widget class="Gui::PrefComboBox" name="pcbMatting">
<property name="prefEntry" stdset="0">
<cstring>MattingStyle</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>Round</string>
</property>
</item>
<item>
<property name="text">
<string>Square</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Section Line Style</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Center Line Style</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Matting Style</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefColorButton" name="colCenterLine">
<property name="color">
<color>
<red>175</red>
<green>175</green>
<blue>175</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterColor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterLine</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</property>
</item>
<item>
<property name="text">
<string>Sollid</string>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
</item>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::PrefComboBox" name="pcbSectionStyle">
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>SectionLine</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</property>
</item>
<item>
<property name="text">
<string>Solid</string>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Center Line Color</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Section Line Color</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="Gui::PrefColorButton" name="colSectionLine">
<property name="color">
<color>
<red>175</red>
<green>175</green>
<blue>175</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>SectionColor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Arrow Style</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="Gui::PrefComboBox" name="pcbArrow">
<property name="toolTip">
<string>Preferred arrowhead style</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="maxVisibleItems">
<number>5</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>ArrowStyle</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>0 - Filled Triangle</string>
</property>
<property name="icon">
<iconset>
<normalon>:/icons/arrowfilled.svg</normalon>
</iconset>
</property>
</item>
<item>
<property name="text">
<string>1 - Open Arrowhead</string>
</property>
<property name="icon">
<iconset>
<normalon>:/icons/arrowopen.svg</normalon>
</iconset>
</property>
</item>
<item>
<property name="text">
<string>2 - Tick</string>
</property>
<property name="icon">
<iconset>
<normalon>:/icons/arrowtick.svg</normalon>
</iconset>
</property>
</item>
<item>
<property name="text">
<string>3 - Dot</string>
</property>
<property name="icon">
<iconset>
<normalon>:/icons/arrowdot.svg</normalon>
</iconset>
</property>
</item>
<item>
<property name="text">
<string>4 - Open Circle</string>
</property>
<property name="icon">
<iconset>
<normalon>:/icons/arrowopendot.svg</normalon>
</iconset>
</property>
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_10">
<property name="toolTip">
<string>Default weight for GeomHatch lines</string>
</property>
<property name="text">
<string>Hatch Weight</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="Gui::PrefDoubleSpinBox" name="doubleSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>GeomWeight</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/PAT</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</item>
<item>
<property name="text">
<string>Sollid</string>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
</item>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::PrefComboBox" name="pcbSectionStyle">
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>SectionLine</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</property>
</item>
<item>
<property name="text">
<string>Solid</string>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Center Line Color</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Section Line Color</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="Gui::PrefColorButton" name="colSectionLine">
<property name="color">
<color>
<red>175</red>
<green>175</green>
<blue>175</blue>
</color>
</property>
<property name="prefEntry" stdset="0">
<cstring>SectionColor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
@@ -385,6 +507,8 @@
<header>Gui/PrefWidgets.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../../../../../Documents/CAD/DrawingModule/Resources/TechDraw.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -52,6 +52,7 @@ void DlgPrefsTechDraw2Imp::saveSettings()
colCenterLine->onSave();
pcbSectionStyle->onSave();
colSectionLine->onSave();
pcbArrow->onSave();
}
void DlgPrefsTechDraw2Imp::loadSettings()
@@ -65,6 +66,7 @@ void DlgPrefsTechDraw2Imp::loadSettings()
colCenterLine->onRestore();
pcbSectionStyle->onRestore();
colSectionLine->onRestore();
pcbArrow->onRestore();
}
/**

View File

@@ -38,6 +38,9 @@
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
#endif // #ifndef _PreComp_
#include <math.h>
@@ -77,6 +80,7 @@
#include <Mod/TechDraw/App/DrawViewSymbol.h>
#include <Mod/TechDraw/App/DrawViewImage.h>
#include "Rez.h"
#include "QGIDrawingTemplate.h"
#include "QGIView.h"
#include "QGIViewPart.h"
@@ -145,6 +149,12 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
m_view->scene(), SIGNAL(selectionChanged()),
this , SLOT (selectionChanged())
);
//get informed by App side about deleted DocumentObjects
App::Document* appDoc = m_vpPage->getDocument()->getDocument();
auto bnd = boost::bind(&MDIViewPage::onDeleteObject, this, _1);
connectDeletedObject = appDoc->signalDeletedObject.connect(bnd);
// A fresh page is added and we iterate through its collected children and add these to Canvas View -MLP
// if docobj is a featureviewcollection (ex orthogroup), add its child views. if there are ever children that have children,
@@ -169,8 +179,8 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
auto pageTemplate( dynamic_cast<TechDraw::DrawTemplate *>(obj) );
if( pageTemplate ) {
//make sceneRect 1 pagesize bigger in every direction
double width = pageTemplate->Width.getValue();
double height = pageTemplate->Height.getValue();
double width = Rez::guiX(pageTemplate->Width.getValue());
double height = Rez::guiX(pageTemplate->Height.getValue());
m_view->scene()->setSceneRect(QRectF(-width,-2.0 * height,3.0*width,3.0*height));
attachTemplate(pageTemplate);
viewAll();
@@ -180,6 +190,7 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
MDIViewPage::~MDIViewPage()
{
connectDeletedObject.disconnect();
}
@@ -254,8 +265,8 @@ void MDIViewPage::attachTemplate(TechDraw::DrawTemplate *obj)
QPointF MDIViewPage::getTemplateCenter(TechDraw::DrawTemplate *obj)
{
double cx = obj->Width.getValue()/2.0;
double cy = -obj->Height.getValue()/2.0;
double cx = Rez::guiX(obj->Width.getValue())/2.0;
double cy = -Rez::guiX(obj->Height.getValue())/2.0;
QPointF result(cx,cy);
return result;
}
@@ -317,7 +328,23 @@ bool MDIViewPage::attachView(App::DocumentObject *obj)
return (qview != nullptr);
}
void MDIViewPage::removeView(QGIView *view)
{
(void) m_view->removeView(view);
}
void MDIViewPage::onDeleteObject(const App::DocumentObject& obj)
{
if (obj.isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
const App::DocumentObject* objPtr = &obj;
const TechDraw::DrawView* dv = static_cast<const TechDraw::DrawView*>(objPtr);
TechDraw::DrawPage* dvPg = dv->findParentPage();
if (dvPg == m_vpPage->getDrawPage()) {
//this is a DV that is on our page
(void) m_view->removeView(dv);
}
}
}
void MDIViewPage::updateTemplate(bool forceUpdate)
{
@@ -347,10 +374,19 @@ void MDIViewPage::updateTemplate(bool forceUpdate)
void MDIViewPage::updateDrawing(bool forceUpdate)
{
// We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number (MLP)
// We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number (MLP)
// WF: this should be fixed now with onDeletedObject signal from App side?
// WF: the QGVP views list may still not be 100% reliable
// TODO: build list of QGIV's from scene everytime?
//logging counters
// int qgvpIn = 0;
// int qgvpValid = 0;
// int qgvpClean = 0;
// int dpIn = 0;
const std::vector<QGIView *> &graphicsList = m_view->getViews();
// qgvpIn = graphicsList.size();
const std::vector<App::DocumentObject*> &pageChildren = m_vpPage->getDrawPage()->Views.getValues();
// Count total # DocumentObjects in Page
unsigned int docObjCount = 0;
for(std::vector<App::DocumentObject*>::const_iterator it = pageChildren.begin(); it != pageChildren.end(); ++it) {
@@ -361,7 +397,12 @@ void MDIViewPage::updateDrawing(bool forceUpdate)
}
docObjCount += 1;
}
// dpIn = docObjCount;
//TODO: should prune QGVP.views first always, then check if view in Page missing QGIVP
// this makes assumption that = numbers mean everythign is OK, but could be double failure - 1 extra QGIV, 1 DV missing graphics!
if(graphicsList.size() < docObjCount) {
// there are more DocumentObjects than graphical representations (QGIVxxxx's)
// Find which DocumentObjects have no graphical representation (QGIVxxxx)
@@ -373,31 +414,50 @@ void MDIViewPage::updateDrawing(bool forceUpdate)
attachView(*it);
}
} else if(graphicsList.size() > docObjCount) {
// There are more graphical representations (QGIVxxxx) than DocumentObjects
// Remove the orphans
std::vector<QGIView *>::const_iterator itGraphics = graphicsList.begin();
// prune any invalid entries in QGVP.views
// TODO: revisit this mess. is it still required with onDeletedItem signal implementation?
std::vector<QGIView *> newGraphicsList;
bool fnd = false;
while(itGraphics != graphicsList.end()) {
fnd = orphanExists((*itGraphics)->getViewName(), pageChildren);
if(fnd) {
newGraphicsList.push_back(*itGraphics);
} else {
if (m_view->scene() == (*itGraphics)->scene()) {
(*itGraphics)->hide();
m_view->scene()->removeItem(*itGraphics);
} else { // this "shouldn't" happen, but it does
Base::Console().Log("ERROR - MDIViewPage::updateDrawing - %s already removed from QGraphicsScene\n",
(*itGraphics)->getViewName());
QList<QGraphicsItem *> items = m_view->scene()->items();
for (auto& v: graphicsList) { //check that everything in QGVP views is valid
for (auto& i:items) {
if (v == i) { //this one is OK
newGraphicsList.push_back(v);
break;
}
}
itGraphics++;
}
// Update the QGVPage (QGraphicsView) list of QGIVxxxx
m_view->setViews(newGraphicsList);
// qgvpValid = newGraphicsList.size();
//newGraphicsList now only contains valid QGIV's
//now prune the ones without docObjs
std::vector<QGIView *> cleanItems;
for (auto& i: newGraphicsList) {
std::string viewName = (i->data(1).toString()).toStdString();
App::DocumentObject* dObj = getAppDocument()->getObject(viewName.c_str());
if (dObj == nullptr) {
//need to remove from group/scene
QGraphicsItemGroup* grp = i->group();
if (grp) {
grp->removeFromGroup(i);
}
if (i->parentItem()) { //not top level
i->setParentItem(0);
}
if (i->scene()) {
i->scene()->removeItem(i);
}
//should delete i too to prevent leak? might be garbage pointer, though.
//add to delete list and delete outside of loop
} else {
QGIView* v = static_cast<QGIView*>(i);
cleanItems.push_back(v);
}
}
// qgvpClean = cleanItems.size();
m_view->setViews(cleanItems);
// Base::Console().Message("Log - MDIVP::updateDrawing pruning: docObjs: %d views in: %d valid views: %d views out: %d\n",
// dpIn,qgvpIn,qgvpValid, qgvpClean);
}
// Update all the QGIVxxxx
const std::vector<QGIView *> &upviews = m_view->getViews();
for(std::vector<QGIView *>::const_iterator it = upviews.begin(); it != upviews.end(); ++it) {
@@ -421,7 +481,7 @@ void MDIViewPage::redraw1View(TechDraw::DrawView* dv)
std::string dvName = dv->getNameInDocument();
const std::vector<QGIView *> &upviews = m_view->getViews();
for(std::vector<QGIView *>::const_iterator it = upviews.begin(); it != upviews.end(); ++it) {
std::string qgivName = (*it)->getViewObject()->getNameInDocument();
std::string qgivName = (*it)->getViewName();
if(dvName == qgivName) {
(*it)->updateView(true);
}
@@ -457,7 +517,7 @@ bool MDIViewPage::hasQView(App::DocumentObject *obj)
while(qview != views.end()) {
// Unsure if we can compare pointers so rely on name
if(strcmp((*qview)->getViewObject()->getNameInDocument(), obj->getNameInDocument()) == 0) {
if(strcmp((*qview)->getViewName(), obj->getNameInDocument()) == 0) {
return true;
}
qview++;
@@ -731,8 +791,8 @@ void MDIViewPage::print(QPrinter* printer)
double width = 0.0;
double height = 0.0;
if( pageTemplate ) {
width = pageTemplate->Width.getValue();
height = pageTemplate->Height.getValue();
width = Rez::guiX(pageTemplate->Width.getValue());
height = Rez::guiX(pageTemplate->Height.getValue());
}
QRectF sourceRect(0.0,-height,width,height);

View File

@@ -65,7 +65,8 @@ public:
void attachTemplate(TechDraw::DrawTemplate *obj);
void updateTemplate(bool force = false);
void updateDrawing(bool force = false);
void removeView(QGIView *view);
bool onMsg(const char* pMsg,const char** ppReturn);
bool onHasMsg(const char* pMsg) const;
void onRelabel(Gui::Document *pDoc);
@@ -110,6 +111,11 @@ protected:
QPrinter::PaperSize getPaperSize(int w, int h) const;
void setDimensionGroups(void);
void showStatusMsg(const char* s1, const char* s2, const char* s3) const;
void onDeleteObject(const App::DocumentObject& obj);
typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection;
Connection connectDeletedObject;
private:
QAction *m_nativeAction;

View File

@@ -40,6 +40,7 @@
#include <qmath.h>
#include <QRectF>
#include "Rez.h"
#include "QGCustomLabel.h"
using namespace TechDrawGui;
@@ -75,5 +76,24 @@ void QGCustomLabel::centerAt(double cX, double cY)
void QGCustomLabel::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
//see QGCustomText for explanation of this code
double dppt = 3.53;
double svgMagicX = Rez::guiX(8.0);
double svgMagicY = Rez::guiX(12.0);
double svgMagicYoffset = Rez::guiX(3.0);
double fontSize = Rez::appX(font().pointSizeF());
double ty = svgMagicY + (svgMagicYoffset*fontSize)/dppt;
QPointF svgMove(-svgMagicX/dppt,ty);
QPaintDevice* hw = painter->device();
QSvgGenerator* svg = dynamic_cast<QSvgGenerator*>(hw);
if (svg) {
painter->scale(Rez::appX(dppt),Rez::appX(dppt));
painter->translate(svgMove);
} else {
painter->scale(1.0,1.0);
}
QGraphicsTextItem::paint (painter, &myOption, widget);
}

View File

@@ -54,6 +54,6 @@ private:
};
} // namespace MDIViewPageGui
}
#endif // DRAWINGGUI_QGCUSTOMLABEL_H

View File

@@ -40,6 +40,7 @@
#include <qmath.h>
#include <QRectF>
#include "Rez.h"
#include "QGIView.h"
#include "QGCustomText.h"
@@ -124,28 +125,27 @@ void QGCustomText::paint ( QPainter * painter, const QStyleOptionGraphicsItem *
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
//svg text is much larger than screen text. scene units(mm) vs points.
//svg text is much larger than screen text. scene units(mm or 0.1mm in hirez) vs points.
//need to scale text if going to svg.
//TODO: magic translation happens? approx: right ~8mm down: 12mm + (3mm per mm of text height)
//TODO: magic translation happens. why? approx: right ~8mm down: 12mm + (3mm per mm of text height)
//SVG transform matrix translation values are different for same font size + different fonts (Sans vs Ubuntu vs Arial)???
// scale values are same for same font size + different fonts.
//double svgScale = 2.835; //72dpi/(25.4mm/in)
//double svgScale = 3.84; //96dpi/(25mm/in)
//double svgScale = 3.6; //90dpi/(25mm/in) more/less CSS standard?
double svgScale = 2.88; //72dpi/(25mm/in) Qt logicalDpiY() is int
double svgMagicX = 8.0;
//double svgMagicY = 7.5; //idk
double fontSize = font().pointSizeF();
//double ty = (12.0/svgScale + 3.0*fontSize/svgScale) + (svgMagicY/svgScale);
double ty = (12.0/svgScale + 3.0*fontSize/svgScale);
QPointF svgMove(-svgMagicX/svgScale,-ty);
//calculate dots/mm
//in hirez - say factor = 10, we have 10 dpmm in scene space.
// so 254dpi / 72pts/in => 3.53 dppt
double dpmm = 3.53; //dots/pt
double svgMagicX = Rez::guiX(8.0); //8mm -> 80 gui dots
double svgMagicY = Rez::guiX(12.0);
double svgMagicYoffset = Rez::guiX(3.0); // 3mm per mm of font size => 30gunits / mm of font size
double fontSize = Rez::appX(font().pointSizeF()); //gui pts 4mm text * 10 scunits/mm = size 40 text but still only 4mm
double ty = svgMagicY + (svgMagicYoffset*fontSize)/dpmm;
// 12mm (in gunits) + [3mm (in gunits) * (# of mm)]/ [dots per mm] works out to dots?
QPointF svgMove(-svgMagicX/dpmm,ty);
QPaintDevice* hw = painter->device();
//QPaintDeviceMetrics hwm(hw);
//QPrinter* pr = dynamic_cast<QPrinter*>(hw); //printer does not rescale vs screen?
QSvgGenerator* svg = dynamic_cast<QSvgGenerator*>(hw);
if (svg) {
painter->scale(svgScale,svgScale);
painter->scale(Rez::appX(dpmm),Rez::appX(dpmm));
painter->translate(svgMove);
} else {
painter->scale(1.0,1.0);

View File

@@ -32,6 +32,11 @@
#include <QPainter>
#endif
#include <App/Application.h>
#include <Base/Parameter.h>
#include <Base/Console.h>
#include "Rez.h"
#include "QGIArrow.h"
using namespace TechDrawGui;
@@ -56,39 +61,102 @@ void QGIArrow::flip(bool state) {
}
void QGIArrow::draw() {
// the center is the end point on a dimension
QPainterPath path;
//QPen pen(Qt::black);
//pen.setWidth(1);
//QBrush brush(Qt::black);
//setPen(pen);
//setBrush(brush);
float length = -m_size; //TODO: Arrow heads sb preference? size & type?
if(isFlipped)
length *= -1;
path.moveTo(QPointF(0.,0.));
path.lineTo(QPointF(length,-0.6));
path.lineTo(QPointF(length, 0.6));
path.closeSubpath();
// path.moveTo(QPointF(-1,1));
// path.lineTo(QPointF(1,-1));
if (m_style == 0) {
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //"arrow l/w sb 3/1" ??
} else if (m_style == 1) {
path = makeOpenArrow(m_size,m_size/3.0,isFlipped); //broad arrow?
} else if (m_style == 2) {
path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped); //big enough?
} else if (m_style == 3) {
path = makeDot(m_size/2.0,m_size/2.0,isFlipped);
} else if (m_style == 4) {
path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped);
} else {
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //sb a question mark or ???
}
setPath(path);
}
void QGIArrow::setSize(double s)
{
m_size = s;
//???
}
void QGIArrow::setStyle(int s)
QPainterPath QGIArrow::makeFilledTriangle(double length, double width, bool flipped)
{
m_style = s;
//???
//(0,0) is tip of arrow
if (!flipped) {
length *= -1;
}
QPainterPath path;
path.moveTo(QPointF(0.,0.));
path.lineTo(QPointF(Rez::guiX(length),Rez::guiX(-width)));
path.lineTo(QPointF(Rez::guiX(length),Rez::guiX(width)));
path.closeSubpath();
m_fill = Qt::SolidPattern;
return path;
}
QPainterPath QGIArrow::makeOpenArrow(double length, double width, bool flipped)
{
//(0,0) is tip of arrow
if (!flipped) {
length *= -1;
}
QPainterPath path;
path.moveTo(QPointF(Rez::guiX(length),Rez::guiX(-width)));
path.lineTo(QPointF(0.,0.));
path.lineTo(QPointF(Rez::guiX(length),Rez::guiX(width)));
m_fill = Qt::NoBrush;
return path;
}
QPainterPath QGIArrow::makeHashMark(double length, double width, bool flipped) //Arch tick
{
double adjWidth = 1.0;
//(0,0) is tip of arrow
if (!flipped) {
length *= -1;
adjWidth *= -1;
}
QPainterPath path;
path.moveTo(QPointF(Rez::guiX(length),Rez::guiX(adjWidth * (-width))));
path.lineTo(QPointF(Rez::guiX(-length),Rez::guiX(adjWidth * width)));
m_fill = Qt::NoBrush;
return path;
}
QPainterPath QGIArrow::makeDot(double length, double width, bool flipped) //closed dot
{
Q_UNUSED(flipped);
QPainterPath path;
path.moveTo(0.0,0.0); ////(0,0) is Center of dot
path.addEllipse(Rez::guiX(-length/2.0), Rez::guiX(-width/2.0), Rez::guiX(length), Rez::guiX(width));
m_fill = Qt::SolidPattern;
return path;
}
QPainterPath QGIArrow::makeOpenDot(double length, double width, bool flipped)
{
Q_UNUSED(flipped);
QPainterPath path;
path.moveTo(0.0,0.0); ////(0,0) is Center of dot
path.addEllipse(Rez::guiX(-length/2.0), Rez::guiX(-width/2.0), Rez::guiX(length), Rez::guiX(width));
m_fill = Qt::NoBrush;
return path;
}
int QGIArrow::getPrefArrowStyle()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter().
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Decorations");
int style = hGrp->GetInt("ArrowStyle", 0);
return style;
}
void QGIArrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
@@ -96,6 +164,7 @@ void QGIArrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
setPen(m_pen);
m_brush.setColor(m_colCurrent);
m_brush.setStyle(m_fill);
setBrush(m_brush);

View File

@@ -44,18 +44,22 @@ public:
public:
void draw();
//void setHighlighted(bool state);
void flip(bool state);
double getSize() { return m_size; }
void setSize(double s);
int getStyle() { return m_style; }
void setStyle(int s);
//QPainterPath shape() const;
void setStyle(int s) { m_style = s; }
static int getPrefArrowStyle();
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
protected:
//QVariant itemChange(GraphicsItemChange change, const QVariant &value);
QPainterPath makeFilledTriangle(double length, double width, bool flipped);
QPainterPath makeOpenArrow(double length, double width, bool flipped);
QPainterPath makeHashMark(double length, double width, bool flipped);
QPainterPath makeDot(double length, double width, bool flipped);
QPainterPath makeOpenDot(double length, double width, bool flipped);
private:
QBrush m_brush;
Qt::BrushStyle m_fill;
@@ -64,6 +68,6 @@ private:
bool isFlipped;
};
} // namespace MDIViewPageGui
}
#endif // DRAWINGGUI_QGRAPHICSITEMARROW_H

View File

@@ -31,6 +31,9 @@
#include <QPainterPathStroker>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QBitmap>
#include <QFile>
#include <QFileInfo>
#endif
#include <QFile>
@@ -45,11 +48,15 @@
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "Rez.h"
#include "QGCustomSvg.h"
#include "QGCustomRect.h"
#include "QGIFace.h"
using namespace TechDrawGui;
using namespace TechDraw;
QGIFace::QGIFace(int index) :
projIndex(index),
@@ -57,15 +64,21 @@ QGIFace::QGIFace(int index) :
m_styleDef(Qt::SolidPattern),
m_styleSelect(Qt::SolidPattern)
{
setFillMode(NoFill);
isHatched(false);
setFlag(QGraphicsItem::ItemClipsChildrenToShape,true);
//setFiltersChildEvents(true);
//setStyle(Qt::NoPen); //don't draw face lines, just fill
//setStyle(Qt::NoPen); //don't draw face lines, just fill for debugging
setStyle(Qt::DashLine);
m_styleNormal = m_styleDef;
m_fillStyle = m_styleDef;
m_colNormalFill = m_colDefFill;
m_geomColor = QColor(Qt::black);
setLineWeight(0.5); //0 = cosmetic
setPrettyNormal();
m_texture = nullptr; //empty texture
m_svg = new QGCustomSvg();
@@ -73,6 +86,7 @@ QGIFace::QGIFace(int index) :
m_rect->setParentItem(this);
m_svgCol = SVGCOLDEFAULT;
m_fillScale = 1.0;
}
QGIFace::~QGIFace()
@@ -80,34 +94,83 @@ QGIFace::~QGIFace()
//nothing to do. every item is a child of QGIFace & will get removed/deleted when QGIF is deleted
}
void QGIFace::draw()
{
setPath(m_outline); //Face boundary
if (isHatched()) {
if (m_mode == GeomHatchFill) { //crosshatch
if (!m_geomHatchPaths.empty()) { //surrogate for LineSets.empty
m_brush.setTexture(nullptr);
m_fillStyle = m_styleDef;
m_styleNormal = m_fillStyle;
int pathNo = 0;
for (auto& pp: m_geomHatchPaths) {
QGraphicsPathItem* fillItem = m_fillItems.at(pathNo);
fillItem->setPath(pp);
QPen geomPen = setGeomPen(pathNo);
fillItem->setPen(geomPen);
pathNo++;
}
}
} else if ((m_mode == FromFile) ||
(m_mode == SvgFill) ||
(m_mode == BitmapFill)) {
QFileInfo hfi(QString::fromUtf8(m_fileSpec.data(),m_fileSpec.size()));
if (hfi.isReadable()) {
QString ext = hfi.suffix();
if (ext.toUpper() == QString::fromUtf8("SVG")) {
setFillMode(SvgFill);
m_brush.setTexture(nullptr);
m_fillStyle = m_styleDef;
m_styleNormal = m_fillStyle;
loadSvgHatch(m_fileSpec);
buildSvgHatch();
toggleSvg(true);
} else if ((ext.toUpper() == QString::fromUtf8("JPG")) ||
(ext.toUpper() == QString::fromUtf8("PNG")) ||
(ext.toUpper() == QString::fromUtf8("JPEG")) ||
(ext.toUpper() == QString::fromUtf8("BMP")) ) {
setFillMode(BitmapFill);
toggleSvg(false);
m_fillStyle = Qt::TexturePattern;
m_texture = textureFromBitmap(m_fileSpec);
m_brush.setTexture(m_texture);
}
}
}
}
show();
}
void QGIFace::setPrettyNormal() {
m_fillStyle = m_styleNormal;
m_fillColor = m_colNormalFill;
if (isHatched() &&
(m_mode == BitmapFill) ) { //hatch with bitmap fill
m_fillStyle = Qt::TexturePattern;
m_brush.setTexture(m_texture);
} else {
m_fillStyle = m_styleNormal;
m_brush.setTexture(nullptr);
m_brush.setStyle(m_fillStyle);
m_fillColor = m_colNormalFill;
}
QGIPrimPath::setPrettyNormal();
}
void QGIFace::setPrettyPre() {
m_brush.setTexture(nullptr);
m_fillStyle = m_styleSelect;
m_fillColor = getPreColor();
QGIPrimPath::setPrettyPre();
}
void QGIFace::setPrettySel() {
m_brush.setTexture(nullptr);
m_fillStyle = m_styleSelect;
m_fillColor = getSelectColor();
QGIPrimPath::setPrettySel();
}
void QGIFace::setFill(QColor c, Qt::BrushStyle s) {
m_colNormalFill = c;
m_styleNormal = s;
}
void QGIFace::setFill(QBrush b) {
m_colNormalFill = b.color();
m_styleNormal = b.style();
}
void QGIFace::setDrawEdges(bool b) {
if (b) {
setStyle(Qt::DashLine);
@@ -116,14 +179,14 @@ void QGIFace::setDrawEdges(bool b) {
}
}
void QGIFace::resetFill() {
m_colNormalFill = m_colDefFill;
m_styleNormal = m_styleDef;
}
void QGIFace::setHatch(std::string fileSpec)
void QGIFace::setHatchFile(std::string fileSpec)
{
QString qfs(QString::fromStdString(fileSpec));
m_fileSpec = fileSpec;
}
void QGIFace::loadSvgHatch(std::string fileSpec)
{
QString qfs(QString::fromUtf8(fileSpec.data(),fileSpec.size()));
QFile f(qfs);
if (!f.open(QFile::ReadOnly | QFile::Text)) {
Base::Console().Error("QGIFace could not read %s\n",fileSpec.c_str());
@@ -134,29 +197,112 @@ void QGIFace::setHatch(std::string fileSpec)
Base::Console().Error("Error - Could not load hatch into SVG renderer for %s\n", fileSpec.c_str());
return;
}
buildHatch();
}
void QGIFace::setPath(const QPainterPath & path)
void QGIFace::setFillMode(QGIFace::fillMode m)
{
QGraphicsPathItem::setPath(path);
if (!m_svgXML.isEmpty()) {
buildHatch();
m_mode = m;
if ((m_mode == NoFill) ||
(m_mode == PlainFill)) {
isHatched(false);
} else {
isHatched(true);
}
}
void QGIFace::buildHatch()
void QGIFace::setOutline(const QPainterPath & path)
{
m_styleNormal = Qt::NoBrush;
double w = boundingRect().width();
double h = boundingRect().height();
QRectF r = boundingRect();
m_outline = path;
}
void QGIFace::clearLineSets(void)
{
m_geomHatchPaths.clear();
m_dashSpecs.clear();
clearFillItems();
}
//each line set needs a painterpath, a dashspec and a QGPItem to show them
void QGIFace::addLineSet(QPainterPath pp, std::vector<double> dp)
{
m_geomHatchPaths.push_back(pp);
m_dashSpecs.push_back(DashSpec(dp));
addFillItem();
}
QGraphicsPathItem* QGIFace::addFillItem()
{
QGraphicsPathItem* fillItem = new QGraphicsPathItem();
fillItem->setParentItem(this);
m_fillItems.push_back(fillItem);
return fillItem;
}
void QGIFace::clearFillItems(void)
{
for (auto& f: m_fillItems) {
f->setParentItem(nullptr);
this->scene()->removeItem(f);
delete f;
}
}
//convert from PAT style "-1,0,-1,+1" to Qt style "mark,space,mark,space"
QVector<qreal> QGIFace::decodeDashSpec(DashSpec patDash)
{
//Rez::guiX(something)?
double dotLength = 3.0;
double unitLength = 6.0;
// double penWidth = m_geomWeight; //mark, space and dot lengths are to be in terms of penWidth(Qt) or mm(PAT)??
// //if we want it in terms of mm, we need to divide by penWidth?
// double minPen = 0.01; //avoid trouble with cosmetic pen (zero width)
std::vector<double> result;
std::string prim;
for (auto& d: patDash.get()) {
double strokeLength;
if (DrawUtil::fpCompare(d,0.0)) { //pat dot
strokeLength = dotLength;
} else if (Rez::guiX(d) < 0) { //pat space
strokeLength = fabs(Rez::guiX(d)) * unitLength;
} else { //pat dash
strokeLength = Rez::guiX(d) * unitLength;
}
result.push_back(strokeLength);
}
return QVector<qreal>::fromStdVector( result );
}
QPen QGIFace::setGeomPen(int i)
{
//m_dashSpecs[i].dump("spec test");
DashSpec ourSpec = m_dashSpecs.at(i);
//ourSpec.dump("our spec");
QPen result;
result.setWidthF(Rez::guiX(m_geomWeight)); //Rez::guiX() ?? line weights are in mm?
result.setColor(m_geomColor);
if (ourSpec.empty()) {
result.setStyle(Qt::SolidLine);
} else {
result.setStyle(Qt::CustomDashLine);
result.setDashPattern(decodeDashSpec(ourSpec));
}
return result;
}
void QGIFace::buildSvgHatch()
{
double wTile = SVGSIZEW * m_fillScale;
double hTile = SVGSIZEH * m_fillScale;
double w = m_outline.boundingRect().width();
double h = m_outline.boundingRect().height();
QRectF r = m_outline.boundingRect();
QPointF fCenter = r.center();
double nw = ceil(w / SVGSIZEW);
double nh = ceil(h / SVGSIZEH);
w = nw * SVGSIZEW;
h = nh * SVGSIZEW;
double nw = ceil(w / wTile);
double nh = ceil(h / hTile);
w = nw * wTile;
h = nh * hTile;
m_rect->setRect(0.,0.,w,-h);
m_rect->centerAt(fCenter);
r = m_rect->rect();
@@ -167,20 +313,46 @@ void QGIFace::buildHatch()
for (int iw = 0; iw < int(nw); iw++) {
for (int ih = 0; ih < int(nh); ih++) {
QGCustomSvg* tile = new QGCustomSvg();
tile->setScale(m_fillScale);
if (tile->load(&colorXML)) {
tile->setParentItem(m_rect);
tile->setPos(iw*SVGSIZEW,-h + ih*SVGSIZEH);
tile->setPos(iw*wTile,-h + ih*hTile);
}
}
}
}
//c is a CSS color ie "#000000"
//set hatch color before building hatch
void QGIFace::setHatchColor(std::string c)
void QGIFace::clearSvg()
{
m_svgCol = c;
toggleSvg(false);
}
//this isn't used currently
QPixmap QGIFace::textureFromSvg(std::string fileSpec)
{
QPixmap result;
QString qs(QString::fromStdString(fileSpec));
QFileInfo ffi(qs);
if (ffi.isReadable()) {
QSvgRenderer renderer(qs);
QPixmap pixMap(renderer.defaultSize());
pixMap.fill(Qt::white); //try Qt::transparent?
QPainter painter(&pixMap);
renderer.render(&painter); //svg texture -> bitmap
result = pixMap.scaled(m_fillScale,m_fillScale);
} //else return empty pixmap
return result;
}
void QGIFace::setHatchColor(App::Color c)
{
m_svgCol = c.asCSSString();
m_geomColor = c.asValue<QColor>();
}
void QGIFace::setHatchScale(double s)
{
m_fillScale = s;
}
//QtSvg does not handle clipping, so we must be able to turn the hatching on/off
@@ -194,6 +366,39 @@ void QGIFace::toggleSvg(bool b)
update();
}
QPixmap QGIFace::textureFromBitmap(std::string fileSpec)
{
QPixmap pix;
QString qs = QString::fromUtf8(fileSpec.data(),fileSpec.size());
QFileInfo ffi(qs);
if (ffi.isReadable()) {
QImage img = QImage(qs);
img = img.scaled(Rez::guiX(m_fillScale),Rez::guiX(m_fillScale));
pix = QPixmap::fromImage(img);
}
return pix;
}
void QGIFace::setFill(QColor c, Qt::BrushStyle s) {
m_colNormalFill = c;
m_styleNormal = s;
}
void QGIFace::setFill(QBrush b) {
m_colNormalFill = b.color();
m_styleNormal = b.style();
}
void QGIFace::resetFill() {
m_colNormalFill = m_colDefFill;
m_styleNormal = m_styleDef;
}
void QGIFace::setLineWeight(double w) {
m_geomWeight = w;
}
QRectF QGIFace::boundingRect() const
{
return shape().controlPointRect();
@@ -213,3 +418,4 @@ void QGIFace::paint ( QPainter * painter, const QStyleOptionGraphicsItem * optio
setBrush(m_brush);
QGIPrimPath::paint (painter, &myOption, widget);
}

View File

@@ -27,9 +27,15 @@
#include <QGraphicsItem>
#include <QSvgRenderer>
#include <QByteArray>
#include <QBrush>
#include <QPixmap>
#include <Mod/TechDraw/App/HatchLine.h>
#include "QGIPrimPath.h"
using namespace TechDraw;
namespace TechDrawGui
{
class QGCustomSvg;
@@ -53,30 +59,77 @@ public:
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
public:
enum fillMode {
NoFill,
FromFile,
SvgFill,
BitmapFill,
GeomHatchFill,
PlainFill
};
int getProjIndex() const { return projIndex; }
void draw();
void setPrettyNormal();
void setPrettyPre();
void setPrettySel();
void setDrawEdges(bool b);
virtual void setOutline(const QPainterPath& path);
//shared fill parms
void isHatched(bool s) {m_isHatched = s; }
bool isHatched(void) {return m_isHatched;}
void setFillMode(fillMode m);
//plain color fill parms
void setFill(QColor c, Qt::BrushStyle s);
void setFill(QBrush b);
void setHatch(std::string fileSpec);
void resetFill(void);
void setPath(const QPainterPath & path);
void buildHatch(void);
void setHatchColor(std::string c);
void setDrawEdges(bool b);
void toggleSvg(bool b);
void resetFill();
protected:
bool load(QByteArray *svgBytes);
//general hatch parms & methods
void setHatchColor(App::Color c);
void setHatchScale(double s);
//svg fill parms & methods
void setHatchFile(std::string fileSpec);
void loadSvgHatch(std::string fileSpec);
void buildSvgHatch(void);
void toggleSvg(bool b);
void clearSvg(void);
//PAT fill parms & methods
void setGeomHatchWeight(double w) { m_geomWeight = w; }
void clearLineSets(void);
void addLineSet(QPainterPath pp, std::vector<double> dp);
QGraphicsPathItem* addFillItem();
void clearFillItems(void);
void setLineWeight(double w);
//bitmap texture fill parms method
QPixmap textureFromBitmap(std::string fileSpec);
QPixmap textureFromSvg(std::string fillSpec);
protected:
int projIndex; //index of face in Projection. -1 for SectionFace.
QGCustomRect *m_rect;
QGCustomSvg *m_svg;
QByteArray m_svgXML;
std::string m_svgCol;
std::string m_fileSpec; //for svg & bitmaps
double m_fillScale;
bool m_isHatched;
QGIFace::fillMode m_mode;
QPen setGeomPen(int i);
QVector<qreal> decodeDashSpec(DashSpec d);
std::vector<QGraphicsPathItem*> m_fillItems;
std::vector<QPainterPath> m_geomHatchPaths; // 0/1 dashspec per hatchpath
std::vector<DashSpec> m_dashSpecs;
private:
QBrush m_brush;
@@ -88,6 +141,15 @@ private:
Qt::BrushStyle m_styleDef; //default Normal fill style
Qt::BrushStyle m_styleNormal; //current Normal fill style
Qt::BrushStyle m_styleSelect; //Select/preSelect fill style
QPixmap m_texture; //
QPainterPath m_outline; //
QPainterPath m_geomhatch; //crosshatch fill lines
QColor m_geomColor; //color for crosshatch lines
double m_geomWeight; //lineweight for crosshatch lines
};
}

View File

@@ -41,6 +41,7 @@
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include "Rez.h"
#include "QGIProjGroup.h"
using namespace TechDrawGui;
@@ -180,9 +181,9 @@ void QGIProjGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
Gui::Command::openCommand("Drag Projection Group");
//TODO: See if these commands actually handle the horizontal/vertical constraints properly...
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.X = %f",
getViewObject()->getNameInDocument(), x());
getViewName(), Rez::appX(x()));
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Y = %f",
getViewObject()->getNameInDocument(), getY());// inverts Y
getViewName(), Rez::appX(getY()));// inverts Y
Gui::Command::commitCommand();
//Gui::Command::updateActive();
}

View File

@@ -40,6 +40,7 @@
#include <Mod/TechDraw/App/Geometry.h>
#include <Mod/TechDraw/App/DrawSVGTemplate.h>
#include "Rez.h"
#include "ZVALUE.h"
#include "TemplateTextField.h"
#include "QGISVGTemplate.h"
@@ -100,15 +101,15 @@ void QGISVGTemplate::load(const QString &fileName)
firstTime = false;
}
//This is probably first time only logic too.
//convert from pixels or mm or inches in svg file to mm page size
TechDraw::DrawSVGTemplate *tmplte = getSVGTemplate();
double xaspect, yaspect;
xaspect = tmplte->getWidth() / (double) size.width();
yaspect = tmplte->getHeight() / (double) size.height();
QTransform qtrans;
qtrans.translate(0.f, -tmplte->getHeight());
qtrans.scale(xaspect , yaspect);
qtrans.translate(0.f, Rez::guiX(-tmplte->getHeight()));
qtrans.scale(Rez::guiX(xaspect) , Rez::guiX(yaspect));
m_svgItem->setTransform(qtrans);
}
@@ -190,11 +191,11 @@ void QGISVGTemplate::createClickHandles(void)
QString yStr = QString::fromStdString(yMatch[1].str());
QString editableName = QString::fromStdString(nameMatch[1].str());
double x = xStr.toDouble();
double y = yStr.toDouble();
double x = Rez::guiX(xStr.toDouble());
double y = Rez::guiX(yStr.toDouble());
//TODO: this should probably be configurable without a code change
double editClickBoxSize = 1.5;
double editClickBoxSize = Rez::guiX(1.5);
QColor editClickBoxColor = Qt::green;
double width = editClickBoxSize;
@@ -202,7 +203,7 @@ void QGISVGTemplate::createClickHandles(void)
TemplateTextField *item = new TemplateTextField(this, tmplte, nameMatch[1].str(), qgview);
float pad = 1;
item->setRect(x - pad, -tmplte->getHeight() + y - height - pad,
item->setRect(x - pad, Rez::guiX(-tmplte->getHeight()) + y - height - pad,
width + 2 * pad, height + 2 * pad);
QPen myPen;

View File

@@ -33,6 +33,7 @@
#include <Base/Parameter.h>
#include <qmath.h>
#include "Rez.h"
#include "QGIView.h"
#include "QGISectionLine.h"
@@ -40,7 +41,7 @@ using namespace TechDrawGui;
QGISectionLine::QGISectionLine()
{
m_extLen = 8.0;
m_extLen = Rez::guiX(8.0);
m_arrowSize = 0.0;
m_line = new QGraphicsPathItem();
@@ -54,7 +55,7 @@ QGISectionLine::QGISectionLine()
m_symbol2 = new QGCustomText();
addToGroup(m_symbol2);
setWidth(0.75);
setWidth(Rez::guiX(0.75));
setStyle(getSectionStyle());
setColor(getSectionColor());
@@ -74,7 +75,7 @@ void QGISectionLine::makeLine()
QPainterPath pp;
QPointF extLineStart,extLineEnd;
QPointF offset(m_arrowDir.x,-m_arrowDir.y);
offset = 0.80 * m_extLen * offset; //0.80 is hack to hide line end behind arrowhead
offset = 0.75 * m_extLen * offset; //0.75 is hack to hide line end behind arrowhead
extLineStart = m_start + offset;
extLineEnd = m_end + offset;
pp.moveTo(extLineStart);
@@ -100,6 +101,8 @@ void QGISectionLine::makeArrows()
extLineStart = m_start + offset;
extLineEnd = m_end + offset;
m_arrow1->setStyle(0);
m_arrow2->setStyle(0);
m_arrow1->setPos(extLineStart);
//m_arrow1->flip(true);
m_arrow1->draw();
@@ -121,9 +124,15 @@ void QGISectionLine::makeSymbols()
m_symFont.setPointSize(m_symSize);
m_symbol1->setFont(m_symFont);
m_symbol1->setPlainText(QString::fromUtf8(m_symbol));
if (m_arrowDir.y < 0.0) { //pointing down
extLineStart -= QPointF (0.0,m_symSize); //move text up a bit
}
m_symbol1->centerAt(extLineStart);
m_symbol2->setFont(m_symFont);
m_symbol2->setPlainText(QString::fromUtf8(m_symbol));
if (m_arrowDir.y < 0.0) { //pointing down
extLineEnd -= QPointF (0.0,m_symSize);
}
m_symbol2->centerAt(extLineEnd);
}

View File

@@ -44,7 +44,12 @@
#include <Base/Console.h>
#include <Gui/Selection.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/ViewProvider.h>
#include "Rez.h"
#include "QGCustomBorder.h"
#include "QGCustomLabel.h"
#include "QGIView.h"
@@ -188,13 +193,9 @@ void QGIView::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
if (!isInnerView()) {
double tempX = x(),
tempY = getY();
// getViewObject()->X.setValue(tempX);
// getViewObject()->Y.setValue(tempY);
getViewObject()->setPosition(tempX,tempY);
getViewObject()->setPosition(Rez::appX(tempX),Rez::appX(tempY));
} else {
// getViewObject()->X.setValue(x());
// getViewObject()->Y.setValue(getYInClip(y()));
getViewObject()->setPosition(x(),getYInClip(y()));
getViewObject()->setPosition(Rez::appX(x()),Rez::appX(getYInClip(y())));
}
getViewObject()->setMouseMove(false);
}
@@ -244,7 +245,7 @@ double QGIView::getYInClip(double y)
if (parentView) {
auto parentFeat( dynamic_cast<TechDraw::DrawViewClip*>(parentView->getViewObject()) );
if (parentFeat) {
return parentFeat->Height.getValue() - y;
return Rez::guiX(parentFeat->Height.getValue()) - y;
}
}
}
@@ -259,8 +260,8 @@ void QGIView::updateView(bool update)
if (update ||
getViewObject()->X.isTouched() ||
getViewObject()->Y.isTouched()) {
double featX = getViewObject()->X.getValue();
double featY = getViewObject()->Y.getValue();
double featX = Rez::guiX(getViewObject()->X.getValue());
double featY = Rez::guiX(getViewObject()->Y.getValue());
setPosition(featX,featY);
}
@@ -269,6 +270,7 @@ void QGIView::updateView(bool update)
//NOTE: QPainterPaths have to be rotated individually. This transform handles Rotation for everything else.
//Scale is handled in GeometryObject for DVP & descendents
//Objects not descended from DVP must setScale for themselves
//note that setTransform(,,rotation,,) is not the same as setRotation!!!
double rot = getViewObject()->Rotation.getValue();
QPointF centre = boundingRect().center();
setTransform(QTransform().translate(centre.x(), centre.y()).rotate(-rot).translate(-centre.x(), -centre.y()));
@@ -295,11 +297,10 @@ void QGIView::setViewFeature(TechDraw::DrawView *obj)
viewObj = obj;
viewName = obj->getNameInDocument();
// Set the QGIGroup initial position based on the DrawView ( wrong. new views are always at Page center)
// float x = obj->X.getValue();
// float y = obj->Y.getValue();
// setPosition(x, y);
//mark the actual QGraphicsItem so we can check what's in the scene later
setData(0,QString::fromUtf8("QGIV"));
setData(1,QString::fromUtf8(obj->getNameInDocument()));
}
void QGIView::toggleCache(bool state)
@@ -408,7 +409,7 @@ void QGIView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
//painter->drawRect(boundingRect());
//painter->drawRect(boundingRect()); //good for debugging
QGraphicsItemGroup::paint(painter, &myOption, widget);
}
@@ -454,6 +455,15 @@ QGIView* QGIView::getQGIVByName(std::string name)
return 0;
}
/* static */
Gui::ViewProvider* QGIView::getViewProvider(App::DocumentObject* obj)
{
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(obj->getDocument());
Gui::ViewProvider* result = guiDoc->getViewProvider(obj);
return result;
}
QColor QGIView::getNormalColor()
{
Base::Reference<ParameterGrp> hGrp = getParmGroupCol();
@@ -501,7 +511,7 @@ double QGIView::getPrefFontSize()
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter().
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Labels");
double fontSize = hGrp->GetFloat("LabelSize", 5.0);
return fontSize;
return Rez::guiX(fontSize);
}
void QGIView::dumpRect(char* text, QRectF r) {

View File

@@ -27,8 +27,10 @@
#include <QPen>
#include <QFont>
#include <App/DocumentObject.h>
#include <App/PropertyLinks.h>
#include <Base/Parameter.h>
#include <Gui/ViewProvider.h>
#include <Mod/TechDraw/App/DrawView.h>
@@ -87,6 +89,8 @@ public:
virtual QColor getNormalColor(void);
virtual QColor getPreColor(void);
virtual QColor getSelectColor(void);
static Gui::ViewProvider* getViewProvider(App::DocumentObject* obj);
protected:
QGIView* getQGIVByName(std::string name);

View File

@@ -50,6 +50,7 @@
#include <Base/Parameter.h>
#include <Mod/TechDraw/App/DrawViewAnnotation.h>
#include "Rez.h"
#include "QGIViewAnnotation.h"
#include "QGCustomText.h"
@@ -115,6 +116,8 @@ void QGIViewAnnotation::draw()
}
}
//TODO: text is position slightly high (and left??) on page save to SVG file
void QGIViewAnnotation::drawAnnotation()
{
auto viewAnno( dynamic_cast<TechDraw::DrawViewAnnotation *>(getViewObject()) );
@@ -129,7 +132,7 @@ void QGIViewAnnotation::drawAnnotation()
ss << "<html>\n<head>\n<style>\n";
ss << "p {";
ss << "font-family:" << viewAnno->Font.getValue() << "; ";
ss << "font-size:" << viewAnno->TextSize.getValue() << "pt; "; //units compatibility???
ss << "font-size:" << Rez::guiX(viewAnno->TextSize.getValue()) << "pt; "; //not really pts???
if (viewAnno->TextStyle.isValue("Normal")) {
ss << "font-weight:normal; font-style:normal; ";
} else if (viewAnno->TextStyle.isValue("Bold")) {
@@ -156,7 +159,7 @@ void QGIViewAnnotation::drawAnnotation()
ss << "</p>\n</body>\n</html> ";
prepareGeometryChange();
m_textItem->setTextWidth(viewAnno->MaxWidth.getValue());
m_textItem->setTextWidth(Rez::guiX(viewAnno->MaxWidth.getValue()));
QString qs = QString::fromUtf8(ss.str().c_str());
m_textItem->setHtml(qs);
m_textItem->setPos(0.,0.);

View File

@@ -53,11 +53,13 @@
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/Geometry.h>
#include "Rez.h"
#include "ZVALUE.h"
#include "QGIArrow.h"
#include "QGIDimLines.h"
#include "QGIViewDimension.h"
using namespace TechDraw;
using namespace TechDrawGui;
enum SnapMode{
@@ -156,6 +158,7 @@ QGIViewDimension::QGIViewDimension() :
//centerMark = new QGICMark();
//addToGroup(centerMark);
// connecting the needed slots and signals
QObject::connect(
datumLabel, SIGNAL(dragging()),
@@ -187,12 +190,12 @@ void QGIViewDimension::setViewPartFeature(TechDraw::DrawViewDimension *obj)
setViewFeature(static_cast<TechDraw::DrawView *>(obj));
// Set the QGIGroup Properties based on the DrawView
float x = obj->X.getValue(); //(0,0)?
float y = obj->Y.getValue();
float x = Rez::guiX(obj->X.getValue());
float y = Rez::guiX(obj->Y.getValue());
datumLabel->setPosFromCenter(x, y);
m_lineWidth = obj->LineWidth.getValue();
m_lineWidth = Rez::guiX(obj->LineWidth.getValue());
updateDim();
draw();
@@ -221,7 +224,7 @@ void QGIViewDimension::updateView(bool update)
if(dim->Fontsize.isTouched() ||
dim->Font.isTouched()) {
QFont font = datumLabel->font();
font.setPointSizeF(dim->Fontsize.getValue()); //scene units (mm), not points
font.setPointSizeF(Rez::guiX(dim->Fontsize.getValue()));
font.setFamily(QString::fromLatin1(dim->Font.getValue()));
datumLabel->setFont(font);
@@ -250,7 +253,7 @@ void QGIViewDimension::updateDim()
QString labelText = QString::fromUtf8(dim->getFormatedValue().data(),dim->getFormatedValue().size());
QFont font = datumLabel->font();
font.setPointSizeF(dim->Fontsize.getValue()); //scene units (mm), not points
font.setPointSizeF(Rez::guiX(dim->Fontsize.getValue()));
font.setFamily(QString::fromUtf8(dim->Font.getValue()));
datumLabel->setFont(font);
@@ -272,8 +275,8 @@ void QGIViewDimension::datumLabelDragFinished()
return;
}
double x = datumLabel->X(),
y = datumLabel->Y();
double x = Rez::appX(datumLabel->X()),
y = Rez::appX(datumLabel->Y());
Gui::Command::openCommand("Drag Dimension");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.X = %f", dim->getNameInDocument(), x);
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Y = %f", dim->getNameInDocument(), y);
@@ -286,23 +289,30 @@ void QGIViewDimension::draw()
if (!isVisible()) { //should this be controlled by parent ViewPart?
return;
}
show();
TechDraw::DrawViewDimension *dim = dynamic_cast<TechDraw::DrawViewDimension *>(getViewObject());
if((!dim) || //nothing to draw, don't try
(!dim->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId())) ||
(!dim->has2DReferences()) ) {
datumLabel->hide();
hide();
return;
}
const TechDraw::DrawViewPart *refObj = dim->getViewPart();
if(!refObj->hasGeometry()) { //nothing to draw yet (restoring)
datumLabel->hide();
hide();
return;
}
m_lineWidth = dim->LineWidth.getValue();
m_lineWidth = Rez::guiX(dim->LineWidth.getValue());
float margin = Rez::guiX(5.f);
QString labelText = datumLabel->toPlainText();
Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0);
Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0); //already gui coords
//const std::vector<App::DocumentObject*> &objects = dim->References2D.getValues();
const std::vector<std::string> &SubNames = dim->References2D.getSubValues();
@@ -327,9 +337,14 @@ void QGIViewDimension::draw()
Base::Vector2d pnt1 = gen->points.at(0);
Base::Vector2d pnt2 = gen->points.at(1);
distStart = Base::Vector3d(pnt1.x, pnt1.y, 0.);
distStart = Rez::guiX(distStart);
distEnd = Base::Vector3d(pnt2.x, pnt2.y, 0.);
distEnd = Rez::guiX(distEnd);
} else {
throw Base::Exception("QGIVD::draw - Original edge not found or is invalid type (1)");
Base::Console().Log("INFO - QGIVD::draw - Original edge not found or is invalid type (1)\n");
datumLabel->hide();
hide();
return;
}
} else if(dim->References2D.getValues().size() == 2 &&
TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]) == "Vertex" &&
@@ -345,7 +360,9 @@ void QGIViewDimension::draw()
return;
}
distStart = Base::Vector3d (v0->pnt.x, v0->pnt.y, 0.);
distStart = Rez::guiX(distStart);
distEnd = Base::Vector3d (v1->pnt.x, v1->pnt.y, 0.);
distEnd = Rez::guiX(distEnd);
} else if(dim->References2D.getValues().size() == 2 &&
TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]) == "Edge" &&
TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]) == "Edge") {
@@ -364,7 +381,9 @@ void QGIViewDimension::draw()
p1 = geom0->nearPoint(geom1);
p2 = geom1->nearPoint(geom0);
distStart = Base::Vector3d(p1.x,p1.y,0.0);
distStart = Rez::guiX(distStart);
distEnd = Base::Vector3d(p2.x,p2.y,0.0);
distEnd = Rez::guiX(distStart);
} else if ( (geom0->geomType == TechDrawGeometry::GENERIC) &&
(geom1->geomType == TechDrawGeometry::GENERIC) ){
TechDrawGeometry::Generic *gen0 = static_cast<TechDrawGeometry::Generic *>(geom0);
@@ -374,11 +393,15 @@ void QGIViewDimension::draw()
pnt1 = gen0->points.at(0);
pnt2 = gen0->points.at(1);
edge1Start = Base::Vector3d(pnt1.x, pnt1.y, 0);
edge1Start = Rez::guiX(edge1Start);
edge1End = Base::Vector3d(pnt2.x, pnt2.y, 0);
edge1End = Rez::guiX(edge1End);
pnt1 = gen1->points.at(0);
pnt2 = gen1->points.at(1);
edge2Start = Base::Vector3d(pnt1.x, pnt1.y, 0);
edge2Start = Rez::guiX(edge2Start);
edge2End = Base::Vector3d(pnt2.x, pnt2.y, 0);
edge2End = Rez::guiX(edge2End);
// figure out which end of each edge to use for drawing
Base::Vector3d lin1 = edge1End - edge1Start; //vector from edge1Start to edge2End
@@ -397,8 +420,10 @@ void QGIViewDimension::draw()
else
distEnd = edge2Start;
} else {
//TODO: Exception here seems drastic. Can we fail more gracefully?
throw Base::Exception("FVD::draw -Invalid reference for dimension type (1)");
Base::Console().Log("INFO - QGIVD::draw - Invalid reference for dimension type (1)\n");
datumLabel->hide();
hide();
return;
}
} else if(dim->References2D.getValues().size() == 2) {
int vx,ex;
@@ -430,8 +455,8 @@ void QGIViewDimension::draw()
displace.ProjectToLine(pnt - edgeStart, edgeEnd - edgeStart);
Base::Vector3d ptOnLine = pnt + displace;
distStart = pnt;
distEnd = ptOnLine;
distStart = Rez::guiX(pnt);
distEnd = Rez::guiX(ptOnLine);
//need to figure out Distance? from slope of distEnd-distStart?
} else {
Base::Console().Message("TARFU - invalid references for Dimension!!");
@@ -443,7 +468,7 @@ void QGIViewDimension::draw()
// text to left of vertical dims
// text above horizontal dims
double offsetFudge = 2.0;
double textOffset = 0.75 * dim->Fontsize.getValue() + offsetFudge;
double textOffset = 0.75 * Rez::guiX(dim->Fontsize.getValue()) + offsetFudge;
Base::Vector3d dir, norm; //direction/normal vectors of distance line (not dimension Line)
if (strcmp(dimType, "Distance") == 0 ) {
dir = (distEnd-distStart);
@@ -498,18 +523,15 @@ void QGIViewDimension::draw()
Base::Vector3d distMid = (distStart_ + distEnd) / 2.0;
// QFont font = datumLabel->font(); //font metrics gives answers in pixels, not mm
// font.setPointSizeF(dim->Fontsize.getValue());
// font.setFamily(QString::fromUtf8(dim->Font.getValue()));
// font.setPointSizeF(dim->Fontsize.getValue());
// QFontMetrics fm(font);
// int w = fm.width(labelText);
// int w = fm.width(labelText); //why is this different than diameter/radius?
// int h = fm.height();
double lblWidth = datumLabel->boundingRect().width();
Base::Vector3d fauxCenter = lblCenter + textOffset * textNorm;
Base::Vector3d vec = fauxCenter - distEnd; //endof dist line to center of dimline
float perpDistance = vec.x * norm.x + vec.y * norm.y; //dot(vec,norm) the perp distance between distance & dimension lines.
float margin = 2.f;
margin = Rez::guiX(2.f);
float scaler = 1.;
float offset1 = (perpDistance + normproj12 < 0) ? -margin : margin;
@@ -536,7 +558,7 @@ void QGIViewDimension::draw()
double dimSpan = (dim2Tail - dim1Tip).Length();
double fauxToDim1 = (fauxCenter - dim1Tip).Length(); //label to end #1
double fauxToDim2 = (fauxCenter - dim2Tail).Length();
double tailLength = 10.f * scaler;
double tailLength = Rez::guiX(10.f) * scaler;
//case2 - innerPlacement * text > span
if ((lblWidth > dimSpan) &&
@@ -571,7 +593,7 @@ void QGIViewDimension::draw()
path.lineTo(ext2End.x, ext2End.y);
//Dimension lines
//line tip goes just a bit too far. overlaps the arrowhead's point
//TODO: line tip goes just a bit too far. overlaps the arrowhead's point
//default arrow perpDistance is 5.0
path.moveTo(dim1Tip.x, dim1Tip.y);
@@ -589,8 +611,10 @@ void QGIViewDimension::draw()
double angleOption = 0.0; //put lblText angle adjustments here
datumLabel->setRotation((angle * 180 / M_PI) + angleOption);
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
aHead1->draw();
aHead2->flip(true);
aHead2->setStyle(QGIArrow::getPrefArrowStyle());
aHead2->draw();
angle = atan2f(dir.y,dir.x);
float arrowAngle = angle * 180 / M_PI;
@@ -609,9 +633,11 @@ void QGIViewDimension::draw()
} else if(strcmp(dimType, "Diameter") == 0) {
// terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
// was datumLabel, datum line/parallel line, perpendicular line, arw
Base::Vector3d arrow1Tip, arrow2Tip, dirDimLine, centre; //was p1,p2,dir
Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0);
Base::Vector3d arrow1Tip, arrow2Tip, dirDimLine; //was p1,p2,dir
double radius;
Base::Vector3d pointOnCurve,curveCenter;
TechDrawGeometry::AOC* geomArc = 0;
bool isArc = false;
if(dim->References2D.getValues().size() == 1 &&
TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]) == "Edge") {
@@ -622,36 +648,53 @@ void QGIViewDimension::draw()
idx,refObj->getEdgeGeometry().size());
return;
}
if( (geom->geomType == TechDrawGeometry::CIRCLE) ||
(geom->geomType == TechDrawGeometry::ARCOFCIRCLE) ) {
if (geom->geomType == TechDrawGeometry::CIRCLE) {
TechDrawGeometry::Circle *circ = static_cast<TechDrawGeometry::Circle *>(geom);
radius = circ->radius;
centre = Base::Vector3d (circ->center.x, circ->center.y, 0);
radius = Rez::guiX(circ->radius);
curveCenter = Base::Vector3d(circ->center.x,circ->center.y,0.0);
curveCenter = Rez::guiX(curveCenter);
pointOnCurve = Base::Vector3d(curveCenter.x + radius, curveCenter.y,0.0);
pointOnCurve = Rez::guiX(pointOnCurve);
} else if (geom->geomType == TechDrawGeometry::ARCOFCIRCLE) {
isArc = true;
TechDrawGeometry::AOC *circ = static_cast<TechDrawGeometry::AOC *>(geom);
geomArc = circ;
radius = Rez::guiX(circ->radius);
curveCenter = Base::Vector3d(circ->center.x,circ->center.y,0.0);
curveCenter = Rez::guiX(curveCenter);
pointOnCurve = Base::Vector3d(circ->midPnt.x, circ->midPnt.y,0.0);
pointOnCurve = Rez::guiX(pointOnCurve);
} else {
throw Base::Exception("FVD::draw - Original edge not found or is invalid type (2)");
Base::Console().Log("INFO - QGIVD::draw - Original edge not found or is invalid type (2)\n");
datumLabel->hide();
hide();
return;
}
} else {
throw Base::Exception("FVD ::draw - Invalid reference for dimension type (2)");
Base::Console().Log("INFO - QGIVD::draw - Invalid reference for dimension type (2)\n");
datumLabel->hide();
hide();
return;
}
// Note Bounding Box size is not the same width or height as text (only used for finding center)
float bbX = datumLabel->boundingRect().width();
float bbY = datumLabel->boundingRect().height();
dirDimLine = (lblCenter - centre).Normalize(); //if lblCenter == centre, this is (0,0,0)??
dirDimLine = (lblCenter - curveCenter).Normalize(); //if lblCenter == curveCenter, this is (0,0,0)??
if (fabs(dirDimLine.Length()) < (Precision::Confusion())) {
dirDimLine = Base::Vector3d(-1.0,0.0,0.0);
}
//this is for inner placement only? recalced for outer?
arrow1Tip = centre - dirDimLine * radius; //endpoint of diameter arrowhead1
arrow2Tip = centre + dirDimLine * radius; //endpoint of diameter arrowhead2
arrow1Tip = curveCenter - dirDimLine * radius; //endpoint of diameter arrowhead1
arrow2Tip = curveCenter + dirDimLine * radius; //endpoint of diameter arrowhead2
QFontMetrics fm(datumLabel->font());
int w = fm.width(labelText);
//int h = fm.height();
float margin = 5.f;
margin = Rez::guiX(5.f);
// Calculate the dimension line endpoints
// recalced for vert & horizontal snap & inner placement. not used for nosnap outer?
@@ -659,7 +702,7 @@ void QGIViewDimension::draw()
Base::Vector3d dLine2Tail = lblCenter + dirDimLine * (margin + w / 2);
bool outerPlacement = false;
if ((lblCenter-centre).Length() > radius) { //label is outside circle
if ((lblCenter-curveCenter).Length() > radius) { //label is outside circle
outerPlacement = true;
}
@@ -686,13 +729,13 @@ void QGIViewDimension::draw()
}
if(posMode == VerticalSnap) {
float tip = (lblCenter.y > centre.y) ? margin: -margin;
tip *= 0.5;
float tip = (lblCenter.y > curveCenter.y) ? margin: -margin;
//tip *= 0.5;
arrow1Tip.x = centre.x - radius; //to left, on circle cl
arrow1Tip.x = curveCenter.x - radius; //to left, on circle cl
arrow1Tip.y = lblCenter.y;
arrow2Tip.x = centre.x + radius;
arrow2Tip.x = curveCenter.x + radius;
arrow2Tip.y = lblCenter.y;
dLine1Tail = lblCenter;
@@ -702,14 +745,14 @@ void QGIViewDimension::draw()
dLine2Tail.x += (margin + w / 2);
// Extension line 1
path.moveTo(centre.x - radius, centre.y);
path.moveTo(curveCenter.x - radius, curveCenter.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y + tip);
path.moveTo(arrow1Tip.x, arrow1Tip.y); //dimension line, not arrowhead
path.lineTo(dLine1Tail.x, dLine1Tail.y);
// Extension line 2
path.moveTo(centre.x + radius, centre.y);
path.moveTo(curveCenter.x + radius, curveCenter.y);
path.lineTo(arrow2Tip.x, arrow2Tip.y + tip);
path.moveTo(dLine2Tail.x, dLine2Tail.y);
@@ -720,13 +763,13 @@ void QGIViewDimension::draw()
} else if(posMode == HorizontalSnap) {
// Snapped Horizontally
float tip = (lblCenter.x > centre.x) ? margin: -margin;
tip *= 0.5;
float tip = (lblCenter.x > curveCenter.x) ? margin: -margin;
//tip *= 0.5;
arrow1Tip.y = centre.y - radius;
arrow1Tip.y = curveCenter.y - radius;
arrow1Tip.x = lblCenter.x;
arrow2Tip.y = centre.y + radius;
arrow2Tip.y = curveCenter.y + radius;
arrow2Tip.x = lblCenter.x;
dLine1Tail = lblCenter;
@@ -736,14 +779,14 @@ void QGIViewDimension::draw()
dLine2Tail.y += (margin + w / 2);
// Extension lines
path.moveTo(centre.x, centre.y - radius);
path.moveTo(curveCenter.x, curveCenter.y - radius);
path.lineTo(arrow1Tip.x + tip, arrow1Tip.y);
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(dLine1Tail.x, dLine1Tail.y);
// Extension lines
path.moveTo(centre.x, centre.y + radius);
path.moveTo(curveCenter.x, curveCenter.y + radius);
path.lineTo(arrow2Tip.x + tip, arrow2Tip.y);
path.moveTo(dLine2Tail.x, dLine2Tail.y);
@@ -753,16 +796,16 @@ void QGIViewDimension::draw()
} else { //outer placement, NoSnap
float tip = (margin + w / 2); // spacer + 0.5*lblText.width() tip is actually tail?
tip = (lblCenter.x < centre.x) ? tip : -tip; //if label on left then tip is +ve (ie to right)
tip = (lblCenter.x < curveCenter.x) ? tip : -tip; //if label on left then tip is +ve (ie to right)
arrow1Tip = lblCenter; //this tip is really tail(ie end near lblText)
arrow1Tip.x += tip;
Base::Vector3d p3 = arrow1Tip;
p3.x += (lblCenter.x < centre.x) ? margin : - margin; // p3 is a little farther away from lblText towards centre in X
p3.x += (lblCenter.x < curveCenter.x) ? margin : - margin; // p3 is a little farther away from lblText towards curveCenter in X
arrow2Tip = centre + (p3 - centre).Normalize() * radius; //point on curve aimed just short of label text
arrow2Tip = curveCenter + (p3 - curveCenter).Normalize() * radius; //point on curve aimed just short of label text
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(p3[0], p3[1]);
@@ -774,8 +817,8 @@ void QGIViewDimension::draw()
} else { //NOT outerplacement ie dimLines are inside circle
//text always rightside up inside circle
datumLabel->setRotation(0);
dLine1Tail = centre - dirDimLine * margin;
dLine2Tail = centre + dirDimLine * margin;
dLine1Tail = curveCenter - dirDimLine * margin;
dLine2Tail = curveCenter + dirDimLine * margin;
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(dLine1Tail.x, dLine1Tail.y);
@@ -784,24 +827,85 @@ void QGIViewDimension::draw()
path.lineTo(arrow2Tip.x, arrow2Tip.y);
}
dimLines->setPath(path);
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
aHead1->draw();
aHead2->flip(true);
aHead2->setStyle(QGIArrow::getPrefArrowStyle());
aHead2->draw();
float arAngle = atan2(dirDimLine.y, dirDimLine.x) * 180 / M_PI;
aHead2->show();
if(outerPlacement) {
//handle partial arc weird cases
Base::Vector3d dLineStart;
Base::Vector3d kinkPoint;
margin = Rez::guiX(5.f); //space around label
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
if (isArc) {
aHead2->hide();
aHead1->flip(true);
aHead1->draw();
Base::Vector3d midPt(geomArc->midPnt.x, geomArc->midPnt.y,0.0);
midPt = Rez::guiX(midPt);
Base::Vector3d startPt(geomArc->startPnt.x, geomArc->startPnt.y,0.0);
startPt = Rez::guiX(startPt);
Base::Vector3d endPt(geomArc->endPnt.x, geomArc->endPnt.y,0.0);
endPt = Rez::guiX(endPt);
kinkLength = (lblCenter.x < curveCenter.x) ? kinkLength : -kinkLength;
dirDimLine = lblCenter - curveCenter;
dirDimLine.Normalize();
Base::Vector3d labelEndDir(1.0,0.0,0.0);
if (lblCenter.x > pointOnCurve.x) { //label is to right of point
labelEndDir = -1.0 * labelEndDir;
}
dLineStart = lblCenter + labelEndDir * (margin + w / 2);
kinkPoint.y = dLineStart.y;
kinkPoint.x = dLineStart.x + kinkLength;
pointOnCurve = curveCenter + dirDimLine * radius;
if (!geomArc->intersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
if (!geomArc->cw ) {
pointOnCurve = endPt;
} else {
pointOnCurve = startPt;
}
} else {
if (!geomArc->cw) {
pointOnCurve = startPt;
} else {
pointOnCurve = endPt;
}
}
}
Base::Vector3d arVector = (kinkPoint - pointOnCurve);
arVector.Normalize();
arAngle = atan2(arVector.y, arVector.x) * 180 / M_PI;
path = QPainterPath();
path.moveTo(dLineStart.x,dLineStart.y);
path.lineTo(kinkPoint.x,kinkPoint.y);
path.lineTo(pointOnCurve.x,pointOnCurve.y);
datumLabel->setRotation(0.);
}
dimLines->setPath(path);
if (isArc) {
aHead1->setPos(pointOnCurve.x, pointOnCurve.y);
aHead1->setRotation(arAngle);
aHead2->hide();
} else if(outerPlacement) {
if(posMode > NoSnap) {
aHead1->setPos(arrow2Tip.x, arrow2Tip.y); //arrow 1's endpoint is arrow2Tip!?
aHead2->setPos(arrow1Tip.x, arrow1Tip.y);
aHead1->setRotation((posMode == HorizontalSnap) ? 90 : 0);
aHead2->setRotation((posMode == HorizontalSnap) ? 90 : 0);
} else {
Base::Vector3d vec = (arrow2Tip - centre).Normalize();
Base::Vector3d vec = (arrow2Tip - curveCenter).Normalize();
float arAngle = atan2(-vec.y, -vec.x) * 180 / M_PI;
aHead1->setPos(arrow2Tip.x, arrow2Tip.y);
aHead1->setRotation(arAngle);
@@ -817,14 +921,14 @@ void QGIViewDimension::draw()
}
// if (dim->CentreLines.getValue()) {
// centreMark->setPos(centre.x,centre.y);
// curveCenterMark->setPos(curveCenter.x,curveCenter.y);
// centerMark->show();
// dim->getViewPart()->addVertex(centre,true);
// dim->getViewPart()->addVertex(curveCenter,true);
// }
} else if(strcmp(dimType, "Radius") == 0) {
// preferred terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
// radius gets 1 dimension line from the dimension text to a point on the curve
Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(),0.0);
// Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(),0.0);
Base::Vector3d pointOnCurve,curveCenter;
double radius;
@@ -841,21 +945,31 @@ void QGIViewDimension::draw()
}
if (geom->geomType == TechDrawGeometry::CIRCLE) {
TechDrawGeometry::Circle *circ = static_cast<TechDrawGeometry::Circle *>(geom);
radius = circ->radius;
radius = Rez::guiX(circ->radius);
curveCenter = Base::Vector3d(circ->center.x,circ->center.y,0.0);
curveCenter = Rez::guiX(curveCenter);
pointOnCurve = Base::Vector3d(curveCenter.x + radius, curveCenter.y,0.0);
pointOnCurve = Rez::guiX(pointOnCurve);
} else if (geom->geomType == TechDrawGeometry::ARCOFCIRCLE) {
isArc = true;
TechDrawGeometry::AOC *circ = static_cast<TechDrawGeometry::AOC *>(geom);
geomArc = circ;
radius = circ->radius;
radius = Rez::guiX(circ->radius);
curveCenter = Base::Vector3d(circ->center.x,circ->center.y,0.0);
curveCenter = Rez::guiX(curveCenter);
pointOnCurve = Base::Vector3d(circ->midPnt.x, circ->midPnt.y,0.0);
pointOnCurve = Rez::guiX(pointOnCurve);
} else {
throw Base::Exception("FVD::draw - Original edge not found or is invalid type (3)");
Base::Console().Log("INFO - QGIVD::draw - Original edge not found or is invalid type (3)\n");
datumLabel->hide();
hide();
return;
}
} else {
throw Base::Exception("FVD::draw - Invalid reference for dimension type (3)");
Base::Console().Log("INFO - QGIVD::draw - Invalid reference for dimension type (3)\n");
datumLabel->hide();
hide();
return;
}
QFontMetrics fm(datumLabel->font());
@@ -880,8 +994,8 @@ void QGIViewDimension::draw()
Base::Vector3d dLineStart;
Base::Vector3d kinkPoint;
double margin = 5.f; //space around label
double kinkLength = 5.0; //sb % of horizontal dist(lblCenter,curveCenter)???
margin = Rez::guiX(5.f); //space around label
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
if (outerPlacement) {
float offset = (margin + w / 2);
offset = (lblCenter.x < curveCenter.x) ? offset : -offset; //if label on left then tip is +ve (ie to right)
@@ -905,10 +1019,13 @@ void QGIViewDimension::draw()
//handle partial arc weird cases
if (isArc) {
Base::Vector3d midPt(geomArc->midPnt.x, geomArc->midPnt.y,0.0);
midPt = Rez::guiX(midPt);
Base::Vector3d startPt(geomArc->startPnt.x, geomArc->startPnt.y,0.0);
startPt = Rez::guiX(startPt);
Base::Vector3d endPt(geomArc->endPnt.x, geomArc->endPnt.y,0.0);
endPt = Rez::guiX(endPt);
if (outerPlacement &&
!geomArc->intersectsArc(curveCenter,kinkPoint) ) {
!geomArc->intersectsArc(Rez::appX(curveCenter),Rez::appX(kinkPoint))) {
pointOnCurve = midPt;
} else if (!outerPlacement) {
if ((midPt - lblCenter).Length() > (midPt - curveCenter).Length()) { //label is farther than center
@@ -917,7 +1034,7 @@ void QGIViewDimension::draw()
dLineStart = curveCenter + dirDimLine * margin;
pointOnCurve = curveCenter + dirDimLine * radius;
kinkPoint = dLineStart;
if (!geomArc->intersectsArc(dLineStart,pointOnCurve)) { //keep pathological case within arc
if (!geomArc->intersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
if (!geomArc->cw ) {
pointOnCurve = endPt;
@@ -944,6 +1061,7 @@ void QGIViewDimension::draw()
dimLines->setPath(dLinePath);
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
aHead1->draw();
Base::Vector3d ar1Pos = pointOnCurve;
@@ -955,7 +1073,7 @@ void QGIViewDimension::draw()
aHead1->show();
aHead2->hide();
// if (dim->CentreLines.getValue()) {
// centreMark->setPos(curveCenter.x,curveCenter.y);
// curveCenterMark->setPos(curveCenter.x,curveCenter.y);
// centerMark->show();
// dim->getViewPart()->addVertex(curveCenter,true);
// }
@@ -978,6 +1096,7 @@ void QGIViewDimension::draw()
TechDrawGeometry::Generic *gen0 = static_cast<TechDrawGeometry::Generic *>(geom0);
TechDrawGeometry::Generic *gen1 = static_cast<TechDrawGeometry::Generic *>(geom1);
// Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0);
// Get Points for line
Base::Vector2d pnt1, pnt2;
Base::Vector3d p1S, p1E, p2S, p2E;
@@ -985,13 +1104,17 @@ void QGIViewDimension::draw()
pnt2 = gen0->points.at(1);
p1S = Base::Vector3d(pnt1.x, pnt1.y, 0);
p1S = Rez::guiX(p1S);
p1E = Base::Vector3d(pnt2.x, pnt2.y, 0);
p1E = Rez::guiX(p1E);
pnt1 = gen1->points.at(0);
pnt2 = gen1->points.at(1);
p2S = Base::Vector3d(pnt1.x, pnt1.y, 0);
p2S = Rez::guiX(p2S);
p2E = Base::Vector3d(pnt2.x, pnt2.y, 0);
p2E = Rez::guiX(p2E);
Base::Vector3d dir1 = p1E - p1S;
Base::Vector3d dir2 = p2E - p2S;
@@ -1018,15 +1141,14 @@ void QGIViewDimension::draw()
double labelangle = atan2(-labelVec.y, labelVec.x);
double startangle = atan2(dir1.y,dir1.x); //whichever edge was clicked first
double range = atan2(-dir1.y*dir2.x+dir1.x*dir2.y, //atan2(dir1.cross(dir2), dir1.dot(dir2)) =
dir1.x*dir2.x+dir1.y*dir2.y); // angle between dir1,dir2
double startangle = atan2(dir1.y,dir1.x);
double range = atan2(-dir1.y*dir2.x+dir1.x*dir2.y,
dir1.x*dir2.x+dir1.y*dir2.y);
double endangle = startangle + range;
// Obtain the Label Position
Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0); //(0,0) at creation
// Obtain the Label Position and measure the length between intersection
// Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0);
float bbX = datumLabel->boundingRect().width();
float bbY = datumLabel->boundingRect().height();
@@ -1043,58 +1165,9 @@ void QGIViewDimension::draw()
Base::Vector3d p2 = ((p2E - p0).Length() > (p2S - p0).Length()) ? p2E : p2S;
// add an offset from the ends (add 1mm from end)
p1 += (p1-p0).Normalize() * 5.;
p1 += (p1-p0).Normalize() * 5.; //apply Rez here??? unitVector * 5 = 1/mm?
p2 += (p2-p0).Normalize() * 5.;
double l = labelangle;
double s = startangle;
double e = endangle;
//map angles onto [0,2PI]
if (l < 0.0) {
l += 2.0 * M_PI;
}
if (s < 0.0) {
s += 2.0 * M_PI;
}
if (e < 0.0) {
e += 2.0 * M_PI;
}
double low = std::min(s,e);
double high = std::max(s,e);
double offset;
offset = -low; //rotate low number to 0*
//double offLow = low + offset; //sb always zero
double offHigh = high + offset;
double offLabel = l + offset;
if (offLabel < 0.0) { //make sure offLabel is [0,2PI]
offLabel += 2.0 * M_PI;
}
//where to draw the arc
double arcDir;
double arcRange;
if ((offLabel <= offHigh) &&
(offLabel >= 0.0)) {
arcRange = high - low;
arcDir = 1.0;
} else { //offhigh <= offLabel <= 2PI
arcRange = 2.0 * M_PI - (high - low);
arcDir = -1.0;
}
//flip the arrow heads?
bool isOutside = true;
if (offHigh <= M_PI) { // end is in top half
if (offLabel <= offHigh ) { //label between 0 and offhigh
isOutside = false;
}
} else { //offHigh > M_PI //en is in bottom half
if (offLabel >= offHigh) { //label between offHigh and 0/360
isOutside = false;
}
}
Base::Vector3d ar1Pos = p0;
Base::Vector3d ar2Pos = p0;
@@ -1107,23 +1180,87 @@ void QGIViewDimension::draw()
// Only draw extension lines if outside arc
if(length > (p1-p0).Length()) {
path.moveTo(p1.x, p1.y);
p1 = ar1Pos + (p1-p0).Normalize() * 5.;
p1 = ar1Pos + (p1-p0).Normalize() * Rez::guiX(5.); //a bit past arrow head on leg 1
path.lineTo(p1.x, p1.y);
}
if(length > (p2-p0).Length()) {
path.moveTo(p2.x, p2.y);
p2 = ar2Pos + (p2-p0).Normalize() * 5.;
p2 = ar2Pos + (p2-p0).Normalize() * Rez::guiX(5.); //a bit past leg 2 arrow head on leg 2
path.lineTo(p2.x, p2.y);
}
bool isOutside = true;
// TODO find a better solution for this. Addmitedely not tidy
// ###############
// Treat zero as positive to be consistent for horizontal lines
if(std::abs(startangle) < FLT_EPSILON)
startangle = 0;
if(std::abs(endangle) < FLT_EPSILON)
endangle = 0;
if(startangle >= 0 && endangle >= 0) { //Both are in positive side
double langle = labelangle;
if(labelangle < 0)
langle += M_PI * 2;
if(endangle - startangle > 0) {
if(langle > startangle && langle < endangle)
isOutside = false;
} else {
if(langle < startangle && langle > endangle)
isOutside = false;
}
} else if(startangle < 0 && endangle < 0) { //both are in negative side
double langle = labelangle;
if(labelangle > 0)
langle -= M_PI * 2;
if(endangle - startangle < 0) {
if(langle > endangle && langle < startangle) //clockwise
isOutside = false;
} else {
if(langle < endangle && langle > startangle) //anticlockwise
isOutside = false;
}
} else if(startangle >= 0 && endangle < 0) {
if(labelangle < startangle && labelangle > endangle) //clockwise
isOutside = false;
} else if(startangle < 0 && endangle >= 0) {
//Both are in positive side
if(labelangle > startangle && labelangle < endangle) //clockwise
isOutside = false;
}
QRectF arcRect(p0.x - length, p0.y - length, 2. * length, 2. * length);
path.arcMoveTo(arcRect, low * 180 / M_PI);
path.arcTo(arcRect, low * 180 / M_PI, arcDir * arcRange * 180 / M_PI);
path.arcMoveTo(arcRect, endangle * 180 / M_PI);
if(isOutside) {
if(labelangle > endangle)
{
path.arcTo(arcRect, endangle * 180 / M_PI, (labelangle - endangle) * 180 / M_PI); //CCW from endangle
path.arcMoveTo(arcRect,startangle * 180 / M_PI);
path.arcTo(arcRect, startangle * 180 / M_PI, -10); //cw10 from start
} else {
path.arcTo(arcRect, endangle * 180 / M_PI, 10); // chosen a nominal value for 10 degrees
path.arcMoveTo(arcRect,startangle * 180 / M_PI);
path.arcTo(arcRect, startangle * 180 / M_PI, (labelangle - startangle) * 180 / M_PI); //unknown dir
}
} else {
path.arcTo(arcRect, endangle * 180 / M_PI, -range * 180 / M_PI);
}
dimLines->setPath(path);
aHead1->flip(true);
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
aHead1->draw();
aHead2->setStyle(QGIArrow::getPrefArrowStyle());
aHead2->draw();
Base::Vector3d norm1 = p1-p0; //(-dir1.y, dir1.x, 0.);
@@ -1137,7 +1274,7 @@ void QGIViewDimension::draw()
aHead1->setPos(ar1Pos.x,ar1Pos.y );
aHead2->setPos(ar2Pos.x,ar2Pos.y );
float ar1angle = atan2(-norm1.y, -norm1.x) * 180 / M_PI; //TODO: arrow dir sb tangent to arc.
float ar1angle = atan2(-norm1.y, -norm1.x) * 180 / M_PI;
float ar2angle = atan2(norm2.y, norm2.x) * 180 / M_PI;
if(isOutside) {
@@ -1148,21 +1285,27 @@ void QGIViewDimension::draw()
aHead2->setRotation(ar2angle);
}
// Set the angle of the datum text
// Set the angle of the dimension text
Base::Vector3d labelNorm(-labelVec.y, labelVec.x, 0.);
double angLabelNorm = atan2(labelNorm.y, labelNorm.x);
//if label moves above/below horizontal, flip it right side up
if (angLabelNorm > M_PI_2-M_PI/12) { // label norm angle > 90 - 15 = 85
angLabelNorm -= M_PI; // angLabelNorm - 180 Flip
} else if (angLabelNorm <= -M_PI_2-M_PI/12) { // < -90 - 15 = - 105
angLabelNorm += M_PI; // angLabelNorm + 180 Flip
double lAngle = atan2(labelNorm.y, labelNorm.x);
//if label is more/less vertical, make it vertical
if (lAngle > M_PI_2+M_PI/12) { // label norm angle > 90 + 15 = 105
lAngle -= M_PI; // lAngle - 180 Flip
} else if (lAngle <= -M_PI_2+M_PI/12) { // < -90 + 15 = - 85
lAngle += M_PI; // langle + 180 Flip
}
datumLabel->setTransformOriginPoint(bbX / 2., bbY /2.);
datumLabel->setRotation(angLabelNorm * 180 / M_PI);
datumLabel->setRotation(lAngle * 180 / M_PI);
} else {
throw Base::Exception("FVD::draw - Invalid reference for dimension type (4)");
Base::Console().Log("INFO - QGIVD::draw - Invalid reference for dimension type (4)\n");
datumLabel->hide();
hide();
return;
}
} //endif 2 Edges
} //endif Distance/Diameter/Radius/Angle
@@ -1217,16 +1360,15 @@ void QGIViewDimension::paint ( QPainter * painter, const QStyleOptionGraphicsIte
QPaintDevice* hw = painter->device();
QSvgGenerator* svg = dynamic_cast<QSvgGenerator*>(hw);
double arrowSaveWidth = aHead1->getWidth();
setPens();
//double arrowSaveWidth = aHead1->getWidth();
if (svg) {
setSvgPens();
} else {
setPens();
}
QGIView::paint (painter, &myOption, widget);
aHead1->setWidth(arrowSaveWidth);
aHead2->setWidth(arrowSaveWidth);
dimLines->setWidth(m_lineWidth);
setPens();
}
void QGIViewDimension::setSvgPens(void)
@@ -1240,6 +1382,8 @@ void QGIViewDimension::setSvgPens(void)
void QGIViewDimension::setPens(void)
{
dimLines->setWidth(m_lineWidth);
aHead1->setWidth(m_lineWidth);
aHead2->setWidth(m_lineWidth);
}
QColor QGIViewDimension::getNormalColor()

View File

@@ -27,6 +27,7 @@
#include <QGraphicsView>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsPathItem>
#include <QGraphicsRectItem>
#include <QColor>
#include <Base/Vector3D.h>
#include "QGIView.h"

View File

@@ -42,6 +42,7 @@
#include <Mod/TechDraw/App/DrawViewImage.h>
#include "Rez.h"
#include "QGCustomImage.h"
#include "QGCustomClip.h"
#include "QGIViewImage.h"
@@ -64,6 +65,7 @@ QGIViewImage::QGIViewImage()
m_cliparea->setRect(0.,0.,5.,5.);
m_imageItem = new QGCustomImage();
m_imageItem->setTransformationMode(Qt::SmoothTransformation);
m_cliparea->addToGroup(m_imageItem);
m_imageItem->setPos(0.,0.);
}
@@ -112,9 +114,10 @@ void QGIViewImage::draw()
return;
}
auto viewImage( static_cast<TechDraw::DrawViewImage*>(getViewObject()) );
QRectF newRect(0.0,0.0,viewImage->Width.getValue(),viewImage->Height.getValue());
m_cliparea->setRect(newRect.adjusted(-1,-1,1,1));
auto viewImage( dynamic_cast<TechDraw::DrawViewImage*>(getViewObject()) );
QRectF newRect(0.0,0.0,Rez::guiX(viewImage->Width.getValue()),Rez::guiX(viewImage->Height.getValue()));
double pad = Rez::guiX(1.0);
m_cliparea->setRect(newRect.adjusted(-pad,-pad,pad,pad));
drawImage();
if (borderVisible) {

View File

@@ -46,13 +46,16 @@
#include <App/Material.h>
#include <Base/Console.h>
#include <Base/Vector3D.h>
#include <Gui/ViewProvider.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
#include "Rez.h"
#include "ZVALUE.h"
#include "QGIFace.h"
#include "QGIEdge.h"
@@ -65,11 +68,12 @@
#include "QGCustomRect.h"
#include "QGIMatting.h"
#include "QGIViewPart.h"
#include "ViewProviderGeomHatch.h"
using namespace TechDrawGui;
using namespace TechDrawGeometry;
const float lineScaleFactor = 1.; // temp fiddle for devel
const float lineScaleFactor = Rez::guiX(1.); // temp fiddle for devel
const float vertexScaleFactor = 2.; // temp fiddle for devel
QGIViewPart::QGIViewPart()
@@ -144,15 +148,25 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
double x = geom->center.x - geom->radius;
double y = geom->center.y - geom->radius;
path.addEllipse(x, y, geom->radius * 2, geom->radius * 2); //topleft@(x,y) radx,rady
path.addEllipse(Rez::guiX(x),
Rez::guiX(y),
Rez::guiX(geom->radius * 2),
Rez::guiX(geom->radius * 2)); //topleft@(x,y) radx,rady
//Base::Console().Message("TRACE -drawPainterPath - making an CIRCLE @(%.3f,%.3f) R:%.3f\n",x, y, geom->radius);
} break;
case TechDrawGeometry::ARCOFCIRCLE: {
TechDrawGeometry::AOC *geom = static_cast<TechDrawGeometry::AOC *>(baseGeom);
pathArc(path, geom->radius, geom->radius, 0., geom->largeArc, geom->cw,
geom->endPnt.x, geom->endPnt.y,
geom->startPnt.x, geom->startPnt.y);
pathArc(path,
Rez::guiX(geom->radius),
Rez::guiX(geom->radius),
0.,
geom->largeArc,
geom->cw,
Rez::guiX(geom->endPnt.x),
Rez::guiX(geom->endPnt.y),
Rez::guiX(geom->startPnt.x),
Rez::guiX(geom->startPnt.y));
// double x = geom->center.x - geom->radius;
// double y = geom->center.y - geom->radius;
//Base::Console().Message("TRACE -drawPainterPath - making an ARCOFCIRCLE @(%.3f,%.3f) R:%.3f\n",x, y, geom->radius);
@@ -166,20 +180,43 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
endX = geom->center.x - geom->major * cos(geom->angle),
endY = geom->center.y - geom->major * sin(geom->angle);
pathArc(path, geom->major, geom->minor, geom->angle, false, false,
endX, endY, startX, startY);
pathArc(path,
Rez::guiX(geom->major),
Rez::guiX(geom->minor),
geom->angle,
false,
false,
Rez::guiX(endX),
Rez::guiX(endY),
Rez::guiX(startX),
Rez::guiX(startY));
pathArc(path, geom->major, geom->minor, geom->angle, false, false,
startX, startY, endX, endY);
pathArc(path,
Rez::guiX(geom->major),
Rez::guiX(geom->minor),
geom->angle,
false,
false,
Rez::guiX(startX),
Rez::guiX(startY),
Rez::guiX(endX),
Rez::guiX(endY));
//Base::Console().Message("TRACE -drawPainterPath - making an ELLIPSE @(%.3f,%.3f) R1:%.3f R2:%.3f\n",geom->center.x,geom->center.y, geom->major, geom->minor);
} break;
case TechDrawGeometry::ARCOFELLIPSE: {
TechDrawGeometry::AOE *geom = static_cast<TechDrawGeometry::AOE *>(baseGeom);
pathArc(path, geom->major, geom->minor, geom->angle, geom->largeArc, geom->cw,
geom->endPnt.x, geom->endPnt.y,
geom->startPnt.x, geom->startPnt.y);
pathArc(path,
Rez::guiX(geom->major),
Rez::guiX(geom->minor),
geom->angle,
geom->largeArc,
geom->cw,
Rez::guiX(geom->endPnt.x),
Rez::guiX(geom->endPnt.y),
Rez::guiX(geom->startPnt.x),
Rez::guiX(geom->startPnt.y));
//Base::Console().Message("TRACE -drawPainterPath - making an ARCOFELLIPSE R1:%.3f R2:%.3f From: (%.3f,%.3f) To: (%.3f,%.3f)\n",geom->major, geom->minor,geom->startPnt.x, geom->startPnt.y,geom->endPnt.x, geom->endPnt.y);
} break;
@@ -187,26 +224,26 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
TechDrawGeometry::BezierSegment *geom = static_cast<TechDrawGeometry::BezierSegment *>(baseGeom);
// Move painter to the beginning
path.moveTo(geom->pnts[0].x, geom->pnts[0].y);
path.moveTo(Rez::guiX(geom->pnts[0].x), Rez::guiX(geom->pnts[0].y));
//Base::Console().Message("TRACE -drawPainterPath - making an BEZIER From: (%.3f,%.3f)\n",geom->pnts[0].x,geom->pnts[0].y);
if ( geom->poles == 2 ) {
// Degree 1 bezier = straight line...
path.lineTo(geom->pnts[1].x, geom->pnts[1].y);
path.lineTo(Rez::guiX(geom->pnts[1].x), Rez::guiX(geom->pnts[1].y));
} else if ( geom->poles == 3 ) {
path.quadTo(geom->pnts[1].x, geom->pnts[1].y,
geom->pnts[2].x, geom->pnts[2].y);
path.quadTo(Rez::guiX(geom->pnts[1].x), Rez::guiX(geom->pnts[1].y),
Rez::guiX(geom->pnts[2].x), Rez::guiX(geom->pnts[2].y));
} else if ( geom->poles == 4 ) {
path.cubicTo(geom->pnts[1].x, geom->pnts[1].y,
geom->pnts[2].x, geom->pnts[2].y,
geom->pnts[3].x, geom->pnts[3].y);
path.cubicTo(Rez::guiX(geom->pnts[1].x), Rez::guiX(geom->pnts[1].y),
Rez::guiX(geom->pnts[2].x), Rez::guiX(geom->pnts[2].y),
Rez::guiX(geom->pnts[3].x), Rez::guiX(geom->pnts[3].y));
} else { //can only handle lines,quads,cubes
Base::Console().Error("Bad pole count (%d) for BezierSegment\n",geom->poles);
auto itBez = geom->pnts.begin() + 1;
for (; itBez != geom->pnts.end();itBez++) {
path.lineTo((*itBez).x, (*itBez).y); //show something for debugging
path.lineTo(Rez::guiX((*itBez).x), Rez::guiX((*itBez).y)); //show something for debugging
}
}
} break;
@@ -216,7 +253,7 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
std::vector<TechDrawGeometry::BezierSegment>::const_iterator it = geom->segments.begin();
// Move painter to the beginning of our first segment
path.moveTo(it->pnts[0].x, it->pnts[0].y);
path.moveTo(Rez::guiX(it->pnts[0].x), Rez::guiX(it->pnts[0].y));
//Base::Console().Message("TRACE -drawPainterPath - making an BSPLINE From: (%.3f,%.3f)\n",it->pnts[0].x,it->pnts[0].y);
for ( ; it != geom->segments.end(); ++it) {
@@ -224,16 +261,16 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
// of the first segment, or end of the last
if ( it->poles == 2 ) {
// Degree 1 bezier = straight line...
path.lineTo(it->pnts[1].x, it->pnts[1].y);
path.lineTo(Rez::guiX(it->pnts[1].x), Rez::guiX(it->pnts[1].y));
} else if ( it->poles == 3 ) {
path.quadTo(it->pnts[1].x, it->pnts[1].y,
it->pnts[2].x, it->pnts[2].y);
path.quadTo(Rez::guiX(it->pnts[1].x), Rez::guiX(it->pnts[1].y),
Rez::guiX(it->pnts[2].x), Rez::guiX(it->pnts[2].y));
} else if ( it->poles == 4 ) {
path.cubicTo(it->pnts[1].x, it->pnts[1].y,
it->pnts[2].x, it->pnts[2].y,
it->pnts[3].x, it->pnts[3].y);
path.cubicTo(Rez::guiX(it->pnts[1].x), Rez::guiX(it->pnts[1].y),
Rez::guiX(it->pnts[2].x), Rez::guiX(it->pnts[2].y),
Rez::guiX(it->pnts[3].x), Rez::guiX(it->pnts[3].y));
} else { //can only handle lines,quads,cubes
Base::Console().Error("Bad pole count (%d) for BezierSegment of BSpline geometry\n",it->poles);
path.lineTo(it->pnts[1].x, it->pnts[1].y); //show something for debugging
@@ -243,11 +280,11 @@ QPainterPath QGIViewPart::drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom)
case TechDrawGeometry::GENERIC: {
TechDrawGeometry::Generic *geom = static_cast<TechDrawGeometry::Generic *>(baseGeom);
path.moveTo(geom->points[0].x, geom->points[0].y);
path.moveTo(Rez::guiX(geom->points[0].x), Rez::guiX(geom->points[0].y));
std::vector<Base::Vector2d>::const_iterator it = geom->points.begin();
//Base::Console().Message("TRACE -drawPainterPath - making an GENERIC From: (%.3f,%.3f)\n",geom->points[0].x, geom->points[0].y);
for(++it; it != geom->points.end(); ++it) {
path.lineTo((*it).x, (*it).y);
path.lineTo(Rez::guiX((*it).x), Rez::guiX((*it).y));
//Base::Console().Message(">>>> To: (%.3f,%.3f)\n",(*it).x, (*it).y);
}
} break;
@@ -280,6 +317,7 @@ void QGIViewPart::updateView(bool update)
viewPart->isTouched() ||
viewPart->Source.isTouched() ||
viewPart->Direction.isTouched() ||
viewPart->Rotation.isTouched() ||
viewPart->Scale.isTouched() ||
viewPart->HardHidden.isTouched() ||
viewPart->SmoothVisible.isTouched() ||
@@ -288,7 +326,10 @@ void QGIViewPart::updateView(bool update)
viewPart->SmoothHidden.isTouched() ||
viewPart->SeamHidden.isTouched() ||
viewPart->IsoHidden.isTouched() ||
viewPart->IsoCount.isTouched() ) {
viewPart->IsoCount.isTouched() ||
viewPart->ShowSectionLine.isTouched() ||
viewPart->HorizCenterLine.isTouched() ||
viewPart->VertCenterLine.isTouched() ) {
draw();
} else if (update ||
viewPart->LineWidth.isTouched() ||
@@ -311,7 +352,8 @@ void QGIViewPart::updateView(bool update)
void QGIViewPart::draw() {
drawViewPart();
drawMatting();
drawBorder();
// drawBorder();
QGIView::draw();
}
void QGIViewPart::drawViewPart()
@@ -336,20 +378,54 @@ void QGIViewPart::drawViewPart()
if (viewPart->handleFaces()) {
// Draw Faces
std::vector<TechDraw::DrawHatch*> hatchObjs = viewPart->getHatches();
std::vector<TechDraw::DrawGeomHatch*> geomObjs = viewPart->getGeomHatches();
const std::vector<TechDrawGeometry::Face *> &faceGeoms = viewPart->getFaceGeometry();
std::vector<TechDrawGeometry::Face *>::const_iterator fit = faceGeoms.begin();
for(int i = 0 ; fit != faceGeoms.end(); fit++, i++) {
QGIFace* newFace = drawFace(*fit,i);
newFace->isHatched(false);
newFace->setFillMode(QGIFace::PlainFill);
TechDraw::DrawHatch* fHatch = faceIsHatched(i,hatchObjs);
if (fHatch) {
if (!fHatch->HatchPattern.isEmpty()) {
App::Color hColor = fHatch->HatchColor.getValue();
newFace->setHatchColor(hColor.asCSSString());
newFace->setHatch(fHatch->HatchPattern.getValue());
TechDraw::DrawGeomHatch* fGeom = faceIsGeomHatched(i,geomObjs);
if (fGeom) {
const std::vector<std::string> &sourceNames = fGeom->Source.getSubValues();
if (!sourceNames.empty()) {
int fdx = TechDraw::DrawUtil::getIndexFromName(sourceNames.at(0));
std::vector<LineSet> lineSets = fGeom->getDrawableLines(fdx);
if (!lineSets.empty()) {
newFace->clearLineSets();
for (auto& ls: lineSets) {
QPainterPath bigPath;
for (auto& g: ls.getGeoms()) {
QPainterPath smallPath = drawPainterPath(g);
bigPath.addPath(smallPath);
}
newFace->addLineSet(bigPath,ls.getDashSpec());
}
newFace->isHatched(true);
newFace->setFillMode(QGIFace::GeomHatchFill);
newFace->setHatchScale(fGeom->ScalePattern.getValue());
newFace->setHatchFile(fGeom->FilePattern.getValue());
Gui::ViewProvider* gvp = QGIView::getViewProvider(fGeom);
ViewProviderGeomHatch* geomVp = dynamic_cast<ViewProviderGeomHatch*>(gvp);
if (geomVp != nullptr) {
newFace->setHatchColor(geomVp->ColorPattern.getValue());
newFace->setLineWeight(geomVp->WeightPattern.getValue());
}
}
}
}
newFace->setDrawEdges(false);
} else if (fHatch) {
if (!fHatch->HatchPattern.isEmpty()) {
newFace->isHatched(true);
newFace->setFillMode(QGIFace::FromFile);
newFace->setHatchFile(fHatch->HatchPattern.getValue());
newFace->setHatchScale(fHatch->HatchScale.getValue());
newFace->setHatchColor(fHatch->HatchColor.getValue());
}
}
newFace->setDrawEdges(true);
newFace->setZValue(ZVALUE::FACE);
newFace->draw();
newFace->setPrettyNormal();
}
}
@@ -412,15 +488,15 @@ void QGIViewPart::drawViewPart()
if (showCenters) {
QGICMark* cmItem = new QGICMark(i);
addToGroup(cmItem);
cmItem->setPos((*vert)->pnt.x, (*vert)->pnt.y); //this is in ViewPart coords
cmItem->setThick(0.5 * lineWidth * lineScaleFactor); //need minimum?
cmItem->setPos(Rez::guiX((*vert)->pnt.x), Rez::guiX((*vert)->pnt.y));
cmItem->setThick(0.5 * lineWidth); //need minimum?
cmItem->setSize( cAdjust * lineWidth * vertexScaleFactor);
cmItem->setZValue(ZVALUE::VERTEX);
}
} else {
QGIVertex *item = new QGIVertex(i);
addToGroup(item);
item->setPos((*vert)->pnt.x, (*vert)->pnt.y); //this is in ViewPart coords
item->setPos(Rez::guiX((*vert)->pnt.x), Rez::guiX((*vert)->pnt.y));
item->setRadius(lineWidth * vertexScaleFactor);
item->setZValue(ZVALUE::VERTEX);
}
@@ -460,7 +536,7 @@ QGIFace* QGIViewPart::drawFace(TechDrawGeometry::Face* f, int idx)
QGIFace* gFace = new QGIFace(idx);
addToGroup(gFace);
gFace->setPos(0.0,0.0);
gFace->setPath(facePath);
gFace->setOutline(facePath);
//debug a path
//std::stringstream faceId;
//faceId << "facePath " << idx;
@@ -511,6 +587,11 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
!viewSection) {
return;
}
if (!viewSection->hasGeometry()) {
return;
}
if (b) {
QGISectionLine* sectionLine = new QGISectionLine();
addToGroup(sectionLine);
@@ -542,15 +623,14 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
Base::Vector3d org = viewSection->SectionOrigin.getValue();
double scale = viewPart->Scale.getValue();
Base::Vector3d pOrg = scale * viewPart->projectPoint(org);
//pOrg.y = -1 * pOrg.y;
//now project pOrg onto arrowDir
Base::Vector3d displace;
displace.ProjectToLine(pOrg, arrowDir);
Base::Vector3d offset = pOrg + displace;
sectionLine->setPos(offset.x,offset.y);
sectionLine->setPos(Rez::guiX(offset.x),Rez::guiX(offset.y));
double sectionSpan;
double sectionFudge = 10.0;
double sectionFudge = Rez::guiX(10.0);
double xVal, yVal;
if (horiz) {
sectionSpan = m_border->rect().width() + sectionFudge;
@@ -562,9 +642,10 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
yVal = sectionSpan / 2.0;
}
sectionLine->setBounds(-xVal,-yVal,xVal,yVal);
sectionLine->setWidth(viewPart->LineWidth.getValue()); //TODO: add fudge to make sectionLine thinner than reg lines?
sectionLine->setFont(m_font,6.0);
sectionLine->setWidth(Rez::guiX(viewPart->LineWidth.getValue())); //TODO: add fudge to make sectionLine thinner than reg lines?
sectionLine->setFont(m_font,Rez::guiX(6.0));
sectionLine->setZValue(ZVALUE::SECTIONLINE);
sectionLine->setRotation(- viewPart->Rotation.getValue());
sectionLine->draw();
}
}
@@ -594,6 +675,7 @@ void QGIViewPart::drawCenterLines(bool b)
centerLine->setBounds(-xVal,-yVal,xVal,yVal);
//centerLine->setWidth(viewPart->LineWidth.getValue());
centerLine->setZValue(ZVALUE::SECTIONLINE);
centerLine->setRotation(- viewPart->Rotation.getValue());
centerLine->draw();
}
if (vert) {
@@ -606,6 +688,7 @@ void QGIViewPart::drawCenterLines(bool b)
centerLine->setBounds(-xVal,-yVal,xVal,yVal);
//centerLine->setWidth(viewPart->LineWidth.getValue());
centerLine->setZValue(ZVALUE::SECTIONLINE);
centerLine->setRotation(- viewPart->Rotation.getValue());
centerLine->draw();
}
}
@@ -625,7 +708,7 @@ void QGIViewPart::drawMatting()
double radius = dvd->Radius.getValue() * scale;
QGIMatting* mat = new QGIMatting();
addToGroup(mat);
mat->setRadius(radius);
mat->setRadius(Rez::guiX(radius));
mat->setPos(0.0,0.0);
mat->draw();
mat->show();
@@ -804,6 +887,21 @@ TechDraw::DrawHatch* QGIViewPart::faceIsHatched(int i,std::vector<TechDraw::Draw
return result;
}
TechDraw::DrawGeomHatch* QGIViewPart::faceIsGeomHatched(int i,std::vector<TechDraw::DrawGeomHatch*> geomObjs) const
{
TechDraw::DrawGeomHatch* result = nullptr;
for (auto& h:geomObjs) {
const std::vector<std::string> &sourceNames = h->Source.getSubValues();
int fdx = TechDraw::DrawUtil::getIndexFromName(sourceNames.at(0));
if (fdx == i) {
result = h;
break;
}
}
return result;
}
void QGIViewPart::dumpPath(const char* text,QPainterPath path)
{
QPainterPath::Element elem;

View File

@@ -34,6 +34,7 @@ namespace TechDraw {
class DrawViewPart;
class DrawViewSection;
class DrawHatch;
class DrawGeomHatch;
}
namespace TechDrawGui
@@ -89,6 +90,7 @@ protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
TechDraw::DrawHatch* faceIsHatched(int i,std::vector<TechDraw::DrawHatch*> hatchObjs) const;
TechDraw::DrawGeomHatch* faceIsGeomHatched(int i,std::vector<TechDraw::DrawGeomHatch*> geomObjs) const;
void dumpPath(const char* text,QPainterPath path);
void removePrimitives(void);
void removeDecorations(void);

View File

@@ -26,6 +26,8 @@
#include <QAction>
#include <QApplication>
#include <QContextMenuEvent>
#include <QFile>
#include <QFileInfo>
#include <QGraphicsScene>
#include <QMenu>
#include <QMouseEvent>
@@ -38,10 +40,14 @@
#include <qmath.h>
#include <Base/Console.h>
#include <App/Material.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include "ZVALUE.h"
#include "ViewProviderViewSection.h"
#include "QGIFace.h"
#include "QGIViewSection.h"
@@ -64,7 +70,13 @@ void QGIViewSection::drawSectionFace()
return;
}
if ( !section->hasGeometry() || !section->ShowCutSurface.getValue() ) {
if ( !section->hasGeometry()) {
return;
}
Gui::ViewProvider* gvp = QGIView::getViewProvider(section);
ViewProviderViewSection* sectionVp = dynamic_cast<ViewProviderViewSection*>(gvp);
if ((sectionVp == nullptr) ||
(!sectionVp->ShowCutSurface.getValue())) {
return;
}
@@ -73,9 +85,11 @@ void QGIViewSection::drawSectionFace()
//Base::Console().Log("INFO - QGIViewSection::drawSectionFace - No sectionFaces available. Check Section plane.\n");
return;
}
std::vector<TechDrawGeometry::Face *>::iterator fit = sectionFaces.begin();
QColor faceColor = section->CutSurfaceColor.getValue().asValue<QColor>();
for(; fit != sectionFaces.end(); fit++) {
QColor faceColor = (sectionVp->CutSurfaceColor.getValue()).asValue<QColor>();
int i = 0;
for(; fit != sectionFaces.end(); fit++, i++) {
QGIFace* newFace = drawFace(*fit,-1);
newFace->setZValue(ZVALUE::SECTIONFACE);
if (section->showSectionEdges()) {
@@ -83,12 +97,40 @@ void QGIViewSection::drawSectionFace()
} else {
newFace->setDrawEdges(false);
}
if (section->HatchCutSurface.getValue()) {
App::Color hColor = section->HatchColor.getValue();
newFace->setHatchColor(hColor.asCSSString());
newFace->setHatch(section->HatchPattern.getValue());
}
newFace->setFill(faceColor, Qt::SolidPattern);
if (sectionVp->HatchCutSurface.getValue()) {
newFace->isHatched(true);
newFace->setFillMode(QGIFace::FromFile);
newFace->setHatchColor(sectionVp->HatchColor.getValue());
newFace->setHatchScale(section->HatchScale.getValue());
std::string hatchFile = section->FileHatchPattern.getValue();
newFace->setHatchFile(hatchFile);
std::string patternName = section->NameGeomPattern.getValue();
QFileInfo hfi(QString::fromUtf8(hatchFile.data(),hatchFile.size()));
if (hfi.isReadable()) {
QString ext = hfi.suffix();
if ((ext.toUpper() == QString::fromUtf8("PAT")) &&
!patternName.empty() ) {
newFace->setFillMode(QGIFace::GeomHatchFill);
newFace->setLineWeight(sectionVp->WeightPattern.getValue());
std::vector<LineSet> lineSets = section->getDrawableLines(i);
if (!lineSets.empty()) {
newFace->clearLineSets();
for (auto& ls: lineSets) {
QPainterPath bigPath;
for (auto& g: ls.getGeoms()) {
QPainterPath smallPath = drawPainterPath(g);
bigPath.addPath(smallPath);
}
newFace->addLineSet(bigPath,ls.getDashSpec());
}
}
}
}
}
newFace->draw();
newFace->setPrettyNormal();
newFace->setAcceptHoverEvents(false);
newFace->setFlag(QGraphicsItem::ItemIsSelectable, false);

View File

@@ -135,7 +135,7 @@ void QGIViewSymbol::symbolToSvg(QByteArray qba)
prepareGeometryChange();
if (!m_svgItem->load(&qba)) {
Base::Console().Error("Error - Could not load Symbol into SVG renderer for %s\n", getViewObject()->getNameInDocument());
Base::Console().Error("Error - Could not load Symbol into SVG renderer for %s\n", getViewName());
}
m_svgItem->centerAt(0.,0.);
}

View File

@@ -60,7 +60,7 @@
#include <Mod/TechDraw/App/DrawViewSpreadsheet.h>
#include <Mod/TechDraw/App/DrawViewImage.h>
#include "Rez.h"
#include "QGIDrawingTemplate.h"
#include "QGITemplate.h"
#include "QGISVGTemplate.h"
@@ -150,8 +150,8 @@ void QGVPage::drawBackground(QPainter *p, const QRectF &)
pageHeight = 297;
if ( m_vpPage->getDrawPage()->hasValidTemplate() ) {
pageWidth = m_vpPage->getDrawPage()->getPageWidth();
pageHeight = m_vpPage->getDrawPage()->getPageHeight();
pageWidth = Rez::guiX(m_vpPage->getDrawPage()->getPageWidth());
pageHeight = Rez::guiX(m_vpPage->getDrawPage()->getPageHeight());
}
// Draw the white page
@@ -180,8 +180,8 @@ int QGVPage::addView(QGIView *view)
QGIView *parent = 0;
parent = findParent(view);
QPointF viewPos(view->getViewObject()->X.getValue(),
view->getViewObject()->Y.getValue() * -1);
QPointF viewPos(Rez::guiX(view->getViewObject()->X.getValue()),
Rez::guiX(view->getViewObject()->Y.getValue() * -1));
if(parent) {
// Transfer the child vierw to the parent
@@ -198,6 +198,80 @@ int QGVPage::addView(QGIView *view)
return views.size();
}
int QGVPage::removeView(QGIView *view)
{
std::vector<QGIView *> qviews = views;
std::vector<QGIView *> newViews;
std::vector<QGIView *>::iterator qvit = qviews.begin();
std::vector<QGIView *>::iterator qvDel = qviews.end();
for (; qvit != qviews.end(); qvit++) {
if ((*qvit) == view) {
qvDel = qvit;
break;
}
}
if (qvDel == qviews.end()) { //didn't find view in views
return views.size();
}
removeViewFromScene(view);
qviews.erase(qvDel);
views = qviews;
delete view;
return views.size();
}
int QGVPage::removeView(const TechDraw::DrawView* dv)
{
std::vector<QGIView *> newViews;
QList<QGraphicsItem *> items = scene()->items();
QString qsName = QString::fromUtf8(dv->getNameInDocument());
bool found = false;
QGIView* ourItem = nullptr;
for (auto& i:items) {
if (qsName == i->data(1).toString()) { //is there really a QGIV for this DV in scene?
found = true;
ourItem = static_cast<QGIView*>(i);
break;
}
}
if (found) {
for (auto&v :views) {
if (ourItem != v) {
newViews.push_back(v);
}
}
removeViewFromScene(ourItem);
delete ourItem;
views = newViews;
}
return views.size();
}
void QGVPage::removeViewFromScene(QGIView *view)
{
QGraphicsItemGroup* grp = view->group();
if (grp) {
grp->removeFromGroup(view);
}
if (view->parentItem()) { //not top level
view->setParentItem(0);
}
if (view->scene()) {
view->scene()->removeItem(view);
}
}
QGIView * QGVPage::addViewPart(TechDraw::DrawViewPart *part)
{
auto viewPart( new QGIViewPart );
@@ -258,7 +332,7 @@ QGIView * QGVPage::addDrawViewAnnotation(TechDraw::DrawViewAnnotation *view)
QGIView * QGVPage::addDrawViewSymbol(TechDraw::DrawViewSymbol *view)
{
QPoint qp(view->X.getValue(),view->Y.getValue());
//QPoint qp(view->X.getValue(),view->Y.getValue());
// This essentially adds a null view feature to ensure view size is consistent
auto qview( new QGIViewSymbol );
@@ -272,7 +346,7 @@ QGIView * QGVPage::addDrawViewClip(TechDraw::DrawViewClip *view)
{
auto qview( new QGIViewClip );
qview->setPosition(view->X.getValue(), view->Y.getValue());
qview->setPosition(Rez::guiX(view->X.getValue()), Rez::guiX(view->Y.getValue()));
qview->setViewFeature(view);
addView(qview);
@@ -291,7 +365,7 @@ QGIView * QGVPage::addDrawViewSpreadsheet(TechDraw::DrawViewSpreadsheet *view)
QGIView * QGVPage::addDrawViewImage(TechDraw::DrawViewImage *view)
{
QPoint qp(view->X.getValue(),view->Y.getValue());
//QPoint qp(view->X.getValue(),view->Y.getValue());
auto qview( new QGIViewImage );
qview->setViewFeature(view);
@@ -343,8 +417,7 @@ QGIView * QGVPage::findView(App::DocumentObject *obj) const
if(obj) {
const std::vector<QGIView *> qviews = views;
for(std::vector<QGIView *>::const_iterator it = qviews.begin(); it != qviews.end(); ++it) {
TechDraw::DrawView *fview = (*it)->getViewObject();
if(fview && strcmp(obj->getNameInDocument(), fview->getNameInDocument()) == 0)
if(strcmp(obj->getNameInDocument(), (*it)->getViewName()) == 0)
return *it;
}
}
@@ -367,8 +440,7 @@ QGIView * QGVPage::findParent(QGIView *view) const
std::vector<App::DocumentObject *> objs = dim->References2D.getValues();
// Attach the dimension to the first object's group
for(std::vector<QGIView *>::const_iterator it = qviews.begin(); it != qviews.end(); ++it) {
TechDraw::DrawView *viewObj = (*it)->getViewObject();
if(strcmp(viewObj->getNameInDocument(), objs.at(0)->getNameInDocument()) == 0) {
if(strcmp((*it)->getViewName(), objs.at(0)->getNameInDocument()) == 0) {
return *it;
}
}
@@ -506,22 +578,19 @@ void QGVPage::saveSvg(QString filename)
docName;
//Base::Console().Message("TRACE - saveSVG - page width: %d height: %d\n",width,height); //A4 297x210
//with Rez set to 10 we make a dot 10 times/mm => 254dpi?
// 12 => 304.8 dpi? approx printer dpi 300dpi
QSvgGenerator svgGen;
svgGen.setFileName(filename);
svgGen.setSize(QSize((int) page->getPageWidth(), (int)page->getPageHeight()));
svgGen.setViewBox(QRect(0, 0, page->getPageWidth(), page->getPageHeight()));
//TODO: Exported Svg file is not quite right. <svg width="301.752mm" height="213.36mm" viewBox="0 0 297 210"... A4: 297x210
// Page too small (A4 vs Letter? margins?)
//TODO: text in Qt is in mm (actually scene units). text in SVG is points(?). fontsize in export file is too small by 1/2.835.
// resize all textItem before export?
// postprocess generated file to mult all font-size attrib by 2.835 to get pts?
// duplicate all textItems and only show the appropriate one for screen/print vs export?
svgGen.setSize(QSize((int) Rez::guiX(page->getPageWidth()), (int) Rez::guiX(page->getPageHeight()))); //expects pixels, gets mm
//"By default this property is set to QSize(-1, -1), which indicates that the generator should not output
// the width and height attributes of the <svg> element." >> but Inkscape won't read it without size info??
svgGen.setViewBox(QRect(0, 0, Rez::guiX(page->getPageWidth()), Rez::guiX(page->getPageHeight())));
svgGen.setResolution(Rez::guiX(25.4)); // docs say this is DPI. 1dot/mm so 25.4dpi
// TODO: Was svgGen.setResolution(25.4000508); // mm/inch?? docs say this is DPI //really "user space units/inch"?
svgGen.setResolution(25); // mm/inch?? docs say this is DPI
//svgGen.setResolution(600); // resulting page is ~12.5x9mm
//svgGen.setResolution(96); // page is ~78x55mm
svgGen.setTitle(QObject::tr("FreeCAD SVG Export"));
svgGen.setDescription(svgDescription);
@@ -532,8 +601,8 @@ void QGVPage::saveSvg(QString filename)
scene()->update();
viewport()->repaint();
double width = page->getPageWidth();
double height = page->getPageHeight();
double width = Rez::guiX(page->getPageWidth());
double height = Rez::guiX(page->getPageHeight());
QRectF sourceRect(0.0,-height,width,height);
QRectF targetRect;

View File

@@ -27,6 +27,7 @@
#include <QGraphicsScene>
namespace TechDraw {
class DrawView;
class DrawViewPart;
class DrawProjGroup;
class DrawViewDimension;
@@ -78,7 +79,11 @@ public:
void addDimToParent(QGIViewDimension* dim, QGIView* parent);
const std::vector<QGIView *> & getViews() const { return views; }
int addView(QGIView * view);
int removeView(QGIView *view);
int removeView(const TechDraw::DrawView* dv);
void setViews(const std::vector<QGIView *> &view) {views = view; }
void setPageTemplate(TechDraw::DrawTemplate *pageTemplate);
@@ -106,6 +111,8 @@ protected:
static QColor SelectColor;
static QColor PreselectColor;
QColor getBackgroundColor();
void removeViewFromScene(QGIView *view);
QGITemplate *pageTemplate;
std::vector<QGIView *> views;

View File

@@ -30,6 +30,11 @@
<file>icons/TechDraw_Dimension_Vertical.svg</file>
<file>icons/TechDraw_Dimension_Link.svg</file>
<file>icons/preferences-techdraw.svg</file>
<file>icons/arrowdot.svg</file>
<file>icons/arrowopendot.svg</file>
<file>icons/arrowfilled.svg</file>
<file>icons/arrowopen.svg</file>
<file>icons/arrowtick.svg</file>
<file>icons/actions/techdraw-new-default.svg</file>
<file>icons/actions/techdraw-new-pick.svg</file>
<file>icons/actions/techdraw-view.svg</file>
@@ -44,6 +49,7 @@
<file>icons/actions/techdraw-saveSVG.svg</file>
<file>icons/actions/techdraw-viewsection.svg</file>
<file>icons/actions/techdraw-hatch.svg</file>
<file>icons/actions/techdraw-geomhatch.svg</file>
<file>icons/actions/techdraw-toggleframe.svg</file>
<file>icons/actions/techdraw-projgroup.svg</file>
<file>icons/actions/techdraw-spreadsheet.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg4024">
<defs
id="defs4026" />
<metadata
id="metadata4029">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<g
transform="translate(-1.0575472,0.61016946)"
id="g4020">
<path
d="m -18.999999,35.857143 a 11.714286,11.428572 0 1 1 -23.428572,0 11.714286,11.428572 0 1 1 23.428572,0 z"
transform="matrix(0.74568413,0,0,0.76432623,53.996092,-4.0167247)"
id="path3769"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:5.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="6.8774428"
y="19.809925"
id="rect3805"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg3942">
<defs
id="defs3944" />
<metadata
id="metadata3947">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<g
transform="translate(5.495789,-0.12462666)"
id="g3801">
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3803"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<g
id="g3938">
<path
d="M 19,31.428572 8.3448741,16.437454 26.655126,14.705404 z"
transform="matrix(0.82772257,0.51753701,-0.59559817,0.71923839,18.136046,-0.16490738)"
id="path2993"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:5.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3805"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg2985">
<defs
id="defs2987" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<g
transform="translate(3.4375,-0.13060184)"
id="g3807">
<g
id="g3796">
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3763"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3799"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="17.57655"
y="-10.165521"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect3773"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="-16.567656"
y="-44.272964"
transform="matrix(0.70710678,-0.70710678,-0.70710678,-0.70710678,0,0)"
id="rect3775"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
d="m 35.392858,21.017857 2.874999,3.071429 -3.035714,3.303571"
id="path3792"
style="color:#000000;fill:#000000;stroke:#000000;stroke-width:0.28200001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
d="m 35.200831,24.273314 -0.129031,-0.129898 0.133942,-0.133048 0.133942,-0.133048 0,0.262945 c 0,0.144621 -0.0022,0.262946 -0.0049,0.262946 -0.0027,0 -0.06298,-0.05845 -0.133942,-0.129897 z"
id="path3794"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.10714286;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:5.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg3816">
<defs
id="defs3818" />
<metadata
id="metadata3821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<g
transform="translate(3.3580721,4.7683716e-7)"
id="g3801">
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3803"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3805"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<path
d="m -18.999999,35.857143 a 11.714286,11.428572 0 1 1 -23.428572,0 11.714286,11.428572 0 1 1 23.428572,0 z"
transform="matrix(0.74568413,0,0,0.76432623,54.118369,-3.4065552)"
id="path3771"
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:5.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg2985">
<defs
id="defs2987" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-1.2369402,2.0609187)"
id="g3106">
<g
transform="translate(10.308369,-1.9117699)"
id="g3796">
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3763"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="24.142857"
height="8.7142859"
rx="1.4997782"
ry="1.7378116"
x="2.8571429"
y="19.642857"
id="rect3799"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.28200001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<rect
width="12.071428"
height="4.3571429"
rx="0.74988908"
ry="0.86890578"
x="-0.50094396"
y="31.798487"
transform="matrix(-0.70710678,0.70710678,0.70710678,0.70710678,0,0)"
id="rect3773"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.141;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
width="12.071428"
height="4.3571429"
rx="0.74988908"
ry="0.86890578"
x="-17.214378"
y="31.541357"
transform="matrix(-0.70710678,0.70710678,0.70710678,0.70710678,0,0)"
id="rect3104"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.141;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,131 @@
/***************************************************************************
* Copyright (c) 2016 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include "Rez.h"
using namespace TechDrawGui;
//*** initial static var outside methods!
double Rez::m_rezFactor = Rez::getParameter();
//***
double Rez::getRezFactor()
{
return Rez::m_rezFactor;
}
void Rez::setRezFactor(double f)
{
Rez::m_rezFactor = f;
}
//turn App side value to Gui side value
double Rez::guiX(double x)
{
return getRezFactor() * x;
}
Base::Vector2d Rez::guiX(Base::Vector2d v)
{
Base::Vector2d result(guiX(v.y),guiX(v.y));
return result;
}
Base::Vector3d Rez::guiX(Base::Vector3d v)
{
Base::Vector3d result(guiX(v.x),guiX(v.y),guiX(v.z));
return result;
}
//turn Gui side value to App side value
double Rez::appX(double x)
{
return x / getRezFactor();
}
Base::Vector2d Rez::appX(Base::Vector2d v)
{
Base::Vector2d result(appX(v.y),appX(v.y));
return result;
}
Base::Vector3d Rez::appX(Base::Vector3d v)
{
Base::Vector3d result(appX(v.x),appX(v.y),appX(v.z));
return result;
}
//Misc conversions
QPointF Rez::guiPt(QPointF p)
{
QPointF result = p;
result *= getRezFactor();
return result;
}
QPointF Rez::appPt(QPointF p)
{
QPointF result(appX(p.x()),appX(p.y()));
return result;
}
QRectF Rez::guiRect(QRectF r)
{
QRectF result(guiX(r.left()),
guiX(r.top()),
guiX(r.width()),
guiX(r.height()));
return result;
}
QSize Rez::guiSize(QSize s)
{
QSize result((int)guiX(s.width()),(int)guiX(s.height()));
return result;
}
QSize Rez::appSize(QSize s)
{
QSize result((int)appX(s.width()),(int)appX(s.height()));
return result;
}
double Rez::getParameter()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Rez");
double rezFactor = hGrp->GetFloat("Resolution", 1.0);
return rezFactor;
}

View File

@@ -0,0 +1,63 @@
/***************************************************************************
* Copyright (c) 2016 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef DRAWINGGUI_REZ_H
#define DRAWINGGUI_REZ_H
#include <QPointF>
#include <QRectF>
#include <QSize>
#include <Base/Vector3D.h>
#include <Base/Tools2D.h>
namespace TechDrawGui
{
/// Functions to handle mm resolution conversion
class TechDrawGuiExport Rez
{
public:
static double getParameter(void);
static double getRezFactor(void);
static void setRezFactor(double f);
//turn App side value to Gui side value
static double guiX(double x);
static Base::Vector2d guiX(Base::Vector2d v);
static Base::Vector3d guiX(Base::Vector3d v);
//turn Gui side value to App side value
static double appX(double x);
static Base::Vector2d appX(Base::Vector2d v);
static Base::Vector3d appX(Base::Vector3d v);
static QPointF guiPt(QPointF p);
static QPointF appPt(QPointF p);
static QRectF guiRect(QRectF r);
static QSize guiSize(QSize s);
static QSize appSize(QSize s);
private:
static double m_rezFactor;
};
} //end namespace TechDrawGui
#endif

View File

@@ -0,0 +1,195 @@
/***************************************************************************
* Copyright (c) 2017 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <cmath>
#endif // #ifndef _PreComp_
#include <Base/Console.h>
#include <Base/Vector3D.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Mod/TechDraw/App/HatchLine.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "ViewProviderGeomHatch.h"
#include "TaskGeomHatch.h"
#include <Mod/TechDraw/Gui/ui_TaskGeomHatch.h>
using namespace Gui;
using namespace TechDraw;
using namespace TechDrawGui;
TaskGeomHatch::TaskGeomHatch(TechDraw::DrawGeomHatch* inHatch,TechDrawGui::ViewProviderGeomHatch* inVp) :
ui(new Ui_TaskGeomHatch),
m_hatch(inHatch),
m_Vp(inVp)
{
ui->setupUi(this);
connect(ui->fcFile, SIGNAL(fileNameSelected( const QString & )), this, SLOT(onFileChanged(void)));
m_source = m_hatch->Source.getValue();
getParameters();
initUi();
}
TaskGeomHatch::~TaskGeomHatch()
{
delete ui;
}
void TaskGeomHatch::initUi()
{
ui->fcFile->setFileName(QString::fromUtf8(m_file.data(), m_file.size()));
std::vector<std::string> names = HatchLine::getPatternList(m_file);
QStringList qsNames = listToQ(names);
ui->cbName->addItems(qsNames);
ui->sbScale->setValue(m_scale);
ui->sbWeight->setValue(m_weight);
ui->ccColor->setColor(m_color.asValue<QColor>());
}
//move values from screen to DocObjs
void TaskGeomHatch::updateValues()
{
m_file = (ui->fcFile->fileName()).toUtf8().constData();
m_hatch->FilePattern.setValue(m_file);
QString cText = ui->cbName->currentText();
m_name = cText.toUtf8().constData();
m_hatch->NamePattern.setValue(m_name);
m_scale = ui->sbScale->value();
m_hatch->ScalePattern.setValue(m_scale);
m_color.setValue<QColor>(ui->ccColor->color());
m_Vp->ColorPattern.setValue(m_color);
m_weight = ui->sbWeight->value();
m_Vp->WeightPattern.setValue(m_weight);
}
QStringList TaskGeomHatch::listToQ(std::vector<std::string> in)
{
QStringList result;
for (auto& s: in) {
QString qs = QString::fromUtf8(s.data(), s.size());
result.append(qs);
}
return result;
}
void TaskGeomHatch::onFileChanged(void)
{
m_file = ui->fcFile->fileName().toUtf8().constData();
std::vector<std::string> names = HatchLine::getPatternList(m_file);
QStringList qsNames = listToQ(names);
ui->cbName->clear();
ui->cbName->addItems(qsNames);
}
bool TaskGeomHatch::accept()
{
updateValues();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
return true;
}
bool TaskGeomHatch::reject()
{
std::string HatchName = m_hatch->getNameInDocument();
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().removeObject('%s')",HatchName.c_str());
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
m_source->touch();
m_source->getDocument()->recompute();
return false;
}
void TaskGeomHatch::getParameters()
{
m_file = m_hatch->FilePattern.getValue();
m_name = m_hatch->NamePattern.getValue();
m_scale = m_hatch->ScalePattern.getValue();
m_color = m_Vp->ColorPattern.getValue();
m_weight = m_Vp->WeightPattern.getValue();
}
void TaskGeomHatch::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TaskDlgGeomHatch::TaskDlgGeomHatch(TechDraw::DrawGeomHatch* inHatch, TechDrawGui::ViewProviderGeomHatch* inVp) :
TaskDialog()
{
widget = new TaskGeomHatch(inHatch,inVp);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("TechDraw_Tree_View"),
widget->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskDlgGeomHatch::~TaskDlgGeomHatch()
{
}
void TaskDlgGeomHatch::update()
{
//widget->updateTask();
}
//==== calls from the TaskView ===============================================================
void TaskDlgGeomHatch::open()
{
}
void TaskDlgGeomHatch::clicked(int i)
{
Q_UNUSED(i);
}
bool TaskDlgGeomHatch::accept()
{
widget->accept();
return true;
}
bool TaskDlgGeomHatch::reject()
{
widget->reject();
return true;
}
#include <Mod/TechDraw/Gui/moc_TaskGeomHatch.cpp>

View File

@@ -0,0 +1,116 @@
/***************************************************************************
* Copyright (c) 2017 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TASKGEOMHATCH_H
#define GUI_TASKVIEW_TASKGEOMHATCH_H
#include <App/Material.h>
#include <Gui/TaskView/TaskView.h>
#include <Gui/TaskView/TaskDialog.h>
#include <Mod/TechDraw/Gui/ui_TaskGeomHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
class Ui_TaskGeomHatch;
namespace App
{
class DocumentObject;
}
namespace TechDrawGui
{
class ViewProviderGeomHatch;
class TaskGeomHatch : public QWidget
{
Q_OBJECT
public:
TaskGeomHatch(TechDraw::DrawGeomHatch* inHatch,TechDrawGui::ViewProviderGeomHatch* inVp);
~TaskGeomHatch();
public:
virtual bool accept();
virtual bool reject();
protected Q_SLOTS:
void onFileChanged(void);
protected:
void changeEvent(QEvent *e);
void initUi();
// bool resetUi();
void updateValues();
void getParameters();
QStringList listToQ(std::vector<std::string> in);
private:
Ui_TaskGeomHatch * ui;
TechDraw::DrawGeomHatch* m_hatch;
TechDrawGui::ViewProviderGeomHatch* m_Vp;
App::DocumentObject* m_source;
std::string m_file;
std::string m_name;
double m_scale;
double m_weight;
App::Color m_color;
};
class TaskDlgGeomHatch : public Gui::TaskView::TaskDialog
{
Q_OBJECT
public:
TaskDlgGeomHatch(TechDraw::DrawGeomHatch* inHatch,TechDrawGui::ViewProviderGeomHatch* inVp);
~TaskDlgGeomHatch();
public:
/// is called the TaskView when the dialog is opened
virtual void open();
/// is called by the framework if an button is clicked which has no accept or reject role
virtual void clicked(int);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
/// is called by the framework if the dialog is rejected (Cancel)
virtual bool reject();
/// is called by the framework if the user presses the help button
virtual void helpRequested() { return;}
virtual bool isAllowedAlterDocument(void) const
{ return false; }
void update();
protected:
private:
TaskGeomHatch * widget;
Gui::TaskView::TaskBox* taskbox;
};
} //namespace TechDrawGui
#endif // #ifndef GUI_TASKVIEW_TASKGEOMHATCH_H

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TechDrawGui::TaskGeomHatch</class>
<widget class="QWidget" name="TechDrawGui::TaskGeomHatch">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>265</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Apply Geometric Hatch to Face</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Define your pattern</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0,1">
<item row="0" column="1">
<widget class="Gui::FileChooser" name="fcFile">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The PAT file containing your pattern</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Pattern File</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,1">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Pattern Name</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Line Weight</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Pattern Scale</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Line Color</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="cbName">
<property name="toolTip">
<string>Name of pattern within file</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::ColorButton" name="ccColor">
<property name="toolTip">
<string>Color of pattern lines</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="sbScale">
<property name="toolTip">
<string>Enlarges/shrinks the pattern</string>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="sbWeight">
<property name="toolTip">
<string>Thickness of lines within the pattern</string>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::FileChooser</class>
<extends>QWidget</extends>
<header>Gui/FileDialog.h</header>
</customwidget>
<customwidget>
<class>Gui::ColorButton</class>
<extends>QPushButton</extends>
<header>Gui/Widgets.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../../Documents/CAD/DrawingModule/Resources/TechDraw.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -480,6 +480,8 @@ bool TaskProjGroup::reject()
PageName.c_str(),multiViewName.c_str());
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().removeObject('%s')",multiViewName.c_str());
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
//make sure any dangling objects are cleaned up
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().recompute()");
} else {
if (Gui::Command::hasPendingCommand()) {
std::vector<std::string> undos = Gui::Application::Instance->activeDocument()->getUndoVector();

View File

@@ -285,10 +285,10 @@ bool TaskSectionView::accept()
{
if (strcmp(sectionDir,"unset") == 0) {
Base::Console().Message("No direction selected!\n");
reject();
return false;
return reject();
} else {
updateValues();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
return true;
}
}
@@ -301,6 +301,9 @@ bool TaskSectionView::reject()
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().%s.removeView(App.activeDocument().%s)",
PageName.c_str(),SectionName.c_str());
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().removeObject('%s')",SectionName.c_str());
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
m_base->touch();
m_base->getDocument()->recompute();
return false;
}

View File

@@ -37,11 +37,9 @@
#include <App/DocumentObject.h>
#include <Gui/Application.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <Gui/MainWindow.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/TechDraw/App/DrawViewClip.h>
#include <Mod/TechDraw/App/DrawPage.h>
@@ -141,13 +139,16 @@ QGIView* ViewProviderDrawingView::getQView(void)
{
QGIView *qView = nullptr;
if (m_docReady){
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(getViewObject()->getDocument());
Gui::ViewProvider* vp = guiDoc->getViewProvider(getViewObject()->findParentPage());
ViewProviderPage* dvp = dynamic_cast<ViewProviderPage*>(vp);
if (dvp) {
if (dvp->getMDIViewPage()) {
if (dvp->getMDIViewPage()->getQGVPage()) {
qView = dynamic_cast<QGIView *>(dvp->getMDIViewPage()->getQGVPage()->findView(getViewObject()));
TechDraw::DrawView* dv = getViewObject();
if (dv) {
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(getViewObject()->getDocument());
Gui::ViewProvider* vp = guiDoc->getViewProvider(getViewObject()->findParentPage());
ViewProviderPage* dvp = dynamic_cast<ViewProviderPage*>(vp);
if (dvp) {
if (dvp->getMDIViewPage()) {
if (dvp->getMDIViewPage()->getQGVPage()) {
qView = dynamic_cast<QGIView *>(dvp->getMDIViewPage()->getQGVPage()->findView(getViewObject()));
}
}
}
}
@@ -186,10 +187,19 @@ void ViewProviderDrawingView::updateData(const App::Property* prop)
qgiv->updateView(true);
}
}
Gui::ViewProviderDocumentObject::updateData(prop);
}
void ViewProviderDrawingView::unsetEdit(int ModNum)
{
if (ModNum == ViewProvider::Default) {
Gui::Control().closeDialog();
}
else {
Gui::ViewProviderDocumentObject::unsetEdit(ModNum);
}
}
MDIViewPage* ViewProviderDrawingView::getMDIViewPage() const
{
MDIViewPage* result = nullptr;

View File

@@ -59,6 +59,7 @@ public:
virtual void onChanged(const App::Property *prop);
virtual void updateData(const App::Property*);
virtual void unsetEdit(int ModNum);
QGIView* getQView(void);
MDIViewPage* getMDIViewPage() const;
@@ -68,10 +69,12 @@ public:
virtual void startRestoring();
virtual void finishRestoring();
//@}
virtual TechDraw::DrawView* getViewObject() const;
private:
bool m_docReady; //sb MDI + QGraphicsScene ready
};
} // namespace TechDrawGui

View File

@@ -0,0 +1,158 @@
/***************************************************************************
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
* Copyright (c) 2017 Wandererfan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Base/Exception.h>
#include <Base/Sequencer.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Gui/Application.h>
#include <Gui/Selection.h>
#include <Gui/MainWindow.h>
#include <Gui/Utilities.h>
#include <Gui/Control.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawView.h>
#include "ViewProviderDrawingView.h"
#include "ViewProviderGeomHatch.h"
using namespace TechDrawGui;
PROPERTY_SOURCE(TechDrawGui::ViewProviderGeomHatch, Gui::ViewProviderDocumentObject)
//**************************************************************************
// Construction/Destruction
ViewProviderGeomHatch::ViewProviderGeomHatch()
{
static const char *vgroup = "Format";
sPixmap = "actions/techdraw-geomhatch";
ADD_PROPERTY_TYPE(ColorPattern,(0),vgroup,App::Prop_None,"The color of the pattern");
ADD_PROPERTY_TYPE(WeightPattern,(0.1),vgroup,App::Prop_None,"GeomHatch pattern line thickness");
getParameters();
}
ViewProviderGeomHatch::~ViewProviderGeomHatch()
{
}
void ViewProviderGeomHatch::attach(App::DocumentObject *pcFeat)
{
// call parent attach method
ViewProviderDocumentObject::attach(pcFeat);
}
void ViewProviderGeomHatch::setDisplayMode(const char* ModeName)
{
ViewProviderDocumentObject::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderGeomHatch::getDisplayModes(void) const
{
// get the modes of the father
std::vector<std::string> StrList = ViewProviderDocumentObject::getDisplayModes();
return StrList;
}
//for VP properties
void ViewProviderGeomHatch::onChanged(const App::Property* prop)
{
if (prop == &WeightPattern ||
prop == &ColorPattern ) {
updateGraphic();
}
Gui::ViewProviderDocumentObject::onChanged(prop);
}
//for feature properties
void ViewProviderGeomHatch::updateData(const App::Property* prop)
{
if (prop == &(getViewObject()->ScalePattern)) {
updateGraphic();
}
Gui::ViewProviderDocumentObject::updateData(prop);
}
void ViewProviderGeomHatch::updateGraphic(void)
{
TechDraw::DrawGeomHatch* dc = getViewObject();
if (dc) {
TechDraw::DrawViewPart* dvp = dc->getSourceView();
if (dvp) {
Gui::ViewProvider* view = Gui::Application::Instance->getDocument(dvp->getDocument())->getViewProvider(dvp);
TechDrawGui::ViewProviderDrawingView* vpDV = dynamic_cast<TechDrawGui::ViewProviderDrawingView*>(view);
if (vpDV) {
vpDV->show();
QGIView* qgiv = vpDV->getQView();
if (qgiv) {
qgiv->updateView(true);
}
}
}
}
}
void ViewProviderGeomHatch::getParameters(void)
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
App::Color fcColor;
fcColor.setPackedValue(hGrp->GetUnsigned("GeomHatch", 0x00000000));
ColorPattern.setValue(fcColor);
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
double lineWeight = hGrp->GetFloat("GeomWeight",0.1);
WeightPattern.setValue(lineWeight);
}
TechDraw::DrawGeomHatch* ViewProviderGeomHatch::getViewObject() const
{
return dynamic_cast<TechDraw::DrawGeomHatch*>(pcObject);
}

View File

@@ -0,0 +1,72 @@
/***************************************************************************
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
* Copyright (c) 2017 Wandererfan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef DRAWINGGUI_VIEWPROVIDERCROSSHATCH_H
#define DRAWINGGUI_VIEWPROVIDERCROSSHATCH_H
#include <App/DocumentObject.h>
#include <App/FeaturePython.h>
#include <App/PropertyStandard.h>
#include <Gui/ViewProviderFeature.h>
namespace TechDraw{
class DrawGeomHatch;
}
namespace TechDrawGui {
class TechDrawGuiExport ViewProviderGeomHatch : public Gui::ViewProviderDocumentObject
{
PROPERTY_HEADER(TechDrawGui::ViewProviderGeomHatch);
public:
/// constructor
ViewProviderGeomHatch();
/// destructor
virtual ~ViewProviderGeomHatch();
App::PropertyFloat WeightPattern;
App::PropertyColor ColorPattern;
virtual void attach(App::DocumentObject *);
virtual void updateData(const App::Property*);
virtual void onChanged(const App::Property *prop);
virtual bool useNewSelectionModel(void) const {return false;}
virtual void setDisplayMode(const char* ModeName);
virtual std::vector<std::string> getDisplayModes(void) const;
void updateGraphic(void);
void getParameters(void);
TechDraw::DrawGeomHatch* getViewObject() const;
};
} // namespace TechDrawGui
#endif // DRAWINGGUI_VIEWPROVIDERHATCH_H

View File

@@ -127,11 +127,13 @@ void ViewProviderPage::hide(void)
void ViewProviderPage::updateData(const App::Property* prop)
{
if (prop == &(getDrawPage()->Views)) {
if(m_mdiView) {
if(m_mdiView &&
!getDrawPage()->isDeleting()) {
m_mdiView->updateDrawing();
}
} else if (prop == &(getDrawPage()->Template)) {
if(m_mdiView) {
if(m_mdiView &&
!getDrawPage()->isDeleting()) {
m_mdiView->updateTemplate();
}
}

View File

@@ -153,7 +153,12 @@ bool ViewProviderProjGroup::setEdit(int ModNum)
void ViewProviderProjGroup::unsetEdit(int ModNum)
{
Q_UNUSED(ModNum);
Gui::Control().closeDialog();
if (ModNum == ViewProvider::Default) {
Gui::Control().closeDialog();
}
else {
ViewProviderDrawingView::unsetEdit(ModNum);
}
}
bool ViewProviderProjGroup::doubleClicked(void)

View File

@@ -39,6 +39,7 @@
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewMulti.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include<Mod/TechDraw/App/DrawPage.h>
#include "ViewProviderViewPart.h"
@@ -117,6 +118,7 @@ std::vector<App::DocumentObject*> ViewProviderViewPart::claimChildren(void) cons
// valid children of a ViewPart are:
// - Dimensions
// - Hatches
// - GeomHatches
std::vector<App::DocumentObject*> temp;
const std::vector<App::DocumentObject *> &views = getViewPart()->getInList();
try {
@@ -132,6 +134,8 @@ std::vector<App::DocumentObject*> ViewProviderViewPart::claimChildren(void) cons
}
} else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawHatch::getClassTypeId())) {
temp.push_back((*it));
} else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawGeomHatch::getClassTypeId())) {
temp.push_back((*it));
}
}
return temp;

View File

@@ -48,7 +48,17 @@ PROPERTY_SOURCE(TechDrawGui::ViewProviderViewSection, TechDrawGui::ViewProviderV
ViewProviderViewSection::ViewProviderViewSection()
{
static const char *sgroup = "Surface";
static const char *hgroup = "Hatch";
sPixmap = "TechDraw_Tree_Section";
ADD_PROPERTY_TYPE(ShowCutSurface ,(true),sgroup,App::Prop_None,"Show/hide the cut surface");
ADD_PROPERTY_TYPE(CutSurfaceColor,(0.0,0.0,0.0),sgroup,App::Prop_None,"The color to shade the cut surface");
ADD_PROPERTY_TYPE(HatchCutSurface ,(false),hgroup,App::Prop_None,"Hatch the cut surface");
ADD_PROPERTY_TYPE(HatchColor,(0.0,0.0,0.0),hgroup,App::Prop_None,"The color of the hatch pattern");
ADD_PROPERTY_TYPE(WeightPattern,(0.1),hgroup,App::Prop_None,"GeomHatch pattern line thickness");
getParameters();
}
ViewProviderViewSection::~ViewProviderViewSection()
@@ -74,16 +84,28 @@ std::vector<std::string> ViewProviderViewSection::getDisplayModes(void) const
return StrList;
}
//for VP properties
void ViewProviderViewSection::onChanged(const App::Property* prop)
{
if (prop == &WeightPattern ||
prop == &HatchCutSurface ||
prop == &HatchColor ||
prop == &ShowCutSurface ||
prop == &CutSurfaceColor ) {
updateGraphic();
}
ViewProviderViewPart::onChanged(prop);
}
//for Feature properties
void ViewProviderViewSection::updateData(const App::Property* prop)
{
if (prop == &(getViewObject()->ShowCutSurface) ||
prop == &(getViewObject()->CutSurfaceColor) ) {
// redraw QGIVP
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);
}
}
if (prop == &(getViewObject()->FileHatchPattern) ||
prop == &(getViewObject()->NameGeomPattern) ||
prop == &(getViewObject()->HatchScale) ) {
updateGraphic();
}
ViewProviderViewPart::updateData(prop);
}
@@ -93,6 +115,30 @@ std::vector<App::DocumentObject*> ViewProviderViewSection::claimChildren(void) c
return ViewProviderViewPart::claimChildren();
}
void ViewProviderViewSection::updateGraphic(void)
{
// redraw QGIVP
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);
}
}
void ViewProviderViewSection::getParameters(void)
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
App::Color cutColor = App::Color((uint32_t) hGrp->GetUnsigned("CutSurfaceColor", 0xC8C8C800));
CutSurfaceColor.setValue(cutColor);
App::Color hatchColor = App::Color((uint32_t) hGrp->GetUnsigned("SectionHatchColor", 0x00000000));
HatchColor.setValue(hatchColor);
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
double lineWeight = hGrp->GetFloat("GeomWeight",0.1);
WeightPattern.setValue(lineWeight);
}
TechDraw::DrawViewSection* ViewProviderViewSection::getViewObject() const
{
return dynamic_cast<TechDraw::DrawViewSection*>(pcObject);

View File

@@ -44,14 +44,25 @@ public:
/// destructor
virtual ~ViewProviderViewSection();
App::PropertyBool ShowCutSurface;
App::PropertyColor CutSurfaceColor;
App::PropertyBool HatchCutSurface;
App::PropertyColor HatchColor;
App::PropertyFloat WeightPattern;
virtual void attach(App::DocumentObject *);
virtual void setDisplayMode(const char* ModeName);
/// returns a list of all possible modes
virtual std::vector<std::string> getDisplayModes(void) const;
virtual void updateData(const App::Property*);
virtual void onChanged(const App::Property *prop);
virtual std::vector<App::DocumentObject*> claimChildren(void) const;
void updateGraphic(void);
void getParameters(void);
virtual TechDraw::DrawViewSection* getViewObject() const;
};

View File

@@ -78,12 +78,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*draw << "TechDraw_ArchView";
*draw << "TechDraw_ExportPage";
*draw << "TechDraw_Image";
//*draw << "TechDraw_Open";
//*part << "TechDraw_NewA3Landscape";
//*part << "TechDraw_OpenBrowserView";
//*part << "TechDraw_DraftView";
//*draw << "Separator";
//*draw << "TechDraw_ProjectShape";
return root;
}
@@ -128,11 +122,12 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem *file = new Gui::ToolBarItem(root);
file->setCommand("TechDraw File Access");
*file << "TechDraw_ExportPage";
*file << "TechDraw_Symbol";
Gui::ToolBarItem *decor = new Gui::ToolBarItem(root);
decor->setCommand("TechDraw Decoration");
*decor << "TechDraw_NewHatch";
*decor << "TechDraw_NewGeomHatch";
*decor << "TechDraw_Symbol";
*decor << "TechDraw_Image";
*decor << "TechDraw_ToggleFrame";
return root;
@@ -177,11 +172,12 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
Gui::ToolBarItem *file = new Gui::ToolBarItem(root);
file->setCommand("TechDraw File Access");
*file << "TechDraw_ExportPage";
*file << "TechDraw_Symbol";
Gui::ToolBarItem *decor = new Gui::ToolBarItem(root);
decor->setCommand("TechDraw Decoration");
*decor << "TechDraw_NewHatch";
*decor << "TechDraw_NewGeomHatch";
*decor << "TechDraw_Symbol";
*decor << "TechDraw_Image";
*decor << "TechDraw_ToggleFrame";

View File

@@ -12,7 +12,7 @@ namespace ZVALUE {
const int VERTEX = 60;
const int SECTIONFACE = 65;
const int SECTIONHATCH = 66;
const int DIMENSION = 70;
const int DIMENSION = 110;
const int SECTIONLINE = 80; //TODO: change to "DECORATION"? section lines, symmetry lines, etc?
const int MATTING = 100;
}

View File

@@ -0,0 +1,21 @@
; standard PAT patterns
*Diamond, 45 diagonals L & R, Solid, 1.0 mm separation
45,0,0,0,1.0
-45,0,0,0,1.0
*Diamond2, 45 diagonals L & R, Solid, 2.0 mm separation
45,0,0,0,2.0
-45,0,0,0,2.0
*Diamond4, 45 diagonals L & R, Solid, 4.0 mm separation
45,0,0,0,4.0
-45,0,0,0,4.0
*Diagonal4, 45 diagonal R, Solid, 4.0 mm separation
45,0,0,0,4.0
*Square, square grid, Solid, 5.0 mm separation
90,1,1,0,5.0
0,0,0,1,5.0
*Horizontal5, horizontal lines, Solid 5.0 separation
0,0,0,0,5.0
*Vertical5, vertical lines, Solid, 5.0 separation
90,0,0,0,5.0