/*************************************************************************** * Copyright (c) Juergen Riegel (juergen.riegel@web.de) 2008 * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #ifndef SKETCHER_SKETCHOBJECT_H #define SKETCHER_SKETCHOBJECT_H #include #include #include #include #include #include #include #include #include "Sketch.h" namespace Sketcher { struct SketcherExport GeoEnum { static const int RtPnt; static const int HAxis; static const int VAxis; static const int RefExt; }; class SketcherExport SketchObject : public Part::Part2DObject { PROPERTY_HEADER(Sketcher::SketchObject); public: SketchObject(); ~SketchObject(); /// Property Part ::PropertyGeometryList Geometry; Sketcher::PropertyConstraintList Constraints; App ::PropertyLinkSubList ExternalGeometry; /** @name methods override Feature */ //@{ /// recalculate the Feature (if no recompute is needed see also solve() and solverNeedsUpdate boolean) App::DocumentObjectExecReturn *execute(void); /// returns the type name of the ViewProvider const char* getViewProviderName(void) const { 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 the solve of execute for the calculation) */ bool noRecomputes; /*! \brief Returns true if the sketcher supports the given geometry \param geo - the geometry \retval bool - true if the geometry is supported */ bool isSupportedGeometry(const Part::Geometry *geo) const; /// add unspecified geometry int addGeometry(const Part::Geometry *geo, bool construction=false); /// add unspecified geometry int addGeometry(const std::vector &geoList, bool construction=false); /*! \brief Deletes indicated geometry (by geoid). \param GeoId - the geometry to delete \param deleteinternalgeo - if true deletes the associated and unconstraint internal geometry, otherwise deletes only the GeoId \retval int - 0 if successful */ int delGeometry(int GeoId, bool deleteinternalgeo = true); /// deletes all the elements/constraints of the sketch except for external geometry int deleteAllGeometry(); /// add all constraints in the list int addConstraints(const std::vector &ConstraintList); /// Copy the constraints instead of cloning them and copying the expressions if any int addCopyOfConstraints(const SketchObject &orig); /// add constraint int addConstraint(const Constraint *constraint); /// delete constraint int delConstraint(int ConstrId); int delConstraintOnPoint(int GeoId, PointPos PosId, bool onlyCoincident=true); int delConstraintOnPoint(int VertexId, bool onlyCoincident=true); /// Deletes all constraints referencing an external geometry int delConstraintsToExternal(); /// transfers all constraints of a point to a new point int transferConstraints(int fromGeoId, PointPos fromPosId, int toGeoId, PointPos toPosId); /// Carbon copy another sketch geometry and constraints int carbonCopy(App::DocumentObject * pObj, bool construction = true); /// add an external geometry reference int addExternal(App::DocumentObject *Obj, const char* SubName); /** delete external * ExtGeoId >= 0 with 0 corresponding to the first user defined * external geometry */ int delExternal(int ExtGeoId); /** deletes all external geometry */ int delAllExternal(); /** returns a pointer to a given Geometry index, possible indexes are: * id>=0 for user defined geometries, * id==-1 for the horizontal sketch axis, * id==-2 for the vertical sketch axis * id<=-3 for user defined projected external geometries, */ const Part::Geometry* getGeometry(int GeoId) const; /// returns a list of all internal geometries const std::vector &getInternalGeometry(void) const { return Geometry.getValues(); } /// returns a list of projected external geometries const std::vector &getExternalGeometry(void) const { return ExternalGeo; } /// rebuilds external geometry (projection onto the sketch plane) void rebuildExternalGeometry(void); /// returns the number of external Geometry entities int getExternalGeometryCount(void) const { return ExternalGeo.size(); } /// retrieves a vector containing both normal and external Geometry (including the sketch axes) std::vector getCompleteGeometry(void) const; /// 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. */ int setUpSketch(); /** 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 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); /// 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 int setDriving(int ConstrId, bool isdriving); /// get the driving status of this constraint int getDriving(int ConstrId, bool &isdriving); /// toggle the driving status of this constraint int toggleDriving(int ConstrId); /// set the driving status of this constraint and solve int setVirtualSpace(int ConstrId, bool isinvirtualspace); /// get the driving status of this constraint int getVirtualSpace(int ConstrId, bool &isinvirtualspace) const; /// toggle the driving status of this constraint int toggleVirtualSpace(int ConstrId); /// move this point to a new location and solve int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false, bool updateGeoBeforeMoving=false); /// retrieves the coordinates of a point Base::Vector3d getPoint(int GeoId, PointPos PosId) const; /// toggle geometry to draft line int toggleConstruction(int GeoId); int setConstruction(int GeoId, bool on); /// create a fillet int fillet(int geoId, PointPos pos, double radius, bool trim=true); int fillet(int geoId1, int geoId2, const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2, double radius, bool trim=true); /// trim a curve int trim(int geoId, const Base::Vector3d& point); /// extend a curve int extend(int geoId, double increment, int endPoint); /// adds symmetric geometric elements with respect to the refGeoId (line or point) int addSymmetric(const std::vector &geoIdList, int refGeoId, Sketcher::PointPos refPosId=Sketcher::none); /// with default parameters adds a copy of the geometric elements displaced by the displacement vector. /// It creates an array of csize elements in the direction of the displacement vector by rsize elements in the /// direction perpendicular to the displacement vector, wherein the modulus of this perpendicular vector is scaled by perpscale. int addCopy(const std::vector &geoIdList, const Base::Vector3d& displacement, bool moveonly = false, bool clone=false, int csize=2, int rsize=1, bool constraindisplacement = false, double perpscale = 1.0); /// Exposes all internal geometry of an object supporting internal geometry /*! * \return -1 on error */ int exposeInternalGeometry(int GeoId); /*! \brief Deletes all unused (not further constrained) internal geometry \param GeoId - the geometry having the internal geometry to delete \param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId geometry \retval int - returns -1 on error, otherwise the number of deleted elements */ int deleteUnusedInternalGeometry(int GeoId, bool delgeoid=false); /*! \brief Approximates the given geometry with a B-spline \param GeoId - the geometry to approximate \param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId geometry \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 \param degreeincrement - the increment in number of degrees to effect \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 \param knotIndex - the index of the knot to modify (note that index is OCC consistent, so 1<=knotindex<=knots) \param multiplicityincr - the increment (positive value) or decrement (negative value) of multiplicity of the knot \retval bool - returns true if the operation succeeded, or false if it did not succeed. */ bool modifyBSplineKnotMultiplicity(int GeoId, int knotIndex, int multiplicityincr = 1); /// retrieves for a Vertex number the corresponding GeoId and PosId void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId) const; 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 int getVertexIndexGeoPos(int GeoId, PointPos PosId) const; // 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 void isCoincidentWithExternalGeometry(int GeoId, bool &start_external, bool &mid_external, bool &end_external); // 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); void getDirectlyCoincidentPoints(int VertexId, std::vector &GeoIdList, std::vector &PosIdList); bool arePointsCoincident(int GeoId1, PointPos PosId1, int GeoId2, PointPos PosId2); /// generates a warning message about constraint conflicts and appends it to the given message static void appendConflictMsg(const std::vector &conflicting, std::string &msg); /// generates a warning message about redundant constraints and appends it to the given message static void appendRedundantMsg(const std::vector &redundant, std::string &msg); double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py); bool isPointOnCurve(int geoIdCurve, double px, double py); double calculateConstraintError(int ConstrId); int changeConstraintsLocking(bool bLock); /// returns whether a given constraint has an associated expression or not bool constraintHasExpression(int constrid) const; ///porting functions int port_reversedExternalArcs(bool justAnalyze); // from base class virtual PyObject *getPyObject(void); virtual unsigned int getMemSize(void) const; virtual void Save(Base::Writer &/*writer*/) const; virtual void Restore(Base::XMLReader &/*reader*/); /// returns the number of construction lines (to be used as axes) virtual int getAxisCount(void) const; /// retrieves an axis iterating through the construction lines of the sketch (indices start at 0) virtual Base::Axis getAxis(int axId) const; /// verify and accept the assigned geometry virtual void acceptGeometry(); /// Check if constraint has invalid indexes bool evaluateConstraint(const Constraint *constraint) const; /// Check for constraints with invalid indexes bool evaluateConstraints() const; /// Remove constraints with invalid indexes void validateConstraints(); /// Checks if support is valid 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 inline bool getLastHasConflicts() const {return lastHasConflict;} /// gets HasRedundancies status of last solver execution inline bool getLastHasRedundancies() const {return lastHasRedundancies;} /// gets solver status of last solver execution inline int getLastSolverStatus() const {return lastSolverStatus;} /// gets solver SolveTime of last solver execution inline float getLastSolveTime() const {return lastSolveTime;} /// gets the conflicting constraints of the last solver execution inline const std::vector &getLastConflicting(void) const { return lastConflicting; } /// gets the redundant constraints of last solver execution inline const std::vector &getLastRedundant(void) const { return lastRedundant; } /// gets the solved sketch as a reference inline Sketch &getSolvedSketch(void) {return solvedSketch;} /// Flag to allow external geometry from other bodies than the one this sketch belongs to bool isAllowedOtherBody() const { return allowOtherBody; } void setAllowOtherBody(bool on) { allowOtherBody = on; } /// Flag to allow carbon copy from misaligned geometry bool isAllowedUnaligned() const { return allowUnaligned; } void setAllowUnaligned(bool on) { allowUnaligned = on; } enum eReasonList{ rlAllowed, rlOtherDoc, rlCircularReference, rlOtherPart, rlOtherBody, rlOtherBodyWithLinks, // for carbon copy rlNotASketch, // for carbon copy rlNonParallel, // for carbon copy rlAxesMisaligned, // for carbon copy rlOriginsMisaligned // for carbon copy }; /// 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; 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); void constraintsRenamed(const std::map &renamed); void constraintsRemoved(const std::set &removed); /*! \brief Returns a list of supported geometries from the input list \param geoList - the geometry list \retval list - the supported geometry list */ std::vector supportedGeometry(const std::vector &geoList) const; private: /// Flag to allow external geometry from other bodies than the one this sketch belongs to bool allowOtherBody; /// Flag to allow carbon copy from misaligned geometry bool allowUnaligned; std::vector ExternalGeo; 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), 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; int lastSolverStatus; float lastSolveTime; std::vector lastConflicting; std::vector lastRedundant; boost::signals::scoped_connection constraintsRenamedConn; boost::signals::scoped_connection constraintsRemovedConn; bool AutoLockTangencyAndPerpty(Constraint* cstr, bool bForce = false, bool bLock = true); }; typedef App::FeaturePythonT SketchObjectPython; } //namespace Sketcher #endif // SKETCHER_SKETCHOBJECT_H