diff --git a/src/Mod/TechDraw/App/AppTechDraw.cpp b/src/Mod/TechDraw/App/AppTechDraw.cpp index 2b981a5ba6..cac9175a10 100644 --- a/src/Mod/TechDraw/App/AppTechDraw.cpp +++ b/src/Mod/TechDraw/App/AppTechDraw.cpp @@ -31,6 +31,7 @@ #include "DrawViewSymbol.h" #include "DrawViewClip.h" #include "DrawHatch.h" +#include "DrawCrosshatch.h" #include "DrawViewDraft.h" #include "DrawViewArch.h" #include "DrawViewSpreadsheet.h" @@ -84,6 +85,7 @@ PyMODINIT_FUNC initTechDraw() TechDraw::DrawViewClip ::init(); TechDraw::DrawHatch ::init(); + TechDraw::DrawCrosshatch ::init(); TechDraw::DrawViewDraft ::init(); TechDraw::DrawViewArch ::init(); TechDraw::DrawViewImage ::init(); diff --git a/src/Mod/TechDraw/App/CMakeLists.txt b/src/Mod/TechDraw/App/CMakeLists.txt index 608de84dc6..ca75b172c5 100644 --- a/src/Mod/TechDraw/App/CMakeLists.txt +++ b/src/Mod/TechDraw/App/CMakeLists.txt @@ -37,6 +37,7 @@ generate_from_xml(DrawViewSymbolPy) generate_from_xml(DrawViewClipPy) generate_from_xml(DrawViewDimensionPy) generate_from_xml(DrawHatchPy) +generate_from_xml(DrawCrosshatchPy) 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 + DrawCrosshatch.cpp + DrawCrosshatch.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 + DrawCrosshatchPy.xml + DrawCrosshatchPyImp.cpp DrawViewCollectionPy.xml DrawViewCollectionPyImp.cpp DrawProjGroupPy.xml diff --git a/src/Mod/TechDraw/App/DrawCrosshatch.cpp b/src/Mod/TechDraw/App/DrawCrosshatch.cpp new file mode 100644 index 0000000000..d216b31069 --- /dev/null +++ b/src/Mod/TechDraw/App/DrawCrosshatch.cpp @@ -0,0 +1,445 @@ +/*************************************************************************** + * Copyright (c) 2015 WandererFan * + * * + * 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 +#include +#include + +# include +# include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include "HatchLine.h" +#include "DrawUtil.h" +#include "Geometry.h" +#include "DrawViewPart.h" +#include "DrawCrosshatch.h" + +#include // generated from DrawCrosshatchPy.xml + +using namespace TechDraw; +using namespace TechDrawGeometry; +using namespace std; + +PROPERTY_SOURCE(TechDraw::DrawCrosshatch, App::DocumentObject) + + +DrawCrosshatch::DrawCrosshatch(void) +{ + static const char *vgroup = "Crosshatch"; + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors"); + App::Color fcColor; + fcColor.setPackedValue(hGrp->GetUnsigned("Crosshatch", 0x00000000)); + + ADD_PROPERTY_TYPE(DirProjection ,(0,0,1.0) ,vgroup,App::Prop_None,"Projection direction when Crosshatch was defined"); //sb RO? + 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,"Crosshatch pattern size adjustment"); +// ADD_PROPERTY_TYPE(ColorPattern,(fcColor),vgroup,App::Prop_None,"The color of the pattern"); //to vp? +// ADD_PROPERTY_TYPE(WeightPattern,(0.0),vgroup,App::Prop_None,"Crosshatch pattern line thickness"); +// ADD_PROPERTY_TYPE(LineSpecs,(""),vgroup,App::Prop_None,"Pattern line specifications"); //this sb RO or removed? + + DirProjection.setStatus(App::Property::ReadOnly,true); + +//this is probably "/build/data/Mod/TechDraw/PAT" + 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 + "FCStd.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()); + } + hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT"); + + std::string defaultNamePattern = "Diamond"; + NamePattern.setValue(hGrp->GetASCII("NamePattern",defaultNamePattern.c_str())); + +} + +DrawCrosshatch::~DrawCrosshatch() +{ +} + +void DrawCrosshatch::onChanged(const App::Property* prop) +{ + if (prop == &Source ) { + if (!isRestoring()) { + DrawCrosshatch::execute(); + } + } + + if (prop == &FilePattern || + prop == &NamePattern ) { + if ((!FilePattern.isEmpty()) && + (!NamePattern.isEmpty())) { + std::vector specs = getDecodedSpecsFromFile(); + m_lineSets.clear(); + for (auto& hl: specs) { + //hl.dump("hl from file"); + LineSet ls; + ls.setHatchLine(hl); + m_lineSets.push_back(ls); + } + + } + } + + if (prop == &ScalePattern) { + if (!isRestoring()) { + adviseParent(); //just need to have the parent redraw on Gui side. handle through VPDC::updateData + } + } + + App::DocumentObject::onChanged(prop); +} + +short DrawCrosshatch::mustExecute() const +{ + short result = 0; + if (!isRestoring()) { + result = (Source.isTouched() || + FilePattern.isTouched() || + NamePattern.isTouched() ); + } + + if (result) { + return result; + } + return App::DocumentObject::mustExecute(); +} + + +App::DocumentObjectExecReturn *DrawCrosshatch::execute(void) +{ + DrawViewPart* source = getSourceView(); + if (!source) { + return App::DocumentObject::StdReturn; + } + + if (!source->hasGeometry()) { + return App::DocumentObject::StdReturn; + } + + Base::Vector3d sourceDir = source->Direction.getValue(); + Base::Vector3d ourDir = DirProjection.getValue(); + if (sourceDir != ourDir) { + Base::Console().Warning("Pattern %s may be incorrect due to source %d Direction change.\n", + getNameInDocument(),source->getNameInDocument()); + } + + adviseParent(); + + return App::DocumentObject::StdReturn; +} + +void DrawCrosshatch::adviseParent(void) const +{ + //if the hatch changes, the source has to change too. actually only the source's QGVI has to change. + DrawViewPart* parent = getSourceView(); + if (parent) { + parent->touch(); + parent->recomputeFeature(); + } +} + +DrawViewPart* DrawCrosshatch::getSourceView(void) const +{ + App::DocumentObject* obj = Source.getValue(); + DrawViewPart* result = dynamic_cast(obj); + return result; +} + +//!get all the specification lines and decode them into HatchLine structures +std::vector DrawCrosshatch::getDecodedSpecsFromFile() +{ + std::vector result; + std::string fileSpec = FilePattern.getValue(); + std::string myPattern = NamePattern.getValue(); + Base::FileInfo fi(fileSpec); + if (!fi.isReadable()) { + Base::Console().Error("DrawCrosshatch::getDecodedSpecsFromFile not able to open %s!\n",fileSpec.c_str()); + return result; + } + result = HatchLine::getSpecsForPattern(fileSpec,myPattern); + + return result; +} + +std::vector DrawCrosshatch::getDrawableLines() +{ + std::vector result; + + DrawViewPart* source = getSourceView(); + if (!source || + !source->hasGeometry()) { + Base::Console().Message("TRACE - DC::getDrawableLines - no source geometry\n"); + return result; + } + + if (m_lineSets.empty()) { + Base::Console().Message("TRACE - DC::getDrawableLines - no LineSets!\n"); + return result; + } + + //get geometry for linked Face + const std::vector &subElements = Source.getSubValues(); + int idx = DrawUtil::getIndexFromName(subElements[0]); + + //build wire(s) from geometry + std::vector faceWires = source->getWireForFace(idx); + gp_Pln plane = source->getProjPlane(); + + BRepBuilderAPI_MakeFace mkFace(plane, faceWires.front(), true); + std::vector::iterator itWire = ++faceWires.begin(); //starting with second wire + for (; itWire != faceWires.end(); itWire++) { + mkFace.Add(*itWire); + } + if (!mkFace.IsDone()) { + Base::Console().Message("TRACE - DC::getDrawableLines - face creation failed\n"); + return result; + } + TopoDS_Face face = mkFace.Face(); + + Bnd_Box bBox; + BRepBndLib::Add(face, bBox); + bBox.SetGap(0.0); +// face & box are done! + + for (auto& ls: m_lineSets) { + HatchLine hl = ls.getHatchLine(); + std::vector candidates = DrawCrosshatch::makeEdgeOverlay(hl, bBox); + + //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().Message("TRACE - DC::getDrawableLines - Common creation failed\n"); + return result; + } + TopoDS_Shape common = mkCommon.Shape(); + + //Save edges from Common + std::vector resultEdges; + std::vector 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().Message("TRACE - DC::getDrawableLines - edge: %d is NULL\n",i); + continue; + } + TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(edge); + if (base == nullptr) { + Base::Console().Message("TRACE - 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; +} + +std::vector DrawCrosshatch::makeEdgeOverlay(HatchLine hl, Bnd_Box b) +{ + std::vector 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 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 DrawCrosshatch::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; +} + +PyObject *DrawCrosshatch::getPyObject(void) +{ + if (PythonObject.is(Py::_None())) { + PythonObject = Py::Object(new DrawCrosshatchPy(this),true); + } + return Py::new_reference_to(PythonObject); +} + +// Python Drawing feature --------------------------------------------------------- + +namespace App { +/// @cond DOXERR +PROPERTY_SOURCE_TEMPLATE(TechDraw::DrawCrosshatchPython, TechDraw::DrawCrosshatch) +template<> const char* TechDraw::DrawCrosshatchPython::getViewProviderName(void) const { + return "TechDrawGui::ViewProviderCrosshatch"; +} +/// @endcond + +// explicit template instantiation +template class TechDrawExport FeaturePythonT; +} diff --git a/src/Mod/TechDraw/App/DrawCrosshatch.h b/src/Mod/TechDraw/App/DrawCrosshatch.h new file mode 100644 index 0000000000..baa2adfbf2 --- /dev/null +++ b/src/Mod/TechDraw/App/DrawCrosshatch.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (c) 2017 WandererFan * + * * + * 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_DrawCrosshatch_h_ +#define _TechDraw_DrawCrosshatch_h_ + +# include +# include +# include +#include + +#include "HatchLine.h" +#include "Geometry.h" + +class TopoDS_Edge; +class Bnd_Box; + +namespace TechDraw +{ +class DrawViewPart; + +class TechDrawExport DrawCrosshatch : public App::DocumentObject +{ + PROPERTY_HEADER(TechDraw::DrawCrosshatch); + +public: + DrawCrosshatch(); + virtual ~DrawCrosshatch(); + + App::PropertyVector DirProjection; //Source is only valid for original projection? + App::PropertyLinkSub Source; //the dvp & face this crosshatch belongs to + App::PropertyFile FilePattern; + App::PropertyString NamePattern; + App::PropertyFloat ScalePattern; +// App::PropertyFloat WeightPattern; +// App::PropertyColor ColorPattern; +// App::PropertyStringList LineSpecs; + + virtual short mustExecute() const; + virtual App::DocumentObjectExecReturn *execute(void); + virtual void onChanged(const App::Property* prop); + virtual const char* getViewProviderName(void) const { + return "TechDrawGui::ViewProviderCrosshatch"; + } + virtual PyObject *getPyObject(void); + + std::vector getDrawableLines(); + DrawViewPart* getSourceView(void) const; + void adviseParent(void) const; //don't like this! + + +protected: + TopoDS_Edge makeLine(Base::Vector3d s, Base::Vector3d e); + std::vector getDecodedSpecsFromFile(); + std::vector makeEdgeOverlay(HatchLine hl, Bnd_Box bBox); + std::vector m_lineSets; + +private: +}; + +typedef App::FeaturePythonT DrawCrosshatchPython; + + + +} //namespace TechDraw +#endif diff --git a/src/Mod/TechDraw/App/DrawCrosshatchPy.xml b/src/Mod/TechDraw/App/DrawCrosshatchPy.xml new file mode 100644 index 0000000000..ec5bf2c20e --- /dev/null +++ b/src/Mod/TechDraw/App/DrawCrosshatchPy.xml @@ -0,0 +1,18 @@ + + + + + + Feature for creating and manipulating Technical Drawing Crosshatch areas + + + + diff --git a/src/Mod/TechDraw/App/DrawCrosshatchPyImp.cpp b/src/Mod/TechDraw/App/DrawCrosshatchPyImp.cpp new file mode 100644 index 0000000000..7074f2ea0e --- /dev/null +++ b/src/Mod/TechDraw/App/DrawCrosshatchPyImp.cpp @@ -0,0 +1,32 @@ + +#include "PreCompiled.h" + +#include "DrawCrosshatch.h" + +// inclusion of the generated files (generated out of DrawCrosshatchPy.xml) +#include +#include + +using namespace TechDraw; + +// returns a string which represents the object e.g. when printed in python +std::string DrawCrosshatchPy::representation(void) const +{ + return std::string(""); +} + + + + + + + +PyObject *DrawCrosshatchPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int DrawCrosshatchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/TechDraw/App/DrawHatch.cpp b/src/Mod/TechDraw/App/DrawHatch.cpp index 5e3942d1fd..81e8437a95 100644 --- a/src/Mod/TechDraw/App/DrawHatch.cpp +++ b/src/Mod/TechDraw/App/DrawHatch.cpp @@ -69,7 +69,7 @@ DrawHatch::DrawHatch(void) 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); } diff --git a/src/Mod/TechDraw/App/DrawPage.cpp b/src/Mod/TechDraw/App/DrawPage.cpp index 561d252b35..b03b03cf40 100644 --- a/src/Mod/TechDraw/App/DrawPage.cpp +++ b/src/Mod/TechDraw/App/DrawPage.cpp @@ -292,6 +292,10 @@ void DrawPage::onDocumentRestored() if (part != nullptr && !part->hasGeometry()) { part->execute(); +// std::vector parent = part->getInList(); +// for (auto& p: parent) { +// p->touch(); +// } } } //second, make sure all the Dimensions have been executed so Measurements have References diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index 4b00e73ceb..33a06aabae 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -1042,6 +1042,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); diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index c0b4beb36f..7b7a193367 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ #include "GeometryObject.h" #include "DrawViewPart.h" #include "DrawHatch.h" +#include "DrawCrosshatch.h" #include "EdgeWalker.h" @@ -147,19 +149,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(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 @@ -391,7 +391,6 @@ void DrawViewPart::extractFaces() } } - std::vector DrawViewPart::getHatches() const { std::vector result; @@ -405,6 +404,19 @@ std::vector DrawViewPart::getHatches() const return result; } +std::vector DrawViewPart::getCrosshatches() const +{ + std::vector result; + std::vector children = getInList(); + for (std::vector::iterator it = children.begin(); it != children.end(); ++it) { + if ((*it)->getTypeId().isDerivedFrom(DrawCrosshatch::getClassTypeId())) { + TechDraw::DrawCrosshatch* cross = dynamic_cast(*it); + result.push_back(cross); + } + } + return result; +} + const std::vector & DrawViewPart::getVertexGeometry() const { return geometryObject->getVertexGeometry(); @@ -450,6 +462,8 @@ TechDrawGeometry::Vertex* DrawViewPart::getProjVertexByIndex(int idx) const return geoms.at(idx); } + +//this is never used!! //! returns existing geometry of 2D Face(idx) //version 1 Face has 1 wire std::vector DrawViewPart::getProjFaceByIndex(int idx) const @@ -467,6 +481,29 @@ std::vector DrawViewPart::getProjFaceByIndex(int id return result; } +std::vector DrawViewPart::getWireForFace(int idx) const +{ +// Base::Console().Message("TRACE - DVP::getWireForFace(%d)\n",idx); + std::vector result; + std::vector edges; + const std::vector& 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 { @@ -570,12 +607,24 @@ const std::vector 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 hGrp = App::GetApplication().GetUserParameter() - .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General"); + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/RunControl"); m_sectionEdges = hGrp->GetBool("ShowSectionEdges", 1l); m_handleFaces = hGrp->GetBool("HandleFaces", 1l); + //Base::Console().Message("TRACE - DVP::getRunControl - handleFaces: %d\n",m_handleFaces); } bool DrawViewPart::handleFaces(void) diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index d33727c5bd..8c88601898 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -40,6 +40,7 @@ #include "DrawProjectSplit.h" class gp_Pnt; +class gp_Pln; namespace TechDrawGeometry { @@ -51,6 +52,7 @@ class Face; namespace TechDraw { class DrawHatch; +class DrawCrosshatch; } namespace TechDraw @@ -91,6 +93,7 @@ public: std::vector getHatches(void) const; + std::vector getCrosshatches(void) const; //TODO: are there use-cases for Python access to TechDrawGeometry??? @@ -136,6 +139,10 @@ public: //return PyObject as DrawViewPartPy virtual PyObject *getPyObject(void); bool isDeleting(void) { return nowDeleting; } + + gp_Pln getProjPlane(void) const; + std::vector getWireForFace(int idx) const; + protected: TechDrawGeometry::GeometryObject *geometryObject; diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 821f2f46c1..0b6d07b9ef 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -545,7 +545,7 @@ void DrawViewSection::getParameters() 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); } diff --git a/src/Mod/TechDraw/App/EdgeWalker.cpp b/src/Mod/TechDraw/App/EdgeWalker.cpp index 1507f419c8..bd6c3b6e98 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.cpp +++ b/src/Mod/TechDraw/App/EdgeWalker.cpp @@ -265,7 +265,7 @@ std::vector EdgeWalker::getResultNoDups() return fw; } - +//* static *// //! make a clean wire with sorted, oriented, connected, etc edges TopoDS_Wire EdgeWalker::makeCleanWire(std::vector edges, double tol) { diff --git a/src/Mod/TechDraw/App/EdgeWalker.h b/src/Mod/TechDraw/App/EdgeWalker.h index 2eeb493336..6556e3d78d 100644 --- a/src/Mod/TechDraw/App/EdgeWalker.h +++ b/src/Mod/TechDraw/App/EdgeWalker.h @@ -175,7 +175,7 @@ public: int findUniqueVert(TopoDS_Vertex vx, std::vector &uniqueVert); std::vector sortStrip(std::vector fw, bool includeBiggest); std::vector sortWiresBySize(std::vector& w, bool reverse = false); - TopoDS_Wire makeCleanWire(std::vector edges, double tol = 0.10); + static TopoDS_Wire makeCleanWire(std::vector edges, double tol = 0.10); std::vector getEmbeddingRowIx(int v); std::vector getEmbeddingRow(int v); diff --git a/src/Mod/TechDraw/App/GeometryObject.cpp b/src/Mod/TechDraw/App/GeometryObject.cpp index 5a00052822..e4de3373df 100644 --- a/src/Mod/TechDraw/App/GeometryObject.cpp +++ b/src/Mod/TechDraw/App/GeometryObject.cpp @@ -161,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"); diff --git a/src/Mod/TechDraw/App/HatchLine.cpp b/src/Mod/TechDraw/App/HatchLine.cpp new file mode 100644 index 0000000000..e469c00c01 --- /dev/null +++ b/src/Mod/TechDraw/App/HatchLine.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (c) 2017 Wandererfan * + * * + * 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 +#include +#include +#include +#include +#endif + +#include + +#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 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 HatchLine::split(std::string line) +{ + std::vector 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::getSpecsForPattern(std::string& parmFile, std::string& parmName) +{ + std::vector result; + std::vector 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 HatchLine::loadPatternDef(std::ifstream& inFile) +{ + std::vector 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 HatchLine::getPatternList(std::string& parmFile) +{ + std::vector 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()); +} + + + + + diff --git a/src/Mod/TechDraw/App/HatchLine.h b/src/Mod/TechDraw/App/HatchLine.h new file mode 100644 index 0000000000..8ed3142a03 --- /dev/null +++ b/src/Mod/TechDraw/App/HatchLine.h @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (c) 2017 Wandererfan * + * * + * 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 +#include +#include +#include +#include + +#include + +#include "Geometry.h" + +namespace TechDraw +{ +class DrawViewPart; +class DrawUtil; + + +// HatchLine is the result of parsing a line from PAT file into accessible parameters +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 getDashParms(void) {return m_dashParms;}; + + static std::vector getSpecsForPattern(std::string& parmFile, std::string& parmName); + static bool findPatternStart(std::ifstream& inFile, std::string& parmName); + static std::vector loadPatternDef(std::ifstream& inFile); + static std::vector getPatternList(std::string& parmFile); + + void dump(char* title); + +private: + void init(void); + std::vector split(std::string line); + + double m_angle; + Base::Vector3d m_origin; + double m_interval; + double m_offset; + std::vector m_dashParms; //why isn't this a DashSpec object? +}; + +// a LineSet is all the generated edges for a HatchLine +class LineSet +{ +public: + LineSet() {} + ~LineSet() {} + + void setHatchLine(HatchLine s) { m_hatchLine = s; } + void setEdges(std::vector e) {m_edges = e;} + void setGeoms(std::vector g) {m_geoms = g;} + + HatchLine getHatchLine(void) { return m_hatchLine; } + std::vector getDashSpec(void) { return m_hatchLine.getDashParms();} + std::vector getEdges(void) { return m_edges; } + std::vector getGeoms(void) { return m_geoms; } + +private: + std::vector m_edges; + std::vector m_geoms; + HatchLine m_hatchLine; +}; + +class DashSpec +{ +public: + DashSpec() {} + DashSpec(std::vector p) { m_parms = p; } + ~DashSpec() {} + + double get(int i) {return m_parms.at(i); } + std::vector 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 m_parms; +}; + +} //end namespace + +#endif diff --git a/src/Mod/TechDraw/Gui/AppTechDrawGui.cpp b/src/Mod/TechDraw/Gui/AppTechDrawGui.cpp index 8030942013..a272545c54 100644 --- a/src/Mod/TechDraw/Gui/AppTechDrawGui.cpp +++ b/src/Mod/TechDraw/Gui/AppTechDrawGui.cpp @@ -48,6 +48,7 @@ #include "ViewProviderSymbol.h" #include "ViewProviderViewClip.h" #include "ViewProviderHatch.h" +#include "ViewProviderCrosshatch.h" #include "ViewProviderSpreadsheet.h" #include "ViewProviderImage.h" @@ -102,6 +103,7 @@ void TechDrawGuiExport initTechDrawGui() TechDrawGui::ViewProviderDraft::init(); TechDrawGui::ViewProviderArch::init(); TechDrawGui::ViewProviderHatch::init(); + TechDrawGui::ViewProviderCrosshatch::init(); TechDrawGui::ViewProviderSpreadsheet::init(); TechDrawGui::ViewProviderImage::init(); diff --git a/src/Mod/TechDraw/Gui/CMakeLists.txt b/src/Mod/TechDraw/Gui/CMakeLists.txt index 09cdad3e43..821924b931 100644 --- a/src/Mod/TechDraw/Gui/CMakeLists.txt +++ b/src/Mod/TechDraw/Gui/CMakeLists.txt @@ -199,6 +199,8 @@ SET(TechDrawGuiViewProvider_SRCS ViewProviderViewClip.h ViewProviderHatch.cpp ViewProviderHatch.h + ViewProviderCrosshatch.cpp + ViewProviderCrosshatch.h ViewProviderImage.cpp ViewProviderImage.h ) diff --git a/src/Mod/TechDraw/Gui/CommandDecorate.cpp b/src/Mod/TechDraw/Gui/CommandDecorate.cpp index 322499d156..fc5e39ecd4 100644 --- a/src/Mod/TechDraw/Gui/CommandDecorate.cpp +++ b/src/Mod/TechDraw/Gui/CommandDecorate.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,69 @@ bool CmdTechDrawNewHatch::isActive(void) return (havePage && haveView); } +//=========================================================================== +// TechDraw_NewCrosshatch +//=========================================================================== + +DEF_STD_CMD_A(CmdTechDrawNewCrosshatch); + +CmdTechDrawNewCrosshatch::CmdTechDrawNewCrosshatch() + : Command("TechDraw_NewCrosshatch") +{ + sAppModule = "TechDraw"; + sGroup = QT_TR_NOOP("TechDraw"); + sMenuText = QT_TR_NOOP("Insert a crosshatched area into a view"); + sToolTipText = QT_TR_NOOP("Insert a crosshatched area into a view"); + sWhatsThis = "TechDraw_NewCrosshatch"; + sStatusTip = sToolTipText; + sPixmap = "actions/techdraw-crosshatch"; +} + +void CmdTechDrawNewCrosshatch::activated(int iMsg) +{ + Q_UNUSED(iMsg); + if (!_checkSelectionHatch(this)) { //same requirements as hatch - page, DrawViewXXX, face + return; + } + + std::vector selection = getSelection().getSelectionEx(); + auto objFeat( dynamic_cast(selection[0].getObject()) ); + if( objFeat == nullptr ) { + return; + } + const std::vector &subNames = selection[0].getSubNames(); + TechDraw::DrawPage* page = objFeat->findParentPage(); + std::string PageName = page->getNameInDocument(); + + std::string FeatName = getUniqueObjectName("Crosshatch"); + std::stringstream featLabel; + featLabel << FeatName << "FX" << TechDraw::DrawUtil::getIndexFromName(subNames.at(0)); + + Base::Console().Message("TRACE - cmd::newCrossHatch - %s - %s\n",featLabel.str().c_str(), FeatName.c_str()); + + openCommand("Create Crosshatch"); + doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawCrosshatch','%s')",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Label = '%s'",FeatName.c_str(),featLabel.str().c_str()); + + auto crosshatch( static_cast(getDocument()->getObject(FeatName.c_str())) ); + crosshatch->Source.setValue(objFeat, subNames); + + commitCommand(); + Base::Console().Message("TRACE - cmd::newCrossHatch - complete\n"); + + //Horrible hack to force Tree update ??still required?? + double x = objFeat->X.getValue(); + objFeat->X.setValue(x); + getDocument()->recompute(); +} + +bool CmdTechDrawNewCrosshatch::isActive(void) +{ + bool havePage = DrawGuiUtil::needPage(this); + bool haveView = DrawGuiUtil::needView(this); + return (havePage && haveView); +} + //=========================================================================== // TechDraw_Image //=========================================================================== @@ -230,6 +294,7 @@ void CreateTechDrawCommandsDecorate(void) Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); rcCmdMgr.addCommand(new CmdTechDrawNewHatch()); + rcCmdMgr.addCommand(new CmdTechDrawNewCrosshatch()); rcCmdMgr.addCommand(new CmdTechDrawImage()); rcCmdMgr.addCommand(new CmdTechDrawToggleFrame()); } diff --git a/src/Mod/TechDraw/Gui/DlgPrefsTechDraw.ui b/src/Mod/TechDraw/Gui/DlgPrefsTechDraw.ui index d026baeb1a..32ba4f5814 100644 --- a/src/Mod/TechDraw/Gui/DlgPrefsTechDraw.ui +++ b/src/Mod/TechDraw/Gui/DlgPrefsTechDraw.ui @@ -82,7 +82,7 @@ - PatternFile + FileHatch /Mod/TechDraw/Files diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index dd6fffdcd9..96248a50c1 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -379,12 +379,12 @@ void MDIViewPage::updateDrawing(bool forceUpdate) // 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; +// int qgvpIn = 0; +// int qgvpValid = 0; +// int qgvpClean = 0; +// int dpIn = 0; const std::vector &graphicsList = m_view->getViews(); - qgvpIn = graphicsList.size(); +// qgvpIn = graphicsList.size(); const std::vector &pageChildren = m_vpPage->getDrawPage()->Views.getValues(); // Count total # DocumentObjects in Page @@ -397,7 +397,7 @@ void MDIViewPage::updateDrawing(bool forceUpdate) } docObjCount += 1; } - dpIn = docObjCount; +// dpIn = docObjCount; //TODO: should prune QGVP.views first always, then check if view in Page missing QGIVP @@ -426,7 +426,7 @@ void MDIViewPage::updateDrawing(bool forceUpdate) } } } - qgvpValid = newGraphicsList.size(); +// qgvpValid = newGraphicsList.size(); //newGraphicsList now only contains valid QGIV's //now prune the ones without docObjs std::vector cleanItems; @@ -452,10 +452,10 @@ void MDIViewPage::updateDrawing(bool forceUpdate) cleanItems.push_back(v); } } - qgvpClean = cleanItems.size(); +// 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); +// 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 diff --git a/src/Mod/TechDraw/Gui/QGIFace.cpp b/src/Mod/TechDraw/Gui/QGIFace.cpp index 63a6c205d8..b35afbaa53 100644 --- a/src/Mod/TechDraw/Gui/QGIFace.cpp +++ b/src/Mod/TechDraw/Gui/QGIFace.cpp @@ -48,12 +48,15 @@ #include #include +#include + #include "Rez.h" #include "QGCustomSvg.h" #include "QGCustomRect.h" #include "QGIFace.h" using namespace TechDrawGui; +using namespace TechDraw; QGIFace::QGIFace(int index) : projIndex(index), @@ -61,8 +64,8 @@ QGIFace::QGIFace(int index) : m_styleDef(Qt::SolidPattern), m_styleSelect(Qt::SolidPattern) { - m_isHatched = false; - m_mode = 0; + setFillMode(NoFill); + isHatched(false); setFlag(QGraphicsItem::ItemClipsChildrenToShape,true); //setStyle(Qt::NoPen); //don't draw face lines, just fill for debugging @@ -71,8 +74,11 @@ QGIFace::QGIFace(int index) : m_styleNormal = m_styleDef; m_fillStyle = m_styleDef; m_colNormalFill = m_colDefFill; + setCrosshatchColor(QColor(Qt::black)); + setCrosshatchWeight(0.5); //0 = cosmetic + setPrettyNormal(); - m_texture = QPixmap(); + m_texture = nullptr; //empty texture m_svg = new QGCustomSvg(); @@ -80,7 +86,7 @@ QGIFace::QGIFace(int index) : m_rect->setParentItem(this); m_svgCol = SVGCOLDEFAULT; - m_svgScale = 1.0; + m_fillScale = 1.0; } QGIFace::~QGIFace() @@ -90,22 +96,47 @@ QGIFace::~QGIFace() void QGIFace::draw() { + setPath(m_outline); //Face boundary + if (isHatched()) { - QFileInfo hfi(QString::fromUtf8(m_fileSpec.data(),m_fileSpec.size())); - if (hfi.isReadable()) { - QString ext = hfi.suffix(); - if (ext.toUpper() == QString::fromUtf8("SVG")) { - m_mode = 1; - 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")) ) { - m_mode = 2; - toggleSvg(false); - m_texture = textureFromBitmap(m_fileSpec); + if (m_mode == CrosshatchFill) { //crosshatch + if (!m_crossHatchPaths.empty()) { //surrogate for LineSets.empty + m_brush.setTexture(nullptr); + m_fillStyle = m_styleDef; + m_styleNormal = m_fillStyle; + int pathNo = 0; + for (auto& pp: m_crossHatchPaths) { + QGraphicsPathItem* fillItem = m_fillItems.at(pathNo); + fillItem->setPath(pp); + QPen crossPen = setCrossPen(pathNo); + fillItem->setPen(crossPen); + 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); + } } } } @@ -114,23 +145,27 @@ void QGIFace::draw() void QGIFace::setPrettyNormal() { if (isHatched() && - (m_mode == 2) ) { //hatch with bitmap fill + (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; } - 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(); @@ -164,21 +199,110 @@ void QGIFace::loadSvgHatch(std::string fileSpec) } } -void QGIFace::setPath(const QPainterPath & path) +void QGIFace::setFillMode(QGIFace::fillMode m) { - QGraphicsPathItem::setPath(path); - if ((m_mode == 1) && !m_svgXML.isEmpty()) { // svg hatch mode and have svg hatch info loded - buildSvgHatch(); + m_mode = m; + if ((m_mode == NoFill) || + (m_mode == PlainFill)) { + isHatched(false); + } else { + isHatched(true); } } +void QGIFace::setOutline(const QPainterPath & path) +{ + m_outline = path; +} + +void QGIFace::clearLineSets(void) +{ + m_crossHatchPaths.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 dp) +{ + m_crossHatchPaths.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; + } +} + +void QGIFace::setCrosshatchColor(const QColor& c) +{ + m_crossColor = c; +} + +//convert from PAT style "-1,0,-1,+1" to Qt style "mark,space,mark,space" +QVector QGIFace::decodeDashSpec(DashSpec patDash) +{ + //Rez::guiX(something)? + double dotLength = 3.0; //guess work! + double unitLength = 6.0; + //double penWidth = m_crossWeight; + std::vector result; + for (auto& d: patDash.get()) { + double strokeLength; + if (DrawUtil::fpCompare(d,0.0)) { //pat dot + strokeLength = dotLength; + result.push_back(strokeLength); + } else if (Rez::guiX(d) < 0) { //pat space + strokeLength = fabs(Rez::guiX(d)) * unitLength; + result.push_back(strokeLength); + } else { //pat dash + strokeLength = Rez::guiX(d) * unitLength; + result.push_back(strokeLength); + } + } + return QVector::fromStdVector( result ); +} + + +QPen QGIFace::setCrossPen(int i) +{ + //m_dashSpecs[i].dump("spec test"); + DashSpec ourSpec = m_dashSpecs.at(i); + //ourSpec.dump("our spec"); + + QPen result; +// result.setWidthF(m_crossWeight); + result.setWidthF(Rez::guiX(0.09)); + result.setColor(m_crossColor); + 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_svgScale; - double hTile = SVGSIZEH * m_svgScale; - double w = boundingRect().width(); - double h = boundingRect().height(); - QRectF r = boundingRect(); + 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 / wTile); double nh = ceil(h / hTile); @@ -194,7 +318,7 @@ void QGIFace::buildSvgHatch() for (int iw = 0; iw < int(nw); iw++) { for (int ih = 0; ih < int(nh); ih++) { QGCustomSvg* tile = new QGCustomSvg(); - tile->setScale(m_svgScale); + tile->setScale(m_fillScale); if (tile->load(&colorXML)) { tile->setParentItem(m_rect); tile->setPos(iw*wTile,-h + ih*hTile); @@ -220,7 +344,7 @@ QPixmap QGIFace::textureFromSvg(std::string fileSpec) pixMap.fill(Qt::white); //try Qt::transparent? QPainter painter(&pixMap); renderer.render(&painter); //svg texture -> bitmap - result = pixMap.scaled(m_svgScale,m_svgScale); + result = pixMap.scaled(m_fillScale,m_fillScale); } //else return empty pixmap return result; } @@ -234,7 +358,7 @@ void QGIFace::setHatchColor(std::string c) void QGIFace::setHatchScale(double s) { - m_svgScale = s; + m_fillScale = s; } //QtSvg does not handle clipping, so we must be able to turn the hatching on/off @@ -255,7 +379,7 @@ QPixmap QGIFace::textureFromBitmap(std::string fileSpec) QFileInfo ffi(qs); if (ffi.isReadable()) { QImage img = QImage(qs); - img = img.scaled(Rez::guiX(m_svgScale),Rez::guiX(m_svgScale)); + img = img.scaled(Rez::guiX(m_fillScale),Rez::guiX(m_fillScale)); pix = QPixmap::fromImage(img); } return pix; @@ -296,3 +420,4 @@ void QGIFace::paint ( QPainter * painter, const QStyleOptionGraphicsItem * optio setBrush(m_brush); QGIPrimPath::paint (painter, &myOption, widget); } + diff --git a/src/Mod/TechDraw/Gui/QGIFace.h b/src/Mod/TechDraw/Gui/QGIFace.h index e28fb4a753..561086efb9 100644 --- a/src/Mod/TechDraw/Gui/QGIFace.h +++ b/src/Mod/TechDraw/Gui/QGIFace.h @@ -30,8 +30,12 @@ #include #include +#include + #include "QGIPrimPath.h" +using namespace TechDraw; + namespace TechDrawGui { class QGCustomSvg; @@ -55,48 +59,78 @@ public: virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); public: + enum fillMode { + NoFill, + FromFile, + SvgFill, + BitmapFill, + CrosshatchFill, + PlainFill + }; + + int getProjIndex() const { return projIndex; } void draw(); void setPrettyNormal(); void setPrettyPre(); void setPrettySel(); - void setPath(const QPainterPath & path); 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 resetFill(); - + + //svg fill parms & methods void setHatchFile(std::string fileSpec); void setHatchColor(std::string c); void setHatchScale(double s); - void loadSvgHatch(std::string fileSpec); void buildSvgHatch(void); void toggleSvg(bool b); void clearSvg(void); + + //PAT fill parms & methods +// void setCrosshatch(const QPainterPath& p); + void setCrosshatchColor(const QColor& c); + void setCrosshatchWeight(double w) { m_crossWeight = w; } + //void setLineSets(std::vector ls); + void clearLineSets(void); + void addLineSet(QPainterPath pp, std::vector dp); + QGraphicsPathItem* addFillItem(); + void clearFillItems(void); + //bitmap texture fill parms method QPixmap textureFromBitmap(std::string fileSpec); QPixmap textureFromSvg(std::string fillSpec); - void isHatched(bool s) {m_isHatched = s; } - bool isHatched(void) {return m_isHatched;} - - -protected: -// bool load(QByteArray *svgBytes); - protected: int projIndex; //index of face in Projection. -1 for SectionFace. QGCustomRect *m_rect; + QGCustomSvg *m_svg; QByteArray m_svgXML; std::string m_svgCol; - double m_svgScale; - std::string m_fileSpec; + std::string m_fileSpec; //for svg & bitmaps + + double m_fillScale; bool m_isHatched; - int m_mode; + QGIFace::fillMode m_mode; + + QPen setCrossPen(int i); + QVector decodeDashSpec(DashSpec d); +// QGraphicsPathItem* m_fillItem; + std::vector m_fillItems; + std::vector m_crossHatchPaths; // 0/1 dashspec per crosshatchpath + std::vector m_dashSpecs; + private: QBrush m_brush; @@ -108,7 +142,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_crosshatch; //crosshatch fill lines + + QColor m_crossColor; //color for crosshatch lines + double m_crossWeight; //lineweight for crosshatch lines }; } diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index 61f201f4ef..f22708c400 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -44,6 +44,10 @@ #include #include #include +#include +#include +#include + #include "Rez.h" #include "QGCustomBorder.h" @@ -451,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 hGrp = getParmGroupCol(); diff --git a/src/Mod/TechDraw/Gui/QGIView.h b/src/Mod/TechDraw/Gui/QGIView.h index 008dd5c4c8..eb217b32f5 100644 --- a/src/Mod/TechDraw/Gui/QGIView.h +++ b/src/Mod/TechDraw/Gui/QGIView.h @@ -27,8 +27,10 @@ #include #include +#include #include #include +#include #include @@ -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); diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index f67c5beeaf..39bb34b3b4 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -46,11 +46,13 @@ #include #include #include +#include #include #include #include #include +#include #include #include "Rez.h" @@ -66,6 +68,7 @@ #include "QGCustomRect.h" #include "QGIMatting.h" #include "QGIViewPart.h" +#include "ViewProviderCrosshatch.h" using namespace TechDrawGui; using namespace TechDrawGeometry; @@ -375,21 +378,49 @@ void QGIViewPart::drawViewPart() if (viewPart->handleFaces()) { // Draw Faces std::vector hatchObjs = viewPart->getHatches(); + std::vector crossObjs = viewPart->getCrosshatches(); const std::vector &faceGeoms = viewPart->getFaceGeometry(); std::vector::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) { + TechDraw::DrawCrosshatch* fCross = faceIsCrosshatched(i,crossObjs); + if (fCross) { + std::vector lineSets = fCross->getDrawableLines(); + 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::CrosshatchFill); + newFace->setHatchScale(fCross->ScalePattern.getValue()); + Gui::ViewProvider* gvp = QGIView::getViewProvider(fCross); + ViewProviderCrosshatch* crossVp = dynamic_cast(gvp); + if (crossVp != nullptr) { + App::Color hColor = crossVp->ColorPattern.getValue(); + newFace->setCrosshatchColor(hColor.asValue()); +// newFace->setLineWeight(crossVp->WeightPattern.getValue()); + } + } + } else if (fHatch) { if (!fHatch->HatchPattern.isEmpty()) { newFace->setHatchFile(fHatch->HatchPattern.getValue()); App::Color hColor = fHatch->HatchColor.getValue(); newFace->setHatchColor(hColor.asCSSString()); newFace->setHatchScale(fHatch->HatchScale.getValue()); newFace->isHatched(true); + newFace->setFillMode(QGIFace::FromFile); } - } - newFace->setDrawEdges(false); + } + newFace->setDrawEdges(true); newFace->setZValue(ZVALUE::FACE); newFace->draw(); newFace->setPrettyNormal(); @@ -502,7 +533,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; @@ -853,6 +884,21 @@ TechDraw::DrawHatch* QGIViewPart::faceIsHatched(int i,std::vector crossObjs) const +{ + TechDraw::DrawCrosshatch* result = nullptr; + for (auto& h:crossObjs) { + const std::vector &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; diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.h b/src/Mod/TechDraw/Gui/QGIViewPart.h index d59206ba69..4a82d3102f 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.h +++ b/src/Mod/TechDraw/Gui/QGIViewPart.h @@ -34,6 +34,7 @@ namespace TechDraw { class DrawViewPart; class DrawViewSection; class DrawHatch; +class DrawCrosshatch; } namespace TechDrawGui @@ -89,6 +90,7 @@ protected: virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; TechDraw::DrawHatch* faceIsHatched(int i,std::vector hatchObjs) const; + TechDraw::DrawCrosshatch* faceIsCrosshatched(int i,std::vector crossObjs) const; void dumpPath(const char* text,QPainterPath path); void removePrimitives(void); void removeDecorations(void); diff --git a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc index b44da796f3..8851fbbe5d 100644 --- a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc +++ b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc @@ -49,6 +49,7 @@ icons/actions/techdraw-saveSVG.svg icons/actions/techdraw-viewsection.svg icons/actions/techdraw-hatch.svg + icons/actions/techdraw-crosshatch.svg icons/actions/techdraw-toggleframe.svg icons/actions/techdraw-projgroup.svg icons/actions/techdraw-spreadsheet.svg diff --git a/src/Mod/TechDraw/Gui/Resources/icons/actions/techdraw-crosshatch.svg b/src/Mod/TechDraw/Gui/Resources/icons/actions/techdraw-crosshatch.svg new file mode 100644 index 0000000000..4f60e3142a --- /dev/null +++ b/src/Mod/TechDraw/Gui/Resources/icons/actions/techdraw-crosshatch.svg @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.cpp b/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.cpp new file mode 100644 index 0000000000..abc342a852 --- /dev/null +++ b/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (c) 2004 Jürgen Riegel * + * Copyright (c) 2017 Wandererfan * + * * + * 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 +#include +#include + +#include +#include +#include +#include + +//#include +#include + +#include +#include +#include "ViewProviderCrosshatch.h" + +using namespace TechDrawGui; + +PROPERTY_SOURCE(TechDrawGui::ViewProviderCrosshatch, Gui::ViewProviderDocumentObject) + +//************************************************************************** +// Construction/Destruction + +ViewProviderCrosshatch::ViewProviderCrosshatch() +{ + static const char *vgroup = "Format"; + + sPixmap = "actions/techdraw-crosshatch"; + App::Color fcColor; + fcColor.setPackedValue(0x00000000); + + ADD_PROPERTY_TYPE(ColorPattern,(fcColor),vgroup,App::Prop_None,"The color of the pattern"); + ADD_PROPERTY_TYPE(WeightPattern,(0.0),vgroup,App::Prop_None,"Crosshatch pattern line thickness"); + +} + +ViewProviderCrosshatch::~ViewProviderCrosshatch() +{ +} + +void ViewProviderCrosshatch::attach(App::DocumentObject *pcFeat) +{ + // call parent attach method + ViewProviderDocumentObject::attach(pcFeat); +} + +void ViewProviderCrosshatch::setDisplayMode(const char* ModeName) +{ + ViewProviderDocumentObject::setDisplayMode(ModeName); +} + +std::vector ViewProviderCrosshatch::getDisplayModes(void) const +{ + // get the modes of the father + std::vector StrList = ViewProviderDocumentObject::getDisplayModes(); + + return StrList; +} + +//for VP properties +void ViewProviderCrosshatch::onChanged(const App::Property* prop) +{ +// Base::Console().Message("TRACE - VPC::onChanged(%s)\n",prop->getName()); + + Gui::ViewProviderDocumentObject::onChanged(prop); +} + +//for feature properties +void ViewProviderCrosshatch::updateData(const App::Property* prop) +{ +// Base::Console().Message("TRACE - VPC::updateData(%s)\n",prop->getName()); + if (prop == &WeightPattern || + prop == &ColorPattern || + prop == &(getViewObject()->ScalePattern)) { + //Base::Console().Message("TRACE - VPC::updateData - should update parent now\n"); + //how does QGIVP find this VP to get properties? +// Gui::ViewProvider* view = Application::Instance->getDocument(it->pDoc)->getViewProvider(it->pObject); +// TechDraw::DrawPage* fp = dynamic_cast(getDocument()->getObject(PageName.c_str())); +// Gui::ViewProvider* vp = Gui::Application::Instance->getDocument(getDocument())->getViewProvider(fp); +// TechDrawGui::ViewProviderPage* dvp = dynamic_cast(vp); +// if (dvp) { +// dvp->show(); + + // redraw QGIVP + //QGIView* qgiv = getQView(); this will be different have to find source's QView +// if (qgiv) { +// qgiv->updateView(true); +// } + } + + Gui::ViewProviderDocumentObject::updateData(prop); +} + +TechDraw::DrawCrosshatch* ViewProviderCrosshatch::getViewObject() const +{ + return dynamic_cast(pcObject); +} diff --git a/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.h b/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.h new file mode 100644 index 0000000000..15c52c6821 --- /dev/null +++ b/src/Mod/TechDraw/Gui/ViewProviderCrosshatch.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (c) 2004 Jürgen Riegel * + * Copyright (c) 2017 Wandererfan * + * * + * 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 +#include +#include + +#include + +namespace TechDraw{ + class DrawCrosshatch; +} + +namespace TechDrawGui { + + +class TechDrawGuiExport ViewProviderCrosshatch : public Gui::ViewProviderDocumentObject +{ + PROPERTY_HEADER(TechDrawGui::ViewProviderCrosshatch); + +public: + /// constructor + ViewProviderCrosshatch(); + /// destructor + virtual ~ViewProviderCrosshatch(); + + 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 getDisplayModes(void) const; + + TechDraw::DrawCrosshatch* getViewObject() const; +}; + +} // namespace TechDrawGui + + +#endif // DRAWINGGUI_VIEWPROVIDERHATCH_H diff --git a/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp b/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp index c510be33d9..049629c9cc 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "ViewProviderViewPart.h" @@ -117,6 +118,7 @@ std::vector ViewProviderViewPart::claimChildren(void) cons // valid children of a ViewPart are: // - Dimensions // - Hatches + // - Crosshatches std::vector temp; const std::vector &views = getViewPart()->getInList(); try { @@ -132,6 +134,8 @@ std::vector ViewProviderViewPart::claimChildren(void) cons } } else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawHatch::getClassTypeId())) { temp.push_back((*it)); + } else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawCrosshatch::getClassTypeId())) { + temp.push_back((*it)); } } return temp; diff --git a/src/Mod/TechDraw/Gui/Workbench.cpp b/src/Mod/TechDraw/Gui/Workbench.cpp index 26462e84b0..816420245b 100644 --- a/src/Mod/TechDraw/Gui/Workbench.cpp +++ b/src/Mod/TechDraw/Gui/Workbench.cpp @@ -133,6 +133,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const Gui::ToolBarItem *decor = new Gui::ToolBarItem(root); decor->setCommand("TechDraw Decoration"); *decor << "TechDraw_NewHatch"; + *decor << "TechDraw_NewCrosshatch"; *decor << "TechDraw_Image"; *decor << "TechDraw_ToggleFrame"; return root; @@ -182,6 +183,7 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const Gui::ToolBarItem *decor = new Gui::ToolBarItem(root); decor->setCommand("TechDraw Decoration"); *decor << "TechDraw_NewHatch"; + *decor << "TechDraw_NewCrosshatch"; *decor << "TechDraw_Image"; *decor << "TechDraw_ToggleFrame"; diff --git a/src/Mod/TechDraw/PAT/FCStd.pat b/src/Mod/TechDraw/PAT/FCStd.pat new file mode 100644 index 0000000000..66b91d9cec --- /dev/null +++ b/src/Mod/TechDraw/PAT/FCStd.pat @@ -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 +