diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 3923fda857..70d441698a 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -105,7 +105,7 @@ SketchObject::SketchObject() ADD_PROPERTY_TYPE(ExternalGeometry,(0,0),"Sketch",(App::PropertyType)(App::Prop_None),"Sketch external geometry"); Geometry.setOrderRelevant(true); - + allowOtherBody = true; allowUnaligned = true; @@ -1657,7 +1657,7 @@ int SketchObject::fillet(int GeoId1, int GeoId2, Base::Console().Log("offset int(%f,%f,0)\n",inter.first.x,inter.first.y); } #endif - + int res = selectintersection(offsetintersectionpoints,filletcenterpoint,refPnt1, refPnt2); if(res != 0) @@ -1665,8 +1665,8 @@ int SketchObject::fillet(int GeoId1, int GeoId2, #ifdef DEBUG Base::Console().Log("selected offset int(%f,%f,0)\n",filletcenterpoint.first.x,filletcenterpoint.first.y); -#endif - +#endif + double refoparam1; double refoparam2; @@ -1869,13 +1869,13 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) std::swap(GeoId1,GeoId2); std::swap(point1,point2); } - + auto handlemultipleintersection = [this] (Constraint * constr, int GeoId, PointPos pos, PointPos & secondPos) { - + Base::Vector3d cp = getPoint(constr->First,constr->FirstPos); - + Base::Vector3d ee = getPoint(GeoId,pos); - + if( (ee-cp).Length() < Precision::Confusion() ) { secondPos = constr->FirstPos; } @@ -2080,8 +2080,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) handlemultipleintersection(constr, GeoId, end, secondPos2); } } - - if( (constrType1 == Sketcher::Coincident && secondPos1 == Sketcher::none) || + + if( (constrType1 == Sketcher::Coincident && secondPos1 == Sketcher::none) || (constrType2 == Sketcher::Coincident && secondPos2 == Sketcher::none)) THROWM(ValueError,"Invalid position Sketcher::none when creating a Coincident constraint") @@ -2161,17 +2161,17 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) delete geoNew; rebuildVertexIndex(); - + auto handleinternalalignment = [this] (Constraint * constr, int GeoId, PointPos & secondPos) { - if( constr->Type == Sketcher::InternalAlignment && - ( constr->AlignmentType == Sketcher::EllipseMajorDiameter || + if( constr->Type == Sketcher::InternalAlignment && + ( constr->AlignmentType == Sketcher::EllipseMajorDiameter || constr->AlignmentType == Sketcher::EllipseMinorDiameter ) ) { - + Base::Vector3d sp = getPoint(constr->First,start); Base::Vector3d ep = getPoint(constr->First,end); - + Base::Vector3d ee = getPoint(GeoId,start); - + if( (ee-sp).Length() < (ee-ep).Length() ) { secondPos = Sketcher::start; } @@ -2179,8 +2179,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) secondPos = Sketcher::end; } } - }; - + }; + PointPos secondPos1 = Sketcher::none, secondPos2 = Sketcher::none; ConstraintType constrType1 = Sketcher::PointOnObject, constrType2 = Sketcher::PointOnObject; for (std::vector::const_iterator it=constraints.begin(); @@ -2194,10 +2194,10 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) else { handlemultipleintersection(constr, GeoId, start, secondPos1); } - + } else if(secondPos2 == Sketcher::none && (constr->First == GeoId2 && constr->Second == GeoId)) { constrType2 = Sketcher::Coincident; - + if(constr->FirstPos == Sketcher::none){ handleinternalalignment(constr, GeoId, secondPos2); } @@ -2206,8 +2206,8 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point) } } } - - if( (constrType1 == Sketcher::Coincident && secondPos1 == Sketcher::none) || + + if( (constrType1 == Sketcher::Coincident && secondPos1 == Sketcher::none) || (constrType2 == Sketcher::Coincident && secondPos2 == Sketcher::none)) THROWM(ValueError,"Invalid position Sketcher::none when creating a Coincident constraint") @@ -6953,6 +6953,16 @@ int SketchObject::autoRemoveRedundants(bool updategeo) return redundants.size(); } +std::vector SketchObject::getOpenVertices(void) const +{ + std::vector points; + + if(analyser) + points = analyser->getOpenVertices(); + + return points; +} + // Python Sketcher feature --------------------------------------------------------- namespace App { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 14788eb3b7..dff6ea7376 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -74,14 +74,14 @@ public: return "SketcherGui::ViewProviderSketch"; } //@} - + /** SketchObject can work in two modes: Recompute Mode and noRecomputes Mode - In Recompute Mode, a recompute is necessary after each geometry addition to update the solver DoF (default) - In NoRecomputes Mode, no recompute is necessary after a geometry addition. If a recompute is triggered it is just less efficient. - + This flag does not regulate whether this object will recompute or not if execute() or a recompute() is actually executed, - it just regulates whether the solver is called or not (i.e. whether it relies on + it just regulates whether the solver is called or not (i.e. whether it relies on the solve of execute for the calculation) */ bool noRecomputes; @@ -131,7 +131,7 @@ public: * external geometry */ int delExternal(int ExtGeoId); - + /** deletes all external geometry */ int delAllExternal(); @@ -156,7 +156,7 @@ public: /// returns non zero if the sketch contains conflicting constraints int hasConflicts(void) const; - /** + /** * sets the geometry of sketchObject as the solvedsketch geometry * returns the DoF of such a geometry. */ @@ -164,12 +164,12 @@ public: /** solves the sketch and updates the geometry, but not all the dependent features (does not recompute) When a recompute is necessary, recompute triggers execute() which solves the sketch and updates all dependent features - When a solve only is necessary (e.g. DoF changed), solve() solves the sketch and + When a solve only is necessary (e.g. DoF changed), solve() solves the sketch and updates the geometry (if updateGeoAfterSolving==true), but does not trigger any recompute. @return 0 if no error, if error, the following codes in this order of priority: -4 if overconstrained, -3 if conflicting, -1 if solver error, -2 if redundant constraints */ - int solve(bool updateGeoAfterSolving=true); + int solve(bool updateGeoAfterSolving=true); /// set the datum of a Distance or Angle constraint and solve int setDatum(int ConstrId, double Datum); /// set the driving status of this constraint and solve @@ -183,7 +183,7 @@ public: int setDatumsDriving(bool isdriving); /// Move Dimensional constraints at the end of the properties array int moveDatumsToEnd(void); - + /// set the driving status of this constraint and solve int setVirtualSpace(int ConstrId, bool isinvirtualspace); /// get the driving status of this constraint @@ -235,7 +235,7 @@ public: \retval bool - returns true if the approximation succeeded, or false if it did not succeed. */ bool convertToNURBS(int GeoId); - + /*! \brief Increases the degree of a BSpline by degreeincrement, which defaults to 1 \param GeoId - the geometry of type bspline to increase the degree @@ -243,7 +243,7 @@ public: \retval bool - returns true if the increase in degree succeeded, or false if it did not succeed. */ bool increaseBSplineDegree(int GeoId, int degreeincrement = 1); - + /*! \brief Increases or Decreases the multiplicity of a BSpline knot by the multiplicityincr param, which defaults to 1, if the result is multiplicity zero, the knot is removed \param GeoId - the geometry of type bspline to increase the degree @@ -258,11 +258,11 @@ public: int getHighestVertexIndex(void) const { return VertexId2GeoId.size() - 1; } // Most recently created int getHighestCurveIndex(void) const { return Geometry.getSize() - 1; } void rebuildVertexIndex(void); - - /// retrieves for a GeoId and PosId the Vertex number + + /// retrieves for a GeoId and PosId the Vertex number int getVertexIndexGeoPos(int GeoId, PointPos PosId) const; - // retrieves an array of maps, each map containing the points that are coincidence by virtue of + // retrieves an array of maps, each map containing the points that are coincidence by virtue of // any number of direct or indirect coincidence constraints const std::vector< std::map > getCoincidenceGroups(); // returns if the given geoId is fixed (coincident) with external geometry on any of the possible relevant points @@ -270,7 +270,7 @@ public: // returns a map containing all the GeoIds that are coincident with the given point as keys, and the PosIds as values associated // with the keys. const std::map getAllCoincidentPoints(int GeoId, PointPos PosId); - + /// retrieves for a Vertex number a list with all coincident points (sharing a single coincidence constraint) void getDirectlyCoincidentPoints(int GeoId, PointPos PosId, std::vector &GeoIdList, std::vector &PosIdList); @@ -314,7 +314,7 @@ public: bool evaluateSupport(void); /// validate External Links (remove invalid external links) void validateExternalLinks(void); - + /// gets DoF of last solver execution inline int getLastDoF() const {return lastDoF;} /// gets HasConflicts status of last solver execution @@ -331,7 +331,7 @@ public: inline const std::vector &getLastRedundant(void) const { return lastRedundant; } /// gets the solved sketch as a reference inline Sketch &getSolvedSketch(void) {return solvedSketch;} - + /// returns the geometric elements/vertex which the solver detects as having dependent parameters. /// these parameters relate to not fully constraint edges/vertices. void getGeometryWithDependentParameters(std::vector>& geometrymap); @@ -367,40 +367,43 @@ public: /// Return true if this object is allowed as external geometry for the /// sketch. rsn argument receives the reason for disallowing. bool isExternalAllowed(App::Document *pDoc, App::DocumentObject *pObj, eReasonList* rsn = 0) const; - + bool isCarbonCopyAllowed(App::Document *pDoc, App::DocumentObject *pObj, bool & xinv, bool & yinv, eReasonList* rsn = 0) const; public: // Analyser functions int autoConstraint(double precision = Precision::Confusion() * 1000, double angleprecision = M_PI/20, bool includeconstruction = true); - + int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000, bool includeconstruction = true); void analyseMissingPointOnPointCoincident(double angleprecision = M_PI/8); int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI/8); int detectMissingEqualityConstraints(double precision); - + std::vector &getMissingPointOnPointConstraints(void); std::vector &getMissingVerticalHorizontalConstraints(void); std::vector &getMissingLineEqualityConstraints(void); std::vector &getMissingRadiusConstraints(void); - + void setMissingRadiusConstraints(std::vector &cl); void setMissingLineEqualityConstraints(std::vector& cl); void setMissingVerticalHorizontalConstraints(std::vector& cl); void setMissingPointOnPointConstraints(std::vector& cl); - + void makeMissingPointOnPointCoincident(bool onebyone = false); void makeMissingVerticalHorizontal(bool onebyone = false); void makeMissingEquality(bool onebyone = true); - + // helper /// returns the number of redundant constraints detected int autoRemoveRedundants(bool updategeo = true); - + + // Validation routines + std::vector getOpenVertices(void) const; + protected: /// get called by the container when a property has changed virtual void onChanged(const App::Property* /*prop*/); virtual void onDocumentRestored(); - + virtual void setExpression(const App::ObjectIdentifier &path, boost::shared_ptr expr, const char * comment = 0); std::string validateExpression(const App::ObjectIdentifier &path, boost::shared_ptr expr); @@ -430,14 +433,14 @@ private: std::vector VertexId2GeoId; std::vector VertexId2PosId; - + Sketch solvedSketch; - - /** this internal flag indicate that an operation modifying the geometry, but not the DoF of the sketch took place (e.g. toggle construction), + + /** this internal flag indicate that an operation modifying the geometry, but not the DoF of the sketch took place (e.g. toggle construction), so if next action is a movement of a point (movePoint), the geometry must be updated first. */ bool solverNeedsUpdate; - + int lastDoF; bool lastHasConflict; bool lastHasRedundancies; diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index a43085e236..93df7b4631 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -181,7 +181,7 @@ add a symmetric geometric objects to the sketch with respect to a reference point or line - + add a copy of geometric objects to the sketch displaced by a vector3d @@ -200,12 +200,12 @@ Deprecated -- use exposeInternalGeometry - + Deprecated -- use deleteUnusedInternalGeometry - + @@ -220,7 +220,7 @@ Approximates the given geometry with a B-Spline - + @@ -305,7 +305,7 @@ - Analyses the already detected Missing Point On Point Constraints to detect endpoint tagency/perpendicular. + Analyses the already detected Missing Point On Point Constraints to detect endpoint tagency/perpendicular. The result may be retrieved or applied using the corresponding Get / Make methods. @@ -354,7 +354,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -387,6 +387,14 @@ + + + + returns a list of vertices positions. + + + + Number of Constraints in this sketch diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index bdeedd3692..bde505abee 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -1617,6 +1617,21 @@ PyObject* SketchObjectPy::getGeometryWithDependentParameters(PyObject *args) return Py::new_reference_to(list); } +Py::List SketchObjectPy::getOpenVertices(void) const +{ + std::vector points = this->getSketchObjectPtr()->getOpenVertices(); + + Py::List list; + for (auto p : points) { + Py::Tuple t(3); + t.setItem(0, Py::Float(p.x)); + t.setItem(1, Py::Float(p.y)); + t.setItem(2, Py::Float(p.z)); + list.append(t); + } + return list; +} + Py::Long SketchObjectPy::getConstraintCount(void) const { return Py::Long(this->getSketchObjectPtr()->Constraints.getSize());