diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index dd23815f0..2ffb8d570 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -89,14 +89,15 @@ DrawViewPart::DrawViewPart(void) : geometryObject(0) ADD_PROPERTY_TYPE(Direction ,(0,0,1.0) ,group,App::Prop_None,"Projection normal direction"); ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"3D Shape to view"); - ADD_PROPERTY_TYPE(ShowHiddenLines ,(false),group,App::Prop_None,"Control the appearance of the dashed hidden lines"); - ADD_PROPERTY_TYPE(ShowSmoothLines ,(false),group,App::Prop_None,"Control the appearance of the smooth lines"); - ADD_PROPERTY_TYPE(LineWidth,(0.7f),vgroup,App::Prop_None,"The thickness of the resulting lines"); - ADD_PROPERTY_TYPE(HiddenWidth,(0.15),vgroup,App::Prop_None,"The thickness of the hidden lines, if enabled"); + ADD_PROPERTY_TYPE(ShowHiddenLines ,(false),group,App::Prop_None,"Hidden lines on/off"); + ADD_PROPERTY_TYPE(ShowSmoothLines ,(false),group,App::Prop_None,"Smooth lines on/off"); + ADD_PROPERTY_TYPE(ShowSeamLines ,(false),group,App::Prop_None,"Seam lines on/off"); + //ADD_PROPERTY_TYPE(ShowIsoLines ,(false),group,App::Prop_None,"Iso u,v lines on/off"); + ADD_PROPERTY_TYPE(LineWidth,(0.7f),vgroup,App::Prop_None,"The thickness of visible lines"); + ADD_PROPERTY_TYPE(HiddenWidth,(0.15),vgroup,App::Prop_None,"The thickness of hidden lines, if enabled"); ADD_PROPERTY_TYPE(Tolerance,(0.05f),vgroup,App::Prop_None,"The tessellation tolerance"); Tolerance.setConstraints(&floatRange); - ADD_PROPERTY_TYPE(XAxisDirection ,(1,0,0) ,group,App::Prop_None,"X-Axis direction"); - //ADD_PROPERTY_TYPE(HatchAreas ,(0),vgroup,App::Prop_None,"Hatched areas of this view"); + ADD_PROPERTY_TYPE(XAxisDirection ,(1,0,0) ,group,App::Prop_None,"Direction to use as X-axis in projection"); geometryObject = new TechDrawGeometry::GeometryObject(); } @@ -124,22 +125,13 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void) } try { - geometryObject->setTolerance(Tolerance.getValue()); - geometryObject->setScale(Scale.getValue()); - geometryObject->extractGeometry(shape, - Direction.getValue(), - ShowHiddenLines.getValue(), - _getValidXDir(this)); - bbox = geometryObject->calcBoundingBox(); - touch(); - + buildGeometryObject(shape); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } - // There is a guaranteed change so check any references linked to this and touch // We need to update all views pointing at this (ProjectionGroup, ClipGroup, etc) std::vector parent = getInList(); @@ -150,6 +142,7 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void) } } + touch(); return DrawView::execute(); } @@ -160,7 +153,9 @@ short DrawViewPart::mustExecute() const Source.isTouched() || Scale.isTouched() || ScaleType.isTouched() || - ShowHiddenLines.isTouched()); + ShowHiddenLines.isTouched() || + ShowSmoothLines.isTouched() || + ShowSeamLines.isTouched()); return result; } @@ -172,7 +167,9 @@ void DrawViewPart::onChanged(const App::Property* prop) prop == &Source || prop == &Scale || prop == &ScaleType || - prop == &ShowHiddenLines) { + prop == &ShowHiddenLines || + prop == &ShowSmoothLines || + prop == &ShowSeamLines) { try { App::DocumentObjectExecReturn *ret = recompute(); delete ret; @@ -183,43 +180,45 @@ void DrawViewPart::onChanged(const App::Property* prop) } DrawView::onChanged(prop); -//TODO: when scale changes, any Dimensions for this View sb recalculated. +//TODO: when scale changes, any Dimensions for this View sb recalculated. (might happen anyway if document is recomputed?) } -#if 0 -int DrawViewPart::addHatch(App::DocumentObject *docObj) +void DrawViewPart::buildGeometryObject(TopoDS_Shape shape) { - if(!docObj->isDerivedFrom(TechDraw::DrawHatch::getClassTypeId())) - return -1; - - const std::vector currAreas = HatchAreas.getValues(); - std::vector newAreas(currAreas); - newAreas.push_back(docObj); - HatchAreas.setValues(newAreas); - HatchAreas.touch(); - return HatchAreas.getSize(); -} - -int DrawViewPart::removeHatch(App::DocumentObject *docObj) -{ - if(!docObj->isDerivedFrom(TechDraw::DrawHatch::getClassTypeId())) - return -1; - - const std::vector currAreas = HatchAreas.getValues(); - std::vector newAreas; - std::vector::const_iterator it = currAreas.begin(); - for (; it != currAreas.end(); it++) { - std::string areaName = docObj->getNameInDocument(); - if (areaName.compare((*it)->getNameInDocument()) != 0) { - newAreas.push_back((*it)); - } + geometryObject->setTolerance(Tolerance.getValue()); + geometryObject->setScale(Scale.getValue()); + //TODO: need to pass ShowSmoothLines, ShowSeamLines + //geometryObject->extractGeometry(shape, + // Direction.getValue(), + // ShowHiddenLines.getValue(), + // _getValidXDir(this)); + geometryObject->initHLR(shape, + Direction.getValue(), + _getValidXDir(this)); + geometryObject->extractGeometry(TechDrawGeometry::ecHARD, + true); + geometryObject->extractGeometry(TechDrawGeometry::ecOUTLINE, + true); + if (ShowSmoothLines.getValue()) { + geometryObject->extractGeometry(TechDrawGeometry::ecSMOOTH, + true); } - HatchAreas.setValues(newAreas); - HatchAreas.touch(); - - return HatchAreas.getSize(); + if (ShowSeamLines.getValue()) { + geometryObject->extractGeometry(TechDrawGeometry::ecSEAM, + true); + } + //if (ShowIsoLines.getValue()) { + // geometryObject->extractGeometry(TechDrawGeometry::ecUVISO, + // true); + //} + if (ShowHiddenLines.getValue()) { + geometryObject->extractGeometry(TechDrawGeometry::ecHARD, + false); + //geometryObject->extractGeometry(TechDrawGeometry::ecOUTLINE, //hidden outline,smooth,seam?? + // true); + } + bbox = geometryObject->calcBoundingBox(); } -#endif std::vector DrawViewPart::getHatches() const { diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index 0b6e12333..75edccee9 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -51,10 +51,11 @@ public: virtual ~DrawViewPart(); App::PropertyLink Source; //Part Feature - App::PropertyVector Direction; //TODO: Rename to YAxisDirection or whatever this actually is + App::PropertyVector Direction; //TODO: Rename to YAxisDirection or whatever this actually is (ProjectionDirection) App::PropertyVector XAxisDirection; App::PropertyBool ShowHiddenLines; App::PropertyBool ShowSmoothLines; + App::PropertyBool ShowSeamLines; App::PropertyFloat LineWidth; App::PropertyFloat HiddenWidth; App::PropertyFloatConstraint Tolerance; @@ -108,7 +109,7 @@ public: protected: void onChanged(const App::Property* prop); - + void buildGeometryObject(TopoDS_Shape shape); TechDrawGeometry::GeometryObject *geometryObject; Base::BoundBox3d bbox; diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 366db9a79..09c843aa4 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -204,26 +204,37 @@ App::DocumentObjectExecReturn *DrawViewSection::execute(void) if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Section cut has failed"); - // Cache the result - result = mkCut.Shape(); + // Cache the sectionShape + sectionShape = mkCut.Shape(); try { - geometryObject->setTolerance(Tolerance.getValue()); - geometryObject->setScale(Scale.getValue()); - //TODO: Do we need to check for nonzero XAxisDirection here? - geometryObject->extractGeometry(result, Direction.getValue(), ShowHiddenLines.getValue(), XAxisDirection.getValue()); - bbox = geometryObject->calcBoundingBox(); - - touch(); + buildGeometryObject(sectionShape); } catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - Base::Console().Log("DrawViewSection::execute - extractGeometry failed: %s\n",e->GetMessageString()); - return new App::DocumentObjectExecReturn(e->GetMessageString()); + Handle_Standard_Failure e1 = Standard_Failure::Caught(); + Base::Console().Log("DrawViewSection::execute - extractGeometry failed: %s\n",e1->GetMessageString()); + return new App::DocumentObjectExecReturn(e1->GetMessageString()); + } + + TopoDS_Compound sectionFaces; + try { + sectionFaces = getSectionFaces(); + } + catch (Standard_Failure) { + Handle_Standard_Failure e2 = Standard_Failure::Caught(); + Base::Console().Log("DrawViewSection::execute - getSectionFaces failed: %s\n",e2->GetMessageString()); + return new App::DocumentObjectExecReturn(e2->GetMessageString()); + } + + if (!sectionFaces.IsNull()) { + //TODO: do something with sectionFaces + //?add to GeometryObject faceGeom? but need to tag these faces as "special" + //how does QGIVSection know to shade these faces?? } // TODO: touch references? see DrawViewPart.execute() - return DrawView::execute(); //sb DrawViewPart? + touch(); + return DrawView::execute(); //note: not DrawViewPart } gp_Pln DrawViewSection::getSectionPlane() const @@ -234,39 +245,37 @@ gp_Pln DrawViewSection::getSectionPlane() const return gp_Pln(gp_Pnt(plnPnt.x, plnPnt.y, plnPnt.z), gp_Dir(plnNorm.x, plnNorm.y, plnNorm.z)); } -//! tries to find the intersection of the section plane with the part??? -//face logic is turned off in GeometryObject, so this won't work now. -void DrawViewSection::getSectionSurface(std::vector §ionFace) const { - -#if MOD_TECHDRAW_HANDLE_FACES - if(result.IsNull()){ - //throw Base::Exception("Sectional View Result is Empty"); - Base::Console().Log("DrawViewSection::getSectionSurface - Sectional View Result is Empty\n"); - return; +//! tries to find the intersection of the section plane with the sectionShape (a collection of planar faces) +TopoDS_Compound DrawViewSection::getSectionFaces(void) +{ + TopoDS_Compound result; + if(sectionShape.IsNull()){ + //throw Base::Exception("Sectional View sectionShape is Empty"); + Base::Console().Log("DrawViewSection::getSectionSurface - Sectional View sectionShape is Empty\n"); + return result; } gp_Pln pln = getSectionPlane(); BRep_Builder builder; - TopoDS_Compound comp; - builder.MakeCompound(comp); + builder.MakeCompound(result); // Iterate through all faces - TopExp_Explorer face(result, TopAbs_FACE); - for ( ; faces.More(); faces.Next()) { - const TopoDS_Face& face = TopoDS::Face(faces.Current()); + TopExp_Explorer expFaces(sectionShape, TopAbs_FACE); + for ( ; expFaces.More(); expFaces.Next()) { + const TopoDS_Face& face = TopoDS::Face(expFaces.Current()); BRepAdaptor_Surface adapt(face); if (adapt.GetType() == GeomAbs_Plane){ gp_Pln plane = adapt.Plane(); if(plane.Contains(pln.Location(), Precision::Confusion()) && plane.Axis().IsParallel(pln.Axis(), Precision::Angular())) { - builder.Add(comp, face); + builder.Add(result, face); } } } - //TODO: Do we need to check for nonzero XAxisDirection here? - geometryObject->projectSurfaces(comp, result, Direction.getValue(), XAxisDirection.getValue(), sectionFace); -#endif + return result; } + + // Python Drawing feature --------------------------------------------------------- namespace App { diff --git a/src/Mod/TechDraw/App/DrawViewSection.h b/src/Mod/TechDraw/App/DrawViewSection.h index 099d0936c..12d7e763c 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.h +++ b/src/Mod/TechDraw/App/DrawViewSection.h @@ -30,6 +30,7 @@ #include "DrawViewPart.h" class gp_Pln; +class TopoDS_Compound; namespace TechDraw { @@ -65,10 +66,10 @@ public: } public: - void getSectionSurface(std::vector §ionFace) const; + TopoDS_Compound getSectionFaces(void); protected: - TopoDS_Shape result; + TopoDS_Shape sectionShape; gp_Pln getSectionPlane() const; }; diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index fb5f6907c..344796590 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -109,50 +110,23 @@ Face::~Face() BaseGeom::BaseGeom() : geomType(NOTDEF), - reversed(false) + extractType(Plain), + classOfEdge(ecNONE), + visible(true), + reversed(false), + ref3D(-1) { } -//! ugh. yuck. std::vector BaseGeom::findEndPoints() { std::vector result; - switch(this->geomType) { - case TechDrawGeometry::CIRCLE: { - TechDrawGeometry::Circle *geom = static_cast(this); - double x = geom->center.fX + geom->radius; - result.push_back(Base::Vector2D(x,geom->center.fY)); - result.push_back(Base::Vector2D(x,geom->center.fY)); - } break; - case TechDrawGeometry::ARCOFCIRCLE: { - TechDrawGeometry::AOC *geom = static_cast(this); - result.push_back(geom->startPnt); - result.push_back(geom->endPnt); - } break; - case TechDrawGeometry::ELLIPSE: { - TechDrawGeometry::Ellipse *geom = static_cast(this); - result.push_back(geom->center + Base::Vector2D(geom->major * cos(geom->angle), geom->major * sin(geom->angle))); - result.push_back(geom->center + Base::Vector2D(geom->major * cos(geom->angle), geom->major * sin(geom->angle))); - } break; - case TechDrawGeometry::ARCOFELLIPSE: { - TechDrawGeometry::AOE *geom = static_cast(this); - result.push_back(geom->startPnt); - result.push_back(geom->endPnt); - } break; - case TechDrawGeometry::BSPLINE: { - TechDrawGeometry::BSpline *geom = static_cast(this); - result.push_back(geom->segments.front().pnts[0]); - TechDrawGeometry::BezierSegment tempSeg = geom->segments.back(); - result.push_back(tempSeg.pnts[tempSeg.poles - 1]); - } break; - case TechDrawGeometry::GENERIC: { - TechDrawGeometry::Generic *geom = static_cast(this); - result.push_back(geom->points.front()); - result.push_back(geom->points.back()); - } break; - default: - break; - } + //if (occEdge) { + gp_Pnt p = BRep_Tool::Pnt(TopExp::FirstVertex(occEdge)); + result.push_back(Base::Vector2D(p.X(),p.Y())); + p = BRep_Tool::Pnt(TopExp::LastVertex(occEdge)); + result.push_back(Base::Vector2D(p.X(),p.Y())); + //} return result; } @@ -168,15 +142,11 @@ Base::Vector2D BaseGeom::getEndPoint() return verts[1]; } -Ellipse::Ellipse() +Ellipse::Ellipse(const TopoDS_Edge &e) { geomType = ELLIPSE; -} - -Ellipse::Ellipse(const BRepAdaptor_Curve& c) -{ - geomType = ELLIPSE; - + BRepAdaptor_Curve c(e); + occEdge = e; gp_Elips ellp = c.Ellipse(); const gp_Pnt &p = ellp.Location(); @@ -189,23 +159,20 @@ Ellipse::Ellipse(const BRepAdaptor_Curve& c) angle = xaxis.AngleWithRef(gp_Dir(1, 0, 0), gp_Dir(0, 0, -1)); } -AOE::AOE() -{ - geomType = ARCOFELLIPSE; -} -AOE::AOE(const BRepAdaptor_Curve& c) : Ellipse(c) +AOE::AOE(const TopoDS_Edge &e) : Ellipse(e) { geomType = ARCOFELLIPSE; + BRepAdaptor_Curve c(e); double f = c.FirstParameter(); double l = c.LastParameter(); gp_Pnt s = c.Value(f); gp_Pnt m = c.Value((l+f)/2.0); - gp_Pnt e = c.Value(l); + gp_Pnt ePt = c.Value(l); gp_Vec v1(m,s); - gp_Vec v2(m,e); + gp_Vec v2(m,ePt); gp_Vec v3(0,0,1); double a = v3.DotCross(v1,v2); @@ -215,38 +182,15 @@ AOE::AOE(const BRepAdaptor_Curve& c) : Ellipse(c) largeArc = (l-f > M_PI) ? true : false; startPnt = Base::Vector2D(s.X(), s.Y()); - endPnt = Base::Vector2D(e.X(), e.Y()); + endPnt = Base::Vector2D(ePt.X(), ePt.Y()); midPnt = Base::Vector2D(m.X(), m.Y()); - /* - char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag - char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) - out << "" << std::endl; -// if (startAngle > endAngle) {// if arc is reversed -// std::swap(startAngle, endAngle); -// }*/ - -// double ax = s.X() - center.fX; -// double ay = s.Y() - center.fY; -// double bx = e.X() - center.fX; -// double by = e.Y() - center.fY; - -// startAngle = f; -// float range = l-f; -// -// endAngle = startAngle + range; } -Circle::Circle() -{ - geomType = CIRCLE; -} - -Circle::Circle(const BRepAdaptor_Curve& c) +Circle::Circle(const TopoDS_Edge &e) { geomType = CIRCLE; + BRepAdaptor_Curve c(e); + occEdge = e; gp_Circ circ = c.Circle(); const gp_Pnt& p = circ.Location(); @@ -255,23 +199,19 @@ Circle::Circle(const BRepAdaptor_Curve& c) center = Base::Vector2D(p.X(), p.Y()); } -AOC::AOC() -{ - geomType = ARCOFCIRCLE; -} - -AOC::AOC(const BRepAdaptor_Curve& c) : Circle(c) +AOC::AOC(const TopoDS_Edge &e) : Circle(e) { geomType = ARCOFCIRCLE; + BRepAdaptor_Curve c(e); double f = c.FirstParameter(); double l = c.LastParameter(); gp_Pnt s = c.Value(f); gp_Pnt m = c.Value((l+f)/2.0); - gp_Pnt e = c.Value(l); + gp_Pnt ePt = c.Value(l); gp_Vec v1(m,s); - gp_Vec v2(m,e); + gp_Vec v2(m,ePt); gp_Vec v3(0,0,1); double a = v3.DotCross(v1,v2); @@ -281,46 +221,49 @@ AOC::AOC(const BRepAdaptor_Curve& c) : Circle(c) largeArc = (l-f > M_PI) ? true : false; startPnt = Base::Vector2D(s.X(), s.Y()); - endPnt = Base::Vector2D(e.X(), e.Y()); + endPnt = Base::Vector2D(ePt.X(), ePt.Y()); midPnt = Base::Vector2D(m.X(), m.Y()); } + +//!Generic is a multiline +Generic::Generic(const TopoDS_Edge &e) +{ + geomType = GENERIC; + occEdge = e; + BRepLib::BuildCurve3d(occEdge); + + TopLoc_Location location; + Handle_Poly_Polygon3D polygon = BRep_Tool::Polygon3D(occEdge, location); + + if (!polygon.IsNull()) { + const TColgp_Array1OfPnt &nodes = polygon->Nodes(); + for (int i = nodes.Lower(); i <= nodes.Upper(); i++){ + points.push_back(Base::Vector2D(nodes(i).X(), nodes(i).Y())); + } + } else { + //no polygon representation? approximate with line? + Base::Console().Log("INFO - Generic::Generic(edge) - polygon is NULL\n"); + gp_Pnt p = BRep_Tool::Pnt(TopExp::FirstVertex(occEdge)); + points.push_back(Base::Vector2D(p.X(), p.Y())); + p = BRep_Tool::Pnt(TopExp::LastVertex(occEdge)); + points.push_back(Base::Vector2D(p.X(), p.Y())); + } +} + Generic::Generic() { geomType = GENERIC; } -Generic::Generic(const BRepAdaptor_Curve& c) -{ - geomType = GENERIC; - - TopLoc_Location location; - Handle_Poly_Polygon3D polygon = BRep_Tool::Polygon3D(c.Edge(), location); - if (!polygon.IsNull()) { - const TColgp_Array1OfPnt &nodes = polygon->Nodes(); - for (int i = nodes.Lower(); i <= nodes.Upper(); i++){ - points.push_back(Base::Vector2D(nodes(i).X(), nodes(i).Y())); - } - } -} - -Generic::Generic(Base::Vector2D start, Base::Vector2D end) -{ - geomType = GENERIC; - points.push_back(start); - points.push_back(end); -} - -BSpline::BSpline() -{ - geomType = BSPLINE; -} - -BSpline::BSpline(const BRepAdaptor_Curve &c) +BSpline::BSpline(const TopoDS_Edge &e) { geomType = BSPLINE; + BRepAdaptor_Curve c(e); + occEdge = e; Handle_Geom_BSplineCurve spline = c.BSpline(); - if (spline->Degree() > 3) { + + if (spline->Degree() > 3) { //if spline is too complex, approximate it Standard_Real tol3D = 0.001; Standard_Integer maxDegree = 3, maxSegment = 10; Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c); @@ -359,6 +302,14 @@ BSpline::BSpline(const BRepAdaptor_Curve &c) //! can this BSpline be represented by a straight line? bool BSpline::isLine() { + bool result = false; + BRepAdaptor_Curve c(occEdge); + Handle_Geom_BSplineCurve spline = c.BSpline(); + if (spline->Degree() == 1) { + result = true; + } + return result; +#if 0 bool result = true; std::vector::iterator iSeg = segments.begin(); double slope; @@ -378,6 +329,18 @@ bool BSpline::isLine() } } return result; +#endif +} + +//**** Vertex +bool Vertex::isEqual(Vertex* v, double tol) +{ + bool result = false; + double dist = (pnt - (v->pnt)).Length(); + if (dist <= tol) { + result = true; + } + return result; } //**** TechDrawGeometry utility funtions @@ -401,7 +364,7 @@ std::vector TechDrawExport chainGeoms(std::vectorgetEndPoint(); used[0] = true; for (unsigned int i = 1; i < geoms.size(); i++) { //do size-1 more edges - getNextReturn next = nextGeom(atPoint,geoms,used,tolerance); + getNextReturnVal next = nextGeom(atPoint,geoms,used,tolerance); if (next.index) { //found an unused edge with vertex == atPoint TechDrawGeometry::BaseGeom* nextEdge = geoms.at(next.index); used[next.index] = true; @@ -422,12 +385,12 @@ std::vector TechDrawExport chainGeoms(std::vector geoms, std::vector used, double tolerance) { - getNextReturn result(0,false); + getNextReturnVal result(0,false); std::vector::iterator itGeom = geoms.begin(); for (; itGeom != geoms.end(); itGeom++) { unsigned int index = itGeom - geoms.begin(); diff --git a/src/Mod/TechDraw/App/Geometry.h b/src/Mod/TechDraw/App/Geometry.h index db1424125..c4bf2fc53 100644 --- a/src/Mod/TechDraw/App/Geometry.h +++ b/src/Mod/TechDraw/App/Geometry.h @@ -24,16 +24,29 @@ #define TECHDRAW_GEOMETRY_H #include +#include +#include +#include + class BRepAdaptor_Curve; namespace TechDrawGeometry { -enum ExtractionType { +enum ExtractionType { //obs sb vis/hid + hard/smooth/seam/out(edgeClass?) Plain = 0, WithHidden = 1, WithSmooth = 2 }; +enum edgeClass { + ecNONE, //not used, OCC index starts at 1 + ecUVISO, + ecOUTLINE, + ecSMOOTH, + ecSEAM, + ecHARD +}; + enum GeomType { NOTDEF, CIRCLE, @@ -48,11 +61,15 @@ class TechDrawExport BaseGeom { public: BaseGeom(); - ~BaseGeom() {} + virtual ~BaseGeom() {} public: GeomType geomType; - ExtractionType extractType; + ExtractionType extractType; //obs + edgeClass classOfEdge; + bool visible; bool reversed; + int ref3D; + TopoDS_Edge occEdge; //projected Edge std::vector findEndPoints(); Base::Vector2D getStartPoint(); Base::Vector2D getEndPoint(); @@ -61,8 +78,7 @@ public: class TechDrawExport Circle: public BaseGeom { public: - Circle(const BRepAdaptor_Curve &c); - Circle(); + Circle(const TopoDS_Edge &e); ~Circle() {} public: Base::Vector2D center; @@ -72,8 +88,7 @@ public: class TechDrawExport Ellipse: public BaseGeom { public: - Ellipse(const BRepAdaptor_Curve &c); - Ellipse(); + Ellipse(const TopoDS_Edge &e); ~Ellipse() {} public: Base::Vector2D center; @@ -86,8 +101,7 @@ public: class TechDrawExport AOE: public Ellipse { public: - AOE(const BRepAdaptor_Curve &c); - AOE(); + AOE(const TopoDS_Edge &e); ~AOE() {} public: Base::Vector2D startPnt; //TODO: The points are used for drawing, the angles for bounding box calcs - seems redundant @@ -105,8 +119,7 @@ public: class TechDrawExport AOC: public Circle { public: - AOC(const BRepAdaptor_Curve &c); - AOC(); + AOC(const TopoDS_Edge &e); ~AOC() {} public: Base::Vector2D startPnt; @@ -142,23 +155,20 @@ struct BezierSegment class TechDrawExport BSpline: public BaseGeom { public: - BSpline(const BRepAdaptor_Curve &c); - BSpline(); + BSpline(const TopoDS_Edge &e); ~BSpline(){} public: bool isLine(void); std::vector segments; }; -class Generic: public BaseGeom +class TechDrawExport Generic: public BaseGeom { public: - Generic(Base::Vector2D start, Base::Vector2D end); - Generic(const BRepAdaptor_Curve& c); + Generic(const TopoDS_Edge &e); Generic(); ~Generic() {} std::vector points; - }; /// Simple Collection of geometric features based on BaseGeom inherited classes in order @@ -177,30 +187,35 @@ struct TechDrawExport Face std::vector wires; }; -/// Simple vertex -struct TechDrawExport Vertex +//! 2D Vertex +class TechDrawExport Vertex { +public: Vertex(double x, double y) { pnt = Base::Vector2D(x, y); } Vertex(Base::Vector2D v) { pnt = v; } ~Vertex() {} Base::Vector2D pnt; ExtractionType extractType; + bool visible; + int ref3D; + TopoDS_Vertex occVertex; + bool isEqual(Vertex* v, double tol); }; //*** utility functions extern "C" { -struct TechDrawExport getNextReturn { +struct TechDrawExport getNextReturnVal { unsigned int index; bool reversed; - explicit getNextReturn(int i = 0, bool r = false) : + explicit getNextReturnVal(int i = 0, bool r = false) : index(i), reversed(r) {} }; std::vector chainGeoms(std::vector geoms); -getNextReturn nextGeom(Base::Vector2D atPoint, +getNextReturnVal nextGeom(Base::Vector2D atPoint, std::vector geoms, std::vector used, double tolerance); diff --git a/src/Mod/TechDraw/App/GeometryObject.cpp b/src/Mod/TechDraw/App/GeometryObject.cpp index 52ad005d8..ec7dce6bb 100644 --- a/src/Mod/TechDraw/App/GeometryObject.cpp +++ b/src/Mod/TechDraw/App/GeometryObject.cpp @@ -68,6 +68,7 @@ # include # include # include +# include # include # include # include @@ -76,6 +77,9 @@ # include # include +#include +#include + // # include # include @@ -110,7 +114,13 @@ struct EdgePoints { TopoDS_Edge edge; }; -GeometryObject::GeometryObject() : brep_hlr(0), Tolerance(0.05f), Scale(1.f) +//debugging routine signatures +void _dumpEdgeData(char* label, int i, HLRBRep_EdgeData& ed); +const char* _printBool(bool b); +void _dumpEdge(char* label, int i, TopoDS_Edge e); + + +GeometryObject::GeometryObject() : brep_hlr(NULL), Tolerance(0.05f), Scale(1.f) { } @@ -157,138 +167,269 @@ void GeometryObject::clear() edgeReferences.clear(); } -void GeometryObject::drawFace (const bool visible, const int iface, - Handle_HLRBRep_Data & DS, - TopoDS_Shape& Result) const +//!set up a hidden line remover and load a shape into it +void GeometryObject::initHLR(const TopoDS_Shape &input, + const Base::Vector3d &direction, + const Base::Vector3d &xAxis) { -// add all the edges for this face(iface) to Result - HLRBRep_FaceIterator Itf; + // Clear previous Geometry and References that may have been stored + //TODO: hate losing references on recompute! if Shape has changed, aren't reference potentially invalid anyway? + clear(); + if (brep_hlr) { + brep_hlr->Remove(1); //remove the old shape from brep (use NbShapes() first? would we ever have > 1 shape?) + //delete brep_hlr; //release old hlralgo + //brep_hlr = NULL; + } - for (Itf.InitEdge(DS->FDataArray().ChangeValue(iface)); Itf.MoreEdge(); Itf.NextEdge()) { - int ie = Itf.Edge(); - // if (std::find(used.begin(),used.end(),ie) == used.end()) { //only use an edge once - HLRBRep_EdgeData& edf = DS->EDataArray().ChangeValue(ie); - if(edf.Status().NbVisiblePart() > 0) { - drawEdge(edf, Result, visible); - } -// double first = edf.Geometry().FirstParameter(); -// double last = edf.Geometry().LastParameter(); -// gp_Pnt p0 = edf.Geometry().Value3D(first); -// gp_Pnt p1 = edf.Geometry().Value3D(last); -// qDebug()<Add(transShape); + + // Project the shape into view space with the object's centroid + // at the origin. + gp_Ax2 viewAxis; + viewAxis = gp_Ax2(inputCentre, + gp_Dir(direction.x, direction.y, direction.z), + gp_Dir(xAxis.x, xAxis.y, xAxis.z)); + HLRAlgo_Projector projector( viewAxis ); + brep_hlr->Projector(projector); + brep_hlr->Update(); + brep_hlr->Hide(); + } + catch (...) { + Standard_Failure::Raise("GeometryObject::initHLR - error occurred while projecting shape"); } } -void GeometryObject::drawEdge(HLRBRep_EdgeData& ed, TopoDS_Shape& Result, const bool visible) const +//!add edges meeting filter criteria for category, visibility +void GeometryObject::extractGeometry(edgeClass category, bool visible) { - double sta,end; - float tolsta,tolend; - - BRep_Builder B; - TopoDS_Edge E; - HLRAlgo_EdgeIterator It; - + HLRBRep_HLRToShape hlrToShape(brep_hlr); + TopoDS_Shape filtEdges; if (visible) { - for(It.InitVisible(ed.Status()); It.MoreVisible(); It.NextVisible()) { - It.Visible(sta,tolsta,end,tolend); - E = HLRBRep::MakeEdge(ed.Geometry(),sta,end); - if (!E.IsNull()) { - B.Add(Result,E); - } + switch (category) { + case ecHARD: + filtEdges = hlrToShape.VCompound(); + break; + case ecOUTLINE: + filtEdges = hlrToShape.OutLineVCompound(); + break; + case ecSMOOTH: + filtEdges = hlrToShape.Rg1LineVCompound(); + break; + case ecSEAM: + filtEdges = hlrToShape.RgNLineHCompound(); + break; + default: + Base::Console().Warning("GeometryObject::ExtractGeometry - unsupported visible edgeClass: %d\n",category); + return; } } else { - for(It.InitHidden(ed.Status()); It.MoreHidden(); It.NextHidden()) { - It.Hidden(sta,tolsta,end,tolend); - E = HLRBRep::MakeEdge(ed.Geometry(),sta,end); - if (!E.IsNull()) { - B.Add(Result,E); + switch (category) { + case ecHARD: + filtEdges = hlrToShape.HCompound(); + break; + //more cases here? + default: + Base::Console().Warning("GeometryObject::ExtractGeometry - unsupported hidden edgeClass: %d\n",category); + return; + } + } + + addGeomFromCompound(filtEdges, category, visible); +} + +//! update edgeGeom and vertexGeom from Compound of edges +void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass category, bool visible) +{ + if(edgeCompound.IsNull()) { + Base::Console().Log("TechDraw::GeometryObject::addGeomFromCompound edgeCompound is NULL\n"); + return; // There is no OpenCascade Geometry to be calculated + } + + // build a mesh to explore the shape + BRepMesh_IncrementalMesh(edgeCompound, Tolerance); //no idea why we need to mesh shape + + // Explore all edges of edgeCompound and calculate base geometry representation + BaseGeom* base; + TopExp_Explorer edges(edgeCompound, TopAbs_EDGE); + for (int i = 1 ; edges.More(); edges.Next(),i++) { + const TopoDS_Edge& edge = TopoDS::Edge(edges.Current()); + if (edge.IsNull()) { + Base::Console().Log("INFO - GO::addGeomFromCompound - edge: %d is NULL\n",i); + continue; + } + base = edgeToBase(edge); + base->classOfEdge = category; + base->visible = visible; + edgeGeom.push_back(base); + edgeReferences.push_back(-1); + + //add vertices of new edge if not already in list + if (visible) { + BaseGeom* lastAdded = edgeGeom.back(); + //if (edgeGeom.empty()) {horrible_death();} //back() undefined behavior (can't happen? edgeToBase always returns a Base?) + bool v1Add = true, v2Add = true; + TechDrawGeometry::Vertex* v1 = new TechDrawGeometry::Vertex(lastAdded->getStartPoint()); + TechDrawGeometry::Vertex* v2 = new TechDrawGeometry::Vertex(lastAdded->getEndPoint()); + std::vector::iterator itVertex = vertexGeom.begin(); + for (; itVertex != vertexGeom.end(); itVertex++) { + if ((*itVertex)->isEqual(v1,Tolerance)) { + v1Add = false; + } + if ((*itVertex)->isEqual(v2,Tolerance)) { + v2Add = false; + } + } + if (v1Add) { + vertexGeom.push_back(v1); + v1->visible = true; + vertexReferences.push_back(-1); + } else { + delete v1; + } + if (v2Add) { + vertexGeom.push_back(v2); + v2->visible = true; + vertexReferences.push_back(-1); + } else { + delete v2; } } + } } -//! only ever called from FVP::getVertex -TechDrawGeometry::Vertex * GeometryObject::projectVertex(const TopoDS_Shape &vert, - const TopoDS_Shape &support, - const Base::Vector3d &direction, - const Base::Vector3d &projXAxis) const +//!convert 1 OCC edge into 1 BaseGeom +BaseGeom* GeometryObject::edgeToBase(TopoDS_Edge edge) { - if(vert.IsNull()) - throw Base::Exception("Projected vertex is null"); + BaseGeom* result = NULL; + BRepAdaptor_Curve adapt(edge); - gp_Pnt supportCentre = findCentroid(support, direction, projXAxis); + switch(adapt.GetType()) { + case GeomAbs_Circle: { + double f = adapt.FirstParameter(); + double l = adapt.LastParameter(); + gp_Pnt s = adapt.Value(f); + gp_Pnt e = adapt.Value(l); - // mirror+scale vert around centre of support - gp_Trsf mat; - mat.SetMirror(gp_Ax2(supportCentre, gp_Dir(0, 1, 0))); - gp_Trsf matScale; - matScale.SetScale(supportCentre, Scale); - mat.Multiply(matScale); - - //TODO: See if it makes sense to use gp_Trsf::Transforms() instead - BRepBuilderAPI_Transform mkTrfScale(vert, mat); - const TopoDS_Vertex &refVert = TopoDS::Vertex(mkTrfScale.Shape()); - - gp_Ax2 transform; - transform = gp_Ax2(supportCentre, - gp_Dir(direction.x, direction.y, direction.z), - gp_Dir(projXAxis.x, projXAxis.y, projXAxis.z)); - - HLRAlgo_Projector projector = HLRAlgo_Projector( transform ); - projector.Scaled(true); - // If the index was found and is unique, the point is projected using the HLR Projector Algorithm - gp_Pnt2d prjPnt; - projector.Project(BRep_Tool::Pnt(refVert), prjPnt); - TechDrawGeometry::Vertex *myVert = new Vertex(prjPnt.X(), prjPnt.Y()); - return myVert; + if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { + Circle *circle = new Circle(edge); + //circle->extractType = extractionType; + result = circle; + } else { + AOC *aoc = new AOC(edge); + //aoc->extractType = extractionType; + result = aoc; + } + } break; + case GeomAbs_Ellipse: { + double f = adapt.FirstParameter(); + double l = adapt.LastParameter(); + gp_Pnt s = adapt.Value(f); + gp_Pnt e = adapt.Value(l); + if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { + Ellipse *ellipse = new Ellipse(edge); + //ellipse->extractType = extractionType; + result = ellipse; + } else { + AOE *aoe = new AOE(edge); + //aoe->extractType = extractionType; + result = aoe; + } + } break; + case GeomAbs_BSplineCurve: { + BSpline *bspline = 0; + Generic* gen = NULL; + try { + bspline = new BSpline(edge); + //bspline->extractType = extractionType; + if (bspline->isLine()) { + gen = new Generic(edge); + //gen->extractType = extractionType; + result = gen; + delete bspline; + } else { + result = bspline; + } + break; + } + catch (Standard_Failure) { + delete bspline; + delete gen; + bspline = 0; + // Move onto generating a primitive + } + } + default: { + Generic *primitive = new Generic(edge); + //primitive->extractType = extractionType; + result = primitive; + } break; + } + return result; } -//only used by DrawViewSection so far -void GeometryObject::projectSurfaces(const TopoDS_Shape &face, - const TopoDS_Shape &support, - const Base::Vector3d &direction, - const Base::Vector3d &xaxis, - std::vector &projFaces) const +//!find the 3D edges & vertices that correspond to 2D edges & vertices +void GeometryObject::update3DRefs() { - if(face.IsNull()) - throw Base::Exception("Projected shape is null"); - - gp_Pnt supportCentre = findCentroid(support, direction, xaxis); - - // TODO: We used to invert Y twice here, make sure that wasn't intentional - gp_Trsf mat; - mat.SetMirror(gp_Ax2(supportCentre, gp_Dir(0, 1, 0))); - gp_Trsf matScale; - matScale.SetScale(supportCentre, Scale); - mat.Multiply(matScale); - - BRepBuilderAPI_Transform mkTrfScale(face, mat); - - gp_Ax2 transform; - transform = gp_Ax2(supportCentre, - gp_Dir(direction.x, direction.y, direction.z), - gp_Dir(xaxis.x, xaxis.y, xaxis.z)); - - HLRBRep_Algo *brep_hlr = new HLRBRep_Algo(); - brep_hlr->Add(mkTrfScale.Shape()); - - HLRAlgo_Projector projector( transform ); - brep_hlr->Projector(projector); - brep_hlr->Update(); - brep_hlr->Hide(); - - Base::Console().Log("GeometryObject::projectSurfaces - projecting face\n"); - - // Extract Faces - std::vector projFaceRefs; - - extractFaces(brep_hlr, mkTrfScale.Shape(), true, WithSmooth, projFaces, projFaceRefs); - delete brep_hlr; } +gp_Pnt GeometryObject::findCentroid(const TopoDS_Shape &shape, + const Base::Vector3d &direction, + const Base::Vector3d &xAxis) const +{ + gp_Ax2 viewAxis; + viewAxis = gp_Ax2(gp_Pnt(0, 0, 0), + gp_Dir(direction.x, -direction.y, direction.z), + gp_Dir(xAxis.x, -xAxis.y, xAxis.z)); // Y invert warning! + + gp_Trsf tempTransform; + tempTransform.SetTransformation(viewAxis); + BRepBuilderAPI_Transform builder(shape, tempTransform); + + Bnd_Box tBounds; + BRepBndLib::Add(builder.Shape(), tBounds); + + tBounds.SetGap(0.0); + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); + + Standard_Real x = (xMin + xMax) / 2.0, + y = (yMin + yMax) / 2.0, + z = (zMin + zMax) / 2.0; + + // Get centroid back into object space + tempTransform.Inverted().Transforms(x, y, z); + + return gp_Pnt(x, y, z); +} + + +/////////////// bbox routines + Base::BoundBox3d GeometryObject::boundingBoxOfBspline(const BSpline *spline) const { Base::BoundBox3d bb; @@ -579,7 +720,96 @@ Base::BoundBox3d GeometryObject::calcBoundingBox() const return bbox; } -//! only ever called from fvp::getCompleteEdge +////////////////// Project TopoDS_xxxxx routines + +//! only ever called from FVP::getVertex which is never used, so obs? +TechDrawGeometry::Vertex * GeometryObject::projectVertex(const TopoDS_Shape &vert, + const TopoDS_Shape &support, + const Base::Vector3d &direction, + const Base::Vector3d &projXAxis) const +{ + if(vert.IsNull()) + throw Base::Exception("Projected vertex is null"); + TechDrawGeometry::Vertex* result = NULL; + return result; +#if 0 + gp_Pnt supportCentre = findCentroid(support, direction, projXAxis); + + // mirror+scale vert around centre of support + gp_Trsf mat; + mat.SetMirror(gp_Ax2(supportCentre, gp_Dir(0, 1, 0))); + gp_Trsf matScale; + matScale.SetScale(supportCentre, Scale); + mat.Multiply(matScale); + + //TODO: See if it makes sense to use gp_Trsf::Transforms() instead + BRepBuilderAPI_Transform mkTrfScale(vert, mat); + const TopoDS_Vertex &refVert = TopoDS::Vertex(mkTrfScale.Shape()); + + gp_Ax2 transform; + transform = gp_Ax2(supportCentre, + gp_Dir(direction.x, direction.y, direction.z), + gp_Dir(projXAxis.x, projXAxis.y, projXAxis.z)); + + HLRAlgo_Projector projector = HLRAlgo_Projector( transform ); + projector.Scaled(true); + // If the index was found and is unique, the point is projected using the HLR Projector Algorithm //wf: what index? + gp_Pnt2d prjPnt; + projector.Project(BRep_Tool::Pnt(refVert), prjPnt); + TechDrawGeometry::Vertex *myVert = new Vertex(prjPnt.X(), prjPnt.Y()); + return myVert; +#endif +} + +//!only used by DrawViewSection, but code is #if 0, so obs? +//don't need anything projected. DVS already has Compound of section faces. just need to turn those into +// BaseGeom::Face with tag for shading? like addGeomFromCompound without verts +void GeometryObject::projectSurfaces(const TopoDS_Shape &face, + const TopoDS_Shape &support, + const Base::Vector3d &direction, + const Base::Vector3d &xaxis, + std::vector &projFaces) const +{ + if(face.IsNull()) { + throw Base::Exception("Projected shape is null"); + return; + } +#if 0 + gp_Pnt supportCentre = findCentroid(support, direction, xaxis); + + // TODO: We used to invert Y twice here, make sure that wasn't intentional + gp_Trsf mat; + mat.SetMirror(gp_Ax2(supportCentre, gp_Dir(0, 1, 0))); + gp_Trsf matScale; + matScale.SetScale(supportCentre, Scale); + mat.Multiply(matScale); + + BRepBuilderAPI_Transform mkTrfScale(face, mat); + + gp_Ax2 transform; + transform = gp_Ax2(supportCentre, + gp_Dir(direction.x, direction.y, direction.z), + gp_Dir(xaxis.x, xaxis.y, xaxis.z)); + + HLRBRep_Algo *brep_hlr = new HLRBRep_Algo(); + brep_hlr->Add(mkTrfScale.Shape()); + + HLRAlgo_Projector projector( transform ); + brep_hlr->Projector(projector); + brep_hlr->Update(); + brep_hlr->Hide(); + + Base::Console().Log("GeometryObject::projectSurfaces - projecting face\n"); + + // Extract Faces + std::vector projFaceRefs; + + extractFaces(brep_hlr, mkTrfScale.Shape(), true, WithSmooth, projFaces, projFaceRefs); + delete brep_hlr; +#endif +} + +//! only ever called from fvp::getCompleteEdge which is only ever called from CmdCreateDim for true dims. so obs? TechDrawGeometry::BaseGeom * GeometryObject::projectEdge(const TopoDS_Shape &edge, const TopoDS_Shape &support, const Base::Vector3d &direction, @@ -589,6 +819,9 @@ TechDrawGeometry::BaseGeom * GeometryObject::projectEdge(const TopoDS_Shape &edg throw Base::Exception("Projected edge is null"); // Invert y function using support to calculate bounding box + TechDrawGeometry::BaseGeom *result = 0; + return result; +#if 0 gp_Pnt supportCentre = findCentroid(support, direction, projXAxis); gp_Trsf mat; @@ -634,21 +867,22 @@ TechDrawGeometry::BaseGeom * GeometryObject::projectEdge(const TopoDS_Shape &edg curve.Projector(&projector); TechDrawGeometry::BaseGeom *result = 0; + TopoDS_Edge e = BRepBuilderAPI_MakeEdge(curve.Curve()); switch(HLRBRep_BCurveTool::GetType(curve.Curve())) { case GeomAbs_Line: { - TechDrawGeometry::Generic *line = new TechDrawGeometry::Generic(); + TechDrawGeometry::Generic *line = new TechDrawGeometry::Generic(e,ecTrue,true); - gp_Pnt2d pnt1 = curve.Value(curve.FirstParameter()); - gp_Pnt2d pnt2 = curve.Value(curve.LastParameter()); +// gp_Pnt2d pnt1 = curve.Value(curve.FirstParameter()); +// gp_Pnt2d pnt2 = curve.Value(curve.LastParameter()); - line->points.push_back(Base::Vector2D(pnt1.X(), pnt1.Y())); - line->points.push_back(Base::Vector2D(pnt2.X(), pnt2.Y())); +// line->points.push_back(Base::Vector2D(pnt1.X(), pnt1.Y())); +// line->points.push_back(Base::Vector2D(pnt2.X(), pnt2.Y())); result = line; }break; case GeomAbs_Circle: { - TechDrawGeometry::Circle *circle = new TechDrawGeometry::Circle(); + TechDrawGeometry::Circle *circle = new TechDrawGeometry::Circle(e,ecTrue,true)); gp_Circ2d prjCirc = curve.Circle(); double f = curve.FirstParameter(); @@ -661,7 +895,7 @@ TechDrawGeometry::BaseGeom * GeometryObject::projectEdge(const TopoDS_Shape &edg circle->center = Base::Vector2D(prjCirc.Location().X(), prjCirc.Location().Y()); result = circle; } else { - AOC *aoc = new AOC(); + AOC *aoc = new AOC(curve.Curve()); aoc->radius = prjCirc.Radius(); aoc->center = Base::Vector2D(prjCirc.Location().X(), prjCirc.Location().Y()); double ax = s.X() - aoc->center.fX; @@ -712,732 +946,10 @@ TechDrawGeometry::BaseGeom * GeometryObject::projectEdge(const TopoDS_Shape &edg return result; } -} - -/* TODO: Clean this up when faces are actually working properly... -void debugEdge(const TopoDS_Edge &e) -{ - gp_Pnt p0 = BRep_Tool::Pnt(TopExp::FirstVertex(e)); - gp_Pnt p1 = BRep_Tool::Pnt(TopExp::LastVertex(e)); - qDebug()< &projFaces, - std::vector &faceRefs) const -{ -#if MOD_TECHDRAW_HANDLE_FACES - if(!myAlgo) - return; - - Handle_HLRBRep_Data DS = myAlgo->DataStructure(); - if (DS.IsNull()) { - Base::Console().Log("TechDraw::GeometryObject::extractFaces - DS is Null\n"); - return; - } - - DS->Projector().Scaled(true); - - int f1 = 1; - int f2 = DS->NbFaces(); - - /* This block seems to set f1 and f2 to indices using a HLRBRep_ShapeBounds - * object based that's based on myAlgo, but DS is also based on myAlgo too, - * so I don't think this is required. IR - if (!S.IsNull()) { - int e1 = 1; - int e2 = DS->NbEdges(); - - Standard_Integer v1,v2; - Standard_Integer index = myAlgo->Index(S); - if(index == 0) { - Base::Console().Log("TechDraw::GeometryObject::extractFaces - myAlgo->Index(S) == 0\n"); - return; - } - - myAlgo->ShapeBounds(index).Bounds(v1, v2, e1, e2, f1, f2); - } */ - - TopTools_IndexedMapOfShape anfIndices; - TopTools_IndexedMapOfShape& Faces = DS->FaceMap(); - TopExp::MapShapes(S, TopAbs_FACE, anfIndices); - - BRep_Builder B; - - /* ----------------- Extract Faces ------------------ */ - for (int iface = f1; iface <= f2; iface++) { - // Why oh why does Hiding() == true mean that a face is visible... - if (! DS->FDataArray().ChangeValue(iface).Hiding()) { - continue; - } - - TopoDS_Shape face; - B.MakeCompound(TopoDS::Compound(face)); - - // Generate a set of new wires based on face - // TODO: Do these end up with input face's geometry as a base? - drawFace(visible, iface, DS, face); - std::vector possibleFaceWires; - createWire(face, possibleFaceWires); - - TechDrawGeometry::Face *myFace = NULL; - - // Process each wire - if we can make at least one face with it, then - // send it down the road toward rendering - for (std::vector::iterator wireIt = possibleFaceWires.begin(); - wireIt != possibleFaceWires.end(); ++wireIt) { - - // Try making a face out of the wire, before doing anything else with it - BRepBuilderAPI_MakeFace testFace(*wireIt); - if (testFace.IsDone()) { - if (myFace == NULL) { - myFace = new TechDrawGeometry::Face(); - } - TechDrawGeometry::Wire *genWire = new TechDrawGeometry::Wire(); - - // See createWire regarding BRepTools_WireExplorer vs TopExp_Explorer - BRepTools_WireExplorer explr(*wireIt); - while (explr.More()) { - BRep_Builder builder; - TopoDS_Compound comp; - builder.MakeCompound(comp); - builder.Add(comp, explr.Current()); - - calculateGeometry(comp, Plain, genWire->geoms); - explr.Next(); - } - myFace->wires.push_back(genWire); - } - } - - if (myFace != NULL) { - projFaces.push_back(myFace); - } - - // I'm pretty sure this doesn't do what it's intended to do. IR - int idxFace; - for (int i = 1; i <= anfIndices.Extent(); i++) { - idxFace = Faces.FindIndex(anfIndices(iface)); - if (idxFace != 0) { - break; - } - } - - if(idxFace == 0) - idxFace = -1; // If Face not found - select hidden - - // Push the found face index onto references stack - faceRefs.push_back(idxFace); - } - - DS->Projector().Scaled(false); -#endif //#if MOD_TECHDRAW_HANDLE_FACES -} - -bool GeometryObject::shouldDraw(const bool inFace, const int typ, HLRBRep_EdgeData& ed) -{ - bool todraw = false; - if(inFace) - todraw = true; - else if (typ == 3) - todraw = ed.Rg1Line() && !ed.RgNLine(); //smooth + !contour? - else if (typ == 4) - todraw = ed.RgNLine(); //contour? - else - todraw =!ed.Rg1Line(); //!smooth? - - return todraw; -} - -void GeometryObject::extractVerts(HLRBRep_Algo *myAlgo, const TopoDS_Shape &S, HLRBRep_EdgeData& ed, int ie, ExtractionType extractionType) -{ - if(!myAlgo) - return; - - Handle_HLRBRep_Data DS = myAlgo->DataStructure(); - - if (DS.IsNull()) - return; - - DS->Projector().Scaled(true); - - TopTools_IndexedMapOfShape anIndices; - TopTools_IndexedMapOfShape anvIndices; - - TopExp::MapShapes(S, TopAbs_EDGE, anIndices); - TopExp::MapShapes(S, TopAbs_VERTEX, anvIndices); - - // Load the edge - if(ie < 0) { - - } else { - TopoDS_Shape shape = anIndices.FindKey(ie); - TopoDS_Edge edge = TopoDS::Edge(shape); - - // Gather a list of points associated with this curve - std::list edgePoints; - - TopExp_Explorer xp; - xp.Init(edge,TopAbs_VERTEX); - while(xp.More()) { - edgePoints.push_back(xp.Current()); - xp.Next(); - } - for(std::list::const_iterator it = edgePoints.begin(); it != edgePoints.end(); ++it) { - - // Should share topological data structure so can reference - int iv = anvIndices.FindIndex(*it); // Index of the found vertex - - if(iv < 0) - continue; - - // Check if vertex has already been addded - std::vector::iterator vert; - vert = std::find(vertexReferences.begin(), vertexReferences.end(), iv); - - if(vert == vertexReferences.end()) { - - // If the index wasnt found and is unique, the point is projected using the HLR Projector Algorithm - gp_Pnt2d prjPnt; - DS->Projector().Project(BRep_Tool::Pnt(TopoDS::Vertex(*it)), prjPnt); - - // Check if this point lies on a visible section of the projected curve - double sta,end; - float tolsta,tolend; - - // There will be multiple edges that form the total edge so collect these - BRep_Builder B; - TopoDS_Compound comp; - B.MakeCompound(comp); - - TopoDS_Edge E; - HLRAlgo_EdgeIterator It; - - for(It.InitVisible(ed.Status()); It.MoreVisible(); It.NextVisible()) { - It.Visible(sta,tolsta,end,tolend); - - E = HLRBRep::MakeEdge(ed.Geometry(),sta,end); - if (!E.IsNull()) { - B.Add(comp,E); - } - } - - bool vertexVisible = false; - TopExp_Explorer exp; - exp.Init(comp,TopAbs_VERTEX); - while(exp.More()) { - - gp_Pnt pnt = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current())); - gp_Pnt2d edgePnt(pnt.X(), pnt.Y()); - if(edgePnt.SquareDistance(prjPnt) < Precision::Confusion()) { - vertexVisible = true; - break; - } - exp.Next(); - } - - if(vertexVisible) { - Vertex *myVert = new Vertex(prjPnt.X(), prjPnt.Y()); - vertexGeom.push_back(myVert); - vertexReferences.push_back(iv); - } - } - } - } -} - -void GeometryObject::extractEdges(HLRBRep_Algo *myAlgo, const TopoDS_Shape &S, int type, bool visible, ExtractionType extractionType) -{ - if (!myAlgo) - return; - Handle_HLRBRep_Data DS = myAlgo->DataStructure(); - - if (DS.IsNull()) - return; - - DS->Projector().Scaled(true); - - int e1 = 1; - int e2 = DS->NbEdges(); - int f1 = 1; - int f2 = DS->NbFaces(); - - if (!S.IsNull()) { - int v1,v2; - int index = myAlgo->Index(S); - if(index == 0) { - Base::Console().Log("TechDraw::GeometryObject::extractEdges - myAlgo->Index(S) == 0\n"); - return; - } - myAlgo->ShapeBounds(index).Bounds(v1,v2,e1,e2,f1,f2); - } - - HLRBRep_EdgeData* ed = &(DS->EDataArray().ChangeValue(e1 - 1)); - - // Get map of edges and faces from projected geometry - TopTools_IndexedMapOfShape& Edges = DS->EdgeMap(); - TopTools_IndexedMapOfShape anIndices; - - TopExp::MapShapes(S, TopAbs_EDGE, anIndices); - - for (int j = e1; j <= e2; j++) { - ed++; - if (ed->Selected() && !ed->Vertical()) { - ed->Used(false); - ed->HideCount(0); - - } else { - ed->Used(true); - } - } - - BRep_Builder B; - - std::list notFound; - /* ----------------- Extract Edges ------------------ */ - for (int i = 1; i <= anIndices.Extent(); i++) { - int ie = Edges.FindIndex(anIndices(i)); - if (ie != 0) { - - HLRBRep_EdgeData& ed = DS->EDataArray().ChangeValue(ie); - if(!ed.Used()) { - if(true) { - - TopoDS_Shape result; - B.MakeCompound(TopoDS::Compound(result)); - - drawEdge(ed, result, visible); - - // Extract and Project Vertices for current Edge - extractVerts(myAlgo, S, ed, i, extractionType); - - int edgesAdded = calculateGeometry(result, extractionType, edgeGeom); - - // Push the edge references - while(edgesAdded--) - edgeReferences.push_back(i); - } - - ed.Used(Standard_True); - } - } else { - notFound.push_back(i); - } - } - - - - // Add any remaining edges that couldn't be found - int edgeIdx = -1; // Negative index for edge references - for (int ie = e1; ie <= e2; ie++) { - // Co - HLRBRep_EdgeData& ed = DS->EDataArray().ChangeValue(ie); - if (!ed.Used()) { - if(shouldDraw(false, type, ed)) { - const TopoDS_Shape &shp = Edges.FindKey(ie); - - //Compares original shape to see if match - if(!shp.IsNull()) { - const TopoDS_Edge& edge = TopoDS::Edge(shp); - BRepAdaptor_Curve adapt1(edge); - for (std::list::iterator it= notFound.begin(); it!= notFound.end(); ++it){ - BRepAdaptor_Curve adapt2(TopoDS::Edge(anIndices(*it))); - if(isSameCurve(adapt1, adapt2)) { - edgeIdx = *it; -// notFound.erase(it); - break; - } - } - } - - TopoDS_Shape result; - B.MakeCompound(TopoDS::Compound(result)); - - drawEdge(ed, result, visible); - int edgesAdded = calculateGeometry(result, extractionType, edgeGeom); - - // Push the edge references - while(edgesAdded--) - edgeReferences.push_back(edgeIdx); - } - ed.Used(true); - } - } - - DS->Projector().Scaled(false); -} - -/** - * Note projected edges are broken up so start and end parameters differ. - */ -bool GeometryObject::isSameCurve(const BRepAdaptor_Curve &c1, const BRepAdaptor_Curve &c2) const -{ - - - if(c1.GetType() != c2.GetType()) - return false; -#if 0 - const gp_Pnt& p1S = c1.Value(c1.FirstParameter()); - const gp_Pnt& p1E = c1.Value(c1.LastParameter()); - - const gp_Pnt& p2S = c2.Value(c2.FirstParameter()); - const gp_Pnt& p2E = c2.Value(c2.LastParameter()); - - bool state = (p1S.IsEqual(p2S, Precision::Confusion()) && p1E.IsEqual(p2E, Precision::Confusion())); - - if( s || - (p1S.IsEqual(p2E, Precision::Confusion()) && p1E.IsEqual(p2S, Precision::Confusion())) ){ - switch(c1.GetType()) { - case GeomAbs_Circle: { - - gp_Circ circ1 = c1.Circle(); - gp_Circ circ2 = c2.Circle(); - - const gp_Pnt& p = circ1.Location(); - const gp_Pnt& p2 = circ2.Location(); - - double radius1 = circ1.Radius(); - double radius2 = circ2.Radius(); - double f1 = c1.FirstParameter(); - double f2 = c2.FirstParameter(); - double l1 = c1.LastParameter(); - double l2 = c2.LastParameter(); - c1.Curve().Curve()-> - if( p.IsEqual(p2,Precision::Confusion()) && - radius2 - radius1 < Precision::Confusion()) { - return true; - } - } break; - default: break; - } - } #endif - return false; } -//only used by extractFaces -void GeometryObject::createWire(const TopoDS_Shape &input, - std::vector &wiresOut) const -{ - //input is a compound of edges? there is edgesToWire logic in Part? - if (input.IsNull()) { - Base::Console().Log("TechDraw::GeometryObject::createWire input is NULL\n"); - return; // There is no OpenCascade Geometry to be calculated - } - - std::list edgeList; - - // make a list of all the edges in the input shape - TopExp_Explorer edges(input, TopAbs_EDGE); - while (edges.More()) { - edgeList.push_back(TopoDS::Edge(edges.Current())); - edges.Next(); - } - // Combine connected edges into wires. - - // BRepBuilderAPI_MakeWire has an annoying behaviour where the only [sane] - // way to test whether an edge connects to a wire is to attempt adding - // the edge. But, if the last added edge was not connected to the wire, - // BRepBuilderAPI_MakeWire::Wire() will throw an exception. So, we need - // to hang on to the last successfully added edge to "reset" scapegoat. - // - // ...and why do we need scapegoat? Because the resetting adds a duplicate - // edge (which can be problematic down the road), but it's not easy to - // remove the edge from the BRepBuilderAPI_MakeWire. - bool lastAddFailed; - TopoDS_Edge lastGoodAdd; - - while (edgeList.size() > 0) { - // add and erase first edge - BRepBuilderAPI_MakeWire scapegoat, mkWire; - scapegoat.Add(edgeList.front()); - mkWire.Add(edgeList.front()); - lastAddFailed = false; - lastGoodAdd = edgeList.front(); - edgeList.pop_front(); - - // try to connect remaining edges to the wire, the wire is complete if no more egdes are connectible - bool found; - do { - found = false; - for (std::list::iterator pE = edgeList.begin(); pE != edgeList.end(); ++pE) { - // Try adding edge - this doesn't necessarily add it - scapegoat.Add(*pE); - if (scapegoat.Error() != BRepBuilderAPI_DisconnectedWire) { - mkWire.Add(*pE); - // Edge added! Remember it, so we can reset scapegoat - lastAddFailed = false; - lastGoodAdd = *pE; - - // ...remove it from edgeList, - edgeList.erase(pE); - - // ...and start searching for the next edge - found = true; - break; //exit for loop - } else { - lastAddFailed = true; - } - } - } while (found); - - // See note above re: BRepBuilderAPI_MakeWire annoying behaviour - if (lastAddFailed) { - scapegoat.Add(lastGoodAdd); - } - - if (scapegoat.Error() == BRepBuilderAPI_WireDone) { - // BRepTools_WireExplorer finds 1st n connected edges, while - // TopExp_Explorer finds all edges. Since we built mkWire using - // TopExp_Explorer, and want to run BRepTools_WireExplorer over - // it, we need to reorder the wire. - ShapeFix_Wire fix; - fix.Load(mkWire.Wire()); - fix.FixReorder(); - fix.Perform(); - - wiresOut.push_back(fix.Wire()); - } else if(scapegoat.Error() == BRepBuilderAPI_DisconnectedWire) { - Standard_Failure::Raise("Fatal error occurred in GeometryObject::createWire()"); - } - } -} - -gp_Pnt GeometryObject::findCentroid(const TopoDS_Shape &shape, - const Base::Vector3d &direction, - const Base::Vector3d &xAxis) const -{ - gp_Ax2 viewAxis; - viewAxis = gp_Ax2(gp_Pnt(0, 0, 0), - gp_Dir(direction.x, -direction.y, direction.z), - gp_Dir(xAxis.x, -xAxis.y, xAxis.z)); // Y invert warning! - - gp_Trsf tempTransform; - tempTransform.SetTransformation(viewAxis); - BRepBuilderAPI_Transform builder(shape, tempTransform); - - Bnd_Box tBounds; - BRepBndLib::Add(builder.Shape(), tBounds); - - tBounds.SetGap(0.0); - Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; - tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - - Standard_Real x = (xMin + xMax) / 2.0, - y = (yMin + yMax) / 2.0, - z = (zMin + zMax) / 2.0; - - // Get centroid back into object space - tempTransform.Inverted().Transforms(x, y, z); - - return gp_Pnt(x, y, z); -} - -void GeometryObject::extractGeometry(const TopoDS_Shape &input, - const Base::Vector3d &direction, - bool extractHidden, - const Base::Vector3d &xAxis) -{ - // Clear previous Geometry and References that may have been stored - clear(); - - ///TODO: Consider whether it would be possible/beneficial to cache some of this effort (eg don't do scale in OpenCASCADE land) IR - TopoDS_Shape transShape; - HLRBRep_Algo *brep_hlr = NULL; - gp_Pnt inputCentre; - try { - inputCentre = findCentroid(input, direction, xAxis); - } - catch (...) { - Base::Console().Log("GeometryObject::extractGeometry - findCentroid failed.\n"); - return; - } - try { - // Make tempTransform scale the object around it's centre point and - // mirror about the Y axis - gp_Trsf tempTransform; - tempTransform.SetScale(inputCentre, Scale); - gp_Trsf mirrorTransform; - mirrorTransform.SetMirror( gp_Ax2(inputCentre, gp_Dir(0, 1, 0)) ); - tempTransform.Multiply(mirrorTransform); - - // Apply that transform to the shape. This should preserve the centre. - BRepBuilderAPI_Transform mkTrf(input, tempTransform); - transShape = mkTrf.Shape(); - - brep_hlr = new HLRBRep_Algo(); - brep_hlr->Add(transShape); - - // Project the shape into view space with the object's centroid - // at the origin. - gp_Ax2 viewAxis; - viewAxis = gp_Ax2(inputCentre, - gp_Dir(direction.x, direction.y, direction.z), - gp_Dir(xAxis.x, xAxis.y, xAxis.z)); - HLRAlgo_Projector projector( viewAxis ); - brep_hlr->Projector(projector); - brep_hlr->Update(); - brep_hlr->Hide(); - - } - catch (...) { - Standard_Failure::Raise("GeometryObject::extractGeometry - error occurred while projecting shape"); - } - - // extracting the result sets: - - //TODO: What is this? IR - // need HLRBRep_HLRToShape aHLRToShape(shapes); - // then TopoDS_Shape V = shapes.VCompound(); //V is a compound of edges - // V = shapes.VCompound ();// hard edge visibly - real edges in original shape - // V1 = shapes.Rg1LineVCompound();// Smoth edges visibly - "transition edges between two surfaces" - // VN = shapes.RgNLineVCompound();// contour edges visibly - "sewn edges"? - // VO = shapes.OutLineVCompound();// contours apparents visibly - ?edge in projection but not in original shape? - // VI = shapes.IsoLineVCompound();// isoparamtriques visibly - ?constant u,v sort of like lat/long - // H = shapes.HCompound ();// hard edge invisibly - // H1 = shapes.Rg1LineHCompound();// Smoth edges invisibly - // HN = shapes.RgNLineHCompound();// contour edges invisibly - // HO = shapes.OutLineHCompound();// contours apparents invisibly - // HI = shapes.IsoLineHCompound();// isoparamtriques invisibly - - // Extract Hidden Edges - if(extractHidden) - extractEdges(brep_hlr, transShape, 5, false, WithHidden);// Hard Edge -// calculateGeometry(extractCompound(brep_hlr, invertShape, 2, false), WithHidden); // Outline -// calculateGeometry(extractCompound(brep_hlr, invertShape, 3, false), (ExtractionType)(WithSmooth | WithHidden)); // Smooth - - // Extract Visible Edges - extractEdges(brep_hlr, transShape, 5, true, WithSmooth); // Hard Edge - - //get endpoints of visible projected edges and add to vertexGeom with ref = -1 - //this could get slow for big models? - const std::vector &edgeGeom = getEdgeGeometry(); - std::vector::const_iterator iEdge = edgeGeom.begin(); - for (; iEdge != edgeGeom.end(); iEdge++) { - if ((*iEdge)->extractType == TechDrawGeometry::WithHidden) { //only use visible edges - continue; - } - std::vector ends = (*iEdge)->findEndPoints(); - if (!ends.empty()) { - if (!findVertex(ends[0])) { - Vertex* v0 = new Vertex(ends[0]); - v0->extractType = TechDrawGeometry::Plain; - vertexGeom.push_back(v0); - vertexReferences.push_back(-1); - } - if (!findVertex(ends[1])) { - Vertex* v1 = new Vertex(ends[1]); - v1->extractType = TechDrawGeometry::Plain; - vertexGeom.push_back(v1); - vertexReferences.push_back(-1); - } - } - } - -// calculateGeometry(extractCompound(brep_hlr, invertShape, 2, true), Plain); // Outline -// calculateGeometry(extractCompound(brep_hlr, invertShape, 3, true), WithSmooth); // Smooth Edge - - // Extract Faces - //algorithm,shape,visible/hidden,smooth edges(show flat/curve transition,facewires,index of face in shape? - extractFaces(brep_hlr, transShape, true, WithSmooth, faceGeom, faceReferences); - - // House Keeping - delete brep_hlr; -} - -//translate all the edges in "input" into BaseGeoms -int GeometryObject::calculateGeometry(const TopoDS_Shape &input, - const ExtractionType extractionType, - std::vector &geom) const -{ - if(input.IsNull()) { - Base::Console().Log("TechDraw::GeometryObject::calculateGeometry input is NULL\n"); - return 0; // There is no OpenCascade Geometry to be calculated - } - - // build a mesh to explore the shape - //BRepMesh::Mesh(input, Tolerance); //OCC has removed BRepMesh::Mesh() as of v6.8.0.oce-0.17-dev - BRepMesh_IncrementalMesh(input, Tolerance); //making a mesh turns edges into multilines? - - int geomsAdded = 0; - - // Explore all edges of input and calculate base geometry representation - TopExp_Explorer edges(input, TopAbs_EDGE); - for (int i = 1 ; edges.More(); edges.Next(),i++) { - const TopoDS_Edge& edge = TopoDS::Edge(edges.Current()); - BRepAdaptor_Curve adapt(edge); - - switch(adapt.GetType()) { - case GeomAbs_Circle: { - double f = adapt.FirstParameter(); - double l = adapt.LastParameter(); - gp_Pnt s = adapt.Value(f); - gp_Pnt e = adapt.Value(l); - - if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { - Circle *circle = new Circle(adapt); - circle->extractType = extractionType; - geom.push_back(circle); - } else { - AOC *aoc = new AOC(adapt); - aoc->extractType = extractionType; - geom.push_back(aoc); - } - } break; - case GeomAbs_Ellipse: { - double f = adapt.FirstParameter(); - double l = adapt.LastParameter(); - gp_Pnt s = adapt.Value(f); - gp_Pnt e = adapt.Value(l); - if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { - Ellipse *ellipse = new Ellipse(adapt); - ellipse->extractType = extractionType; - geom.push_back(ellipse); - } else { - AOE *aoe = new AOE(adapt); - aoe->extractType = extractionType; - geom.push_back(aoe); - } - } break; - case GeomAbs_BSplineCurve: { - BSpline *bspline = 0; - Generic* gen = NULL; - try { - bspline = new BSpline(adapt); - bspline->extractType = extractionType; - if (bspline->isLine()) { - Base::Vector2D start,end; - start = bspline->segments.front().pnts[0]; - end = bspline->segments.back().pnts[1]; - gen = new Generic(start,end); - gen->extractType = extractionType; - geom.push_back(gen); - delete bspline; - } else { - geom.push_back(bspline); - } - break; - } - catch (Standard_Failure) { - delete bspline; - delete gen; - bspline = 0; - // Move onto generating a primitive - } - } - default: { - Generic *primitive = new Generic(adapt); - primitive->extractType = extractionType; - geom.push_back(primitive); - } break; - } - geomsAdded++; - } - return geomsAdded; -} +///////////////////////////////////////////////////// //! does this GeometryObject already have this vertex bool GeometryObject::findVertex(Base::Vector2D v) @@ -1453,3 +965,45 @@ bool GeometryObject::findVertex(Base::Vector2D v) } return found; } + +void _dumpEdgeData(char* label, int i, HLRBRep_EdgeData& ed) +{ + Base::Console().Message("Dump of EdgeData for %s Edge: %d\n",label,i); + Base::Console().Message("Selected:%s Smooth(Rg1):%s Sewn(RgN):%s OutSta:%s OutEnd:%s\n", + _printBool(ed.Selected()),_printBool(ed.Rg1Line()),_printBool(ed.RgNLine()),_printBool(ed.OutLVSta()),_printBool(ed.OutLVEnd())); + Base::Console().Message("Vertical:%s Simple:%s Used:%s HideCount:%d\n", + _printBool(ed.Vertical()),_printBool(ed.Simple()),_printBool(ed.Used()),ed.HideCount()); +} + +/* TODO: Clean this up when faces are actually working properly... + +void debugEdge(const TopoDS_Edge &e) + +{ + + gp_Pnt p0 = BRep_Tool::Pnt(TopExp::FirstVertex(e)); + + gp_Pnt p1 = BRep_Tool::Pnt(TopExp::LastVertex(e)); + + qDebug()< #include #include @@ -36,13 +37,13 @@ class HLRBRep_Algo; class Handle_HLRBRep_Data; class HLRBRep_EdgeData; class TopoDS_Wire; +class HLRBRep_HLRToShape; namespace TechDrawGeometry { class BaseGeom; -/** Algo class for projecting shapes and creating SVG output of it - */ + class TechDrawExport GeometryObject { public: @@ -66,39 +67,29 @@ public: const std::vector & getEdgeRefs() const { return edgeReferences; }; const std::vector & getFaceRefs() const { return faceReferences; }; - TechDrawGeometry::BaseGeom * projectEdge(const TopoDS_Shape &edge, - const TopoDS_Shape &support, - const Base::Vector3d &direction, - const Base::Vector3d &projXAxis) const; - TechDrawGeometry::Vertex * projectVertex(const TopoDS_Shape &vert, - const TopoDS_Shape &support, - const Base::Vector3d &direction, - const Base::Vector3d &projXAxis) const; - void projectSurfaces(const TopoDS_Shape &face, const TopoDS_Shape &support, const Base::Vector3d &direction, const Base::Vector3d &xaxis, std::vector &result) const; + BaseGeom* projectEdge(const TopoDS_Shape &edge, + const TopoDS_Shape &support, + const Base::Vector3d &direction, + const Base::Vector3d &projXAxis) const; + Vertex* projectVertex(const TopoDS_Shape &vert, + const TopoDS_Shape &support, + const Base::Vector3d &direction, + const Base::Vector3d &projXAxis) const; - /// Process 3D shape to get 2D geometry - /*! - * Applies a projection to the input based on direction and vAxis, then - * calls extractEdges (which in turn calls extractVerts) and extractFaces - * to populate vectors used by getVertexRefs(), getEdgeRefs(), and - * getFaceRefs() - */ - void extractGeometry(const TopoDS_Shape &input,const Base::Vector3d &direction, bool extractHidden = false, const Base::Vector3d &vAxis = Base::Vector3d(0.,0.,0.)); + void initHLR(const TopoDS_Shape &input, + const Base::Vector3d &direction, + const Base::Vector3d &xAxis); + void extractGeometry(edgeClass category, bool visible); + BaseGeom* edgeToBase(TopoDS_Edge edge); + void update3DRefs(); protected: - bool shouldDraw(const bool inFace, const int typ,HLRBRep_EdgeData& ed); - bool isSameCurve(const BRepAdaptor_Curve &c1, const BRepAdaptor_Curve &c2) const; - - /// Reimplements HLRBRep Drawing Algorithms to satisfy Drawing Workbench requirements - void drawFace(const bool visible, const int iface, Handle_HLRBRep_Data & DS, TopoDS_Shape& Result) const; - - /// Add (visible) intervals of ed to Result as Edges - void drawEdge(HLRBRep_EdgeData& ed, TopoDS_Shape& Result, const bool visible) const; + void addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass category, bool visible); /// Helper for calcBoundingBox() /*! Note that the name of this function isn't totally accurate due to @@ -121,21 +112,6 @@ protected: */ bool isWithinArc(double theta, double first, double last, bool cw) const; - void extractVerts(HLRBRep_Algo *myAlgo, const TopoDS_Shape &S, HLRBRep_EdgeData& ed, int ie, ExtractionType extractionType); - void extractEdges(HLRBRep_Algo *myAlgo, const TopoDS_Shape &S, int type, bool visible, ExtractionType extractionType); - - void extractFaces(HLRBRep_Algo *myAlgo, - const TopoDS_Shape &S, - bool visible, - ExtractionType extractionType, - std::vector &projFaces, - std::vector &faceRefs) const; - - int calculateGeometry(const TopoDS_Shape &input, ExtractionType extractionType, std::vector &geoms) const; - - /// Accumulate edges from input and store them in wires - void createWire(const TopoDS_Shape &input, std::vector &wiresOut) const; - // Geometry std::vector edgeGeom; std::vector vertexGeom; @@ -148,7 +124,7 @@ protected: std::vector edgeReferences; std::vector faceReferences; - HLRBRep_Algo *brep_hlr; + Handle_HLRBRep_Algo brep_hlr; double Tolerance; double Scale; diff --git a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp index 171541cdc..47fcd0d99 100644 --- a/src/Mod/TechDraw/Gui/CommandCreateDims.cpp +++ b/src/Mod/TechDraw/Gui/CommandCreateDims.cpp @@ -111,11 +111,10 @@ void CmdTechDrawNewDimension::activated(int iMsg) std::vector objs; std::vector subs; - //TODO: do all these validations have to be accessible from Python? - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidSingleEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if (edgeType) { if (edgeType < isCircle) { @@ -187,12 +186,7 @@ void CmdTechDrawNewDimension::activated(int iMsg) dim = dynamic_cast(getDocument()->getObject(FeatName.c_str())); dim->References.setValues(objs, subs); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -240,11 +234,10 @@ void CmdTechDrawNewRadiusDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidSingleEdge(this,trueDimAllowed); - if (edgeType == isCircle) { + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if (edgeType == isCircle) { centerLine = true; objs.push_back(objFeat); subs.push_back(SubNames[0]); @@ -272,11 +265,7 @@ void CmdTechDrawNewRadiusDimension::activated(int iMsg) dim = dynamic_cast(getDocument()->getObject(FeatName.c_str())); dim->References.setValues(objs, subs); - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -325,11 +314,10 @@ void CmdTechDrawNewDiameterDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - - int edgeType = _isValidSingleEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if (edgeType == isCircle) { centerLine = true; objs.push_back(objFeat); @@ -358,12 +346,7 @@ void CmdTechDrawNewDiameterDimension::activated(int iMsg) dim = dynamic_cast(getDocument()->getObject(FeatName.c_str())); dim->References.setValues(objs, subs); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -413,10 +396,10 @@ void CmdTechDrawNewLengthDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidSingleEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if ((edgeType == isHorizontal) || (edgeType == isVertical) || (edgeType == isDiagonal)) { @@ -451,12 +434,7 @@ void CmdTechDrawNewLengthDimension::activated(int iMsg) doCommand(Doc, "App.activeDocument().%s.FormatSpec = '%%value%%'", FeatName.c_str()); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -505,10 +483,10 @@ void CmdTechDrawNewDistanceXDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidSingleEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if ((edgeType == isHorizontal) || (edgeType == isDiagonal)) { objs.push_back(objFeat); @@ -541,12 +519,7 @@ void CmdTechDrawNewDistanceXDimension::activated(int iMsg) doCommand(Doc, "App.activeDocument().%s.FormatSpec = '%%value%%'", FeatName.c_str()); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -596,10 +569,10 @@ void CmdTechDrawNewDistanceYDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidSingleEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if ((edgeType == isVertical) || (edgeType == isDiagonal)) { objs.push_back(objFeat); @@ -631,12 +604,7 @@ void CmdTechDrawNewDistanceYDimension::activated(int iMsg) doCommand(Doc, "App.activeDocument().%s.FormatSpec = '%%value%%'", FeatName.c_str()); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); @@ -685,10 +653,10 @@ void CmdTechDrawNewAngleDimension::activated(int iMsg) std::vector objs; std::vector subs; - //selected edge(s) must have valid reference to Source edge for True Dimension - //otherwise Dimension must be Projected - bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); - int edgeType = _isValidEdgeToEdge(this,trueDimAllowed); + //All Dimensions start as Projected + //bool trueDimAllowed = _isTrueAllowed(objFeat,SubNames); + //int edgeType = _isValidSingleEdge(this,trueDimAllowed); + int edgeType = _isValidSingleEdge(this,false); if (edgeType == isAngle) { objs.push_back(objFeat); objs.push_back(objFeat); @@ -711,12 +679,7 @@ void CmdTechDrawNewAngleDimension::activated(int iMsg) dim = dynamic_cast(getDocument()->getObject(FeatName.c_str())); dim->References.setValues(objs, subs); - // make a True dimension if you can, Projected otherwise - if (trueDimAllowed) { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'True'",FeatName.c_str()); - } else { - doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); - } + doCommand(Doc,"App.activeDocument().%s.ProjectionType = 'Projected'",FeatName.c_str()); std::vector pages = getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); TechDraw::DrawPage *page = dynamic_cast(pages.front()); diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index 717e847ce..b828905be 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -485,6 +485,7 @@ void MDIViewPage::selectionChanged() static_cast (Gui::Selection().addSelection(viewObj->getDocument()->getName(), viewObj->getNameInDocument(), ss.str().c_str())); + //Base::Console().Message("TRACE - MDIVP::selectionChanged - selection: %s\n",ss.str().c_str()); } QGIVertex *vert = dynamic_cast(*it); diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index e9fd69252..6f65623e4 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -48,9 +48,11 @@ #include "../App/DrawUtil.h" #include "../App/DrawViewPart.h" #include "../App/DrawHatch.h" +#include "../App/Geometry.h" #include "QGIViewPart.h" using namespace TechDrawGui; +using namespace TechDrawGeometry; void _dumpPath(const char* text,QPainterPath path); @@ -384,33 +386,39 @@ void QGIViewPart::drawViewPart() // Draw Edges const std::vector &geoms = viewPart->getEdgeGeometry(); const std::vector &refs = viewPart->getEdgeReferences(); - std::vector::const_iterator it = geoms.begin(); + std::vector::const_iterator itEdge = geoms.begin(); QGIEdge* item; - for(int i = 0 ; it != geoms.end(); ++it, i++) { - //TODO: investigate if an Edge can be both Hidden and Smooth??? - if(((*it)->extractType == TechDrawGeometry::Plain) || - (((*it)->extractType == TechDrawGeometry::WithHidden) && viewPart->ShowHiddenLines.getValue()) || - ((*it)->extractType == TechDrawGeometry::WithSmooth)) { -// (((*it)->extractType == TechDrawGeometry::WithSmooth) && part->ShowSmoothLines.getValue())) { - //item = new QGIEdge(refs.at(i)); + for(int i = 0 ; itEdge != geoms.end(); itEdge++, i++) { + bool showEdge = false; + if ((*itEdge)->visible) { + if (((*itEdge)->classOfEdge == ecHARD) || + ((*itEdge)->classOfEdge == ecOUTLINE) || + (((*itEdge)->classOfEdge == ecSMOOTH) && viewPart->ShowSmoothLines.getValue()) || + (((*itEdge)->classOfEdge == ecSEAM) && viewPart->ShowSeamLines.getValue())) { + showEdge = true; + } + } else { + if (viewPart->ShowHiddenLines.getValue()) { + showEdge = true; + } + } + if (showEdge) { item = new QGIEdge(i); item->setReference(refs.at(i)); addToGroup(item); //item is at scene(0,0), not group(0,0) item->setPos(0.0,0.0); item->setStrokeWidth(lineWidth); - if((*it)->extractType == TechDrawGeometry::WithHidden) { + if(!(*itEdge)->visible) { item->setStrokeWidth(lineWidthHid); item->setHiddenEdge(true); - } else if((*it)->extractType == TechDrawGeometry::WithSmooth) { - item->setSmoothEdge(true); } - item->setPath(drawPainterPath(*it)); + item->setPath(drawPainterPath(*itEdge)); item->setFlag(QGraphicsItem::ItemIsSelectable, true); item->setAcceptHoverEvents(true); //debug a path - //QPainterPath edgePath=drawPainterPath(*it); + //QPainterPath edgePath=drawPainterPath(*itEdge); //item->setPath(edgePath); //std::stringstream edgeId; //edgeId << "edge" << i; @@ -422,7 +430,6 @@ void QGIViewPart::drawViewPart() const std::vector &verts = viewPart->getVertexGeometry(); const std::vector &vertRefs = viewPart->getVertexReferences(); std::vector::const_iterator vert = verts.begin(); - for(int i = 0 ; vert != verts.end(); ++vert, i++) { QGIVertex *item = new QGIVertex(i); item->setReference(vertRefs.at(i)); diff --git a/src/Mod/TechDraw/Gui/QGIViewSection.cpp b/src/Mod/TechDraw/Gui/QGIViewSection.cpp index ece5c68cc..5edd3b983 100644 --- a/src/Mod/TechDraw/Gui/QGIViewSection.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewSection.cpp @@ -72,11 +72,11 @@ void QGIViewSection::drawSectionFace() //Base::Console().Log("drawing section face\n"); - // Get the section face from the feature - std::vector faceGeoms; - part->getSectionSurface(faceGeoms); - if (faceGeoms.empty()) { - Base::Console().Log("INFO - QGIViewSection::drawSectionFace - No Face available. Check Section plane.\n"); + // Get the section faces from the feature + std::vector sectionFaces; + //part->getSectionFaces(faceGeoms); + if (sectionFaces.empty()) { + Base::Console().Log("INFO - QGIViewSection::drawSectionFace - No sectionFaces available. Check Section plane.\n"); return; } @@ -124,7 +124,7 @@ void QGIViewSection::drawSectionFace() if(graphicsItem) { // Hide any edges that are hidden if option is set. - // if((*fit)->extractType == TechDrawGeometry::WithHidden && !part->ShowHiddenLines.getValue()) + // if(!(*fit)->visible && !part->ShowHiddenLines.getValue()) // graphicsItem->hide(); addToGroup(graphicsItem);