<plugin script="addons_Features" configuration="addons_Features.xml"/>
<plugin script="ConnectorPlugin" configuration="plugin-Connector.xml" dependency="Geometry"/>
<plugin library="ParametersPlugin" configuration="plugin-Parameters.xml"/>
- <plugin library="SolveSpaceSolver"/>
+ <plugin library="SketchSolver"/>
<plugin library="GeomValidators"/>
<plugin library="DFBrowser" internal="true"/>
</plugins>
## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
INCLUDE(Common)
+FIND_PACKAGE(SolveSpace REQUIRED)
SET(PROJECT_HEADERS
SketchSolver.h
SketchSolver_Error.h
+ SketchSolver_Solver.h
SketchSolver_Constraint.h
SketchSolver_ConstraintAngle.h
SketchSolver_ConstraintCoincidence.h
SketchSolver_ConstraintDistance.h
SketchSolver_ConstraintEqual.h
+ SketchSolver_ConstraintFillet.h
SketchSolver_ConstraintLength.h
SketchSolver_ConstraintMirror.h
- SketchSolver_ConstraintFixed.h
+ SketchSolver_ConstraintRigid.h
SketchSolver_ConstraintTangent.h
SketchSolver_ConstraintMulti.h
SketchSolver_ConstraintMultiRotation.h
SketchSolver_ConstraintMultiTranslation.h
SketchSolver_ConstraintMovement.h
-# SketchSolver_ConstraintParametric.h
- SketchSolver_Group.h
+ SketchSolver_ConstraintParametric.h
SketchSolver_Builder.h
- SketchSolver_IConstraintWrapper.h
- SketchSolver_IEntityWrapper.h
- SketchSolver_IParameterWrapper.h
- SketchSolver_ISolver.h
- SketchSolver_Manager.h
+ SketchSolver_Group.h
+ SketchSolver_ConstraintManager.h
SketchSolver_Storage.h
+ SketchSolver_FeatureStorage.h
)
SET(PROJECT_SOURCES
+ SketchSolver_Solver.cpp
SketchSolver_Constraint.cpp
SketchSolver_ConstraintAngle.cpp
SketchSolver_ConstraintCoincidence.cpp
SketchSolver_ConstraintDistance.cpp
SketchSolver_ConstraintEqual.cpp
+ SketchSolver_ConstraintFillet.cpp
SketchSolver_ConstraintLength.cpp
SketchSolver_ConstraintMirror.cpp
- SketchSolver_ConstraintFixed.cpp
+ SketchSolver_ConstraintRigid.cpp
SketchSolver_ConstraintTangent.cpp
SketchSolver_ConstraintMulti.cpp
SketchSolver_ConstraintMultiRotation.cpp
SketchSolver_ConstraintMultiTranslation.cpp
+ SketchSolver_ConstraintParametric.cpp
SketchSolver_ConstraintMovement.cpp
-# SketchSolver_ConstraintParametric.cpp
- SketchSolver_Group.cpp
SketchSolver_Builder.cpp
- SketchSolver_Manager.cpp
+ SketchSolver_Group.cpp
+ SketchSolver_ConstraintManager.cpp
SketchSolver_Storage.cpp
+ SketchSolver_FeatureStorage.cpp
)
SET(PROJECT_LIBRARIES
+ ${SOLVESPACE_LIBRARIES}
Config
Events
ModelAPI
)
INCLUDE_DIRECTORIES(
+ ${SOLVESPACE_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/Config
${PROJECT_SOURCE_DIR}/src/SketchPlugin
${PROJECT_SOURCE_DIR}/src/ModelAPI
ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
-ADD_LIBRARY(SketchSolver SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}
+ADD_LIBRARY(SketchSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS}
)
TARGET_LINK_LIBRARIES(SketchSolver ${PROJECT_LIBRARIES}
)
INSTALL(TARGETS SketchSolver DESTINATION plugins)
-
-
-# Include specific solvers
-FIND_FILE(SSPath "SolveSpaceSolver/CMakeLists.txt" PATHS "${CMAKE_CURRENT_SOURCE_DIR}")
-STRING(COMPARE NOTEQUAL ${SSPath} "SSPath-NOTFOUND" SSPath_FOUND)
-FIND_FILE(GCSPath "PlainGCSSolver/CMakeLists.txt" PATHS "${CMAKE_CURRENT_SOURCE_DIR}")
-STRING(COMPARE NOTEQUAL ${GCSPath} "GCSPath-NOTFOUND" GCSPath_FOUND)
-
-IF(${SSPath_FOUND} OR ${GCSPath_FOUND})
- IF(${SSPath_FOUND})
- MESSAGE(STATUS "SolveSpaceSolver plugin found in ${SSPath}")
- ADD_SUBDIRECTORY(SolveSpaceSolver)
- ENDIF()
- IF(${GCSPath_FOUND})
- MESSAGE(STATUS "PlainGCSSolver plugin found in ${GCSPath}")
- ADD_SUBDIRECTORY(PlainGCSSolver)
- ENDIF()
-ELSE()
- MESSAGE(WARNING "No sketch solver plugin is found")
-ENDIF()
#ifndef SKETCHSOLVER_H
#define SKETCHSOLVER_H
-#include <stdlib.h>
-
#if defined SKETCHSOLVER_EXPORTS
#if defined WIN32
#define SKETCHSOLVER_EXPORT __declspec( dllexport )
#define PI 3.1415926535897932
-// Types for data entities enumeration
-typedef size_t GroupID;
-typedef size_t ParameterID;
-typedef size_t EntityID;
-typedef size_t ConstraintID;
-
-// Predefined values for identifiers
-const GroupID GID_UNKNOWN = 0;
-const GroupID GID_OUTOFGROUP = 1;
-
-const ParameterID PID_UNKNOWN = 0;
-const EntityID EID_UNKNOWN = 0;
-const ConstraintID CID_UNKNOWN = 0;
-
#endif
// Author: Artem ZHIDKOV
#include "SketchSolver_Builder.h"
-#include <SketchSolver_Constraint.h>
+#include <SketchPlugin_ConstraintAngle.h>
#include <SketchSolver_ConstraintAngle.h>
#include <SketchSolver_ConstraintCoincidence.h>
#include <SketchSolver_ConstraintDistance.h>
#include <SketchSolver_ConstraintEqual.h>
-#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintFillet.h>
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_ConstraintRigid.h>
#include <SketchSolver_ConstraintTangent.h>
#include <SketchSolver_ConstraintMultiRotation.h>
#include <SketchSolver_ConstraintMultiTranslation.h>
#include <SketchSolver_ConstraintMovement.h>
-////#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_Error.h>
-#ifdef _DEBUG
+#include <GeomAPI_Edge.h>
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
#include <Events_Error.h>
+#include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_ResultConstruction.h>
-#include <SketchSolver_Error.h>
-#endif
-////#include <GeomAPI_Edge.h>
-////#include <GeomDataAPI_Dir.h>
-////#include <GeomDataAPI_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////#include <ModelAPI_Attribute.h>
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////
-////#include <SketchPlugin_Arc.h>
-////#include <SketchPlugin_Circle.h>
-////#include <SketchPlugin_Line.h>
-////#include <SketchPlugin_Point.h>
-#include <SketchPlugin_ConstraintAngle.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintEqual.h>
+#include <SketchPlugin_ConstraintFillet.h>
+#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMirror.h>
+#include <SketchPlugin_ConstraintParallel.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
+#include <SketchPlugin_ConstraintRadius.h>
#include <SketchPlugin_ConstraintRigid.h>
#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintVertical.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
#include <math.h>
-SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint) const
+// Initialization of constraint builder self pointer
+SketchSolver_Builder* SketchSolver_Builder::mySelf = 0;
+
+SketchSolver_Builder* SketchSolver_Builder::getInstance()
+{
+ if (!mySelf)
+ mySelf = new SketchSolver_Builder();
+ return mySelf;
+}
+
+SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint)
{
SolverConstraintPtr aResult;
DataPtr aData = theConstraint->data();
return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintHorizontal(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintParallel(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintRadius::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintRadius(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintVertical::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintVertical(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
- return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theConstraint));
+ return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
} else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
}
- // All other types of constraints
- return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
+ return aResult;
}
-SolverConstraintPtr SketchSolver_Builder::createFixedConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createRigidConstraint(FeaturePtr theFixedFeature)
{
DataPtr aData = theFixedFeature->data();
if (!aData || !aData->isValid())
return SolverConstraintPtr();
- return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature));
+ return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theFixedFeature));
}
-SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature)
{
DataPtr aData = theFixedFeature->data();
if (!aData || !aData->isValid())
return SolverConstraintPtr(new SketchSolver_ConstraintMovement(theFixedFeature));
}
-////SolverConstraintPtr SketchSolver_Builder::createParametricConstraint(AttributePtr theAttribute)
-////{
-//// return SolverConstraintPtr(new SketchSolver_ConstraintParametric(theAttribute));
-////}
+SolverConstraintPtr SketchSolver_Builder::createParametricConstraint(AttributePtr theAttribute)
+{
+ return SolverConstraintPtr(new SketchSolver_ConstraintParametric(theAttribute));
+}
+
+
+
+bool SketchSolver_Builder::createWorkplane(
+ CompositeFeaturePtr theSketch,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters)
+{
+ DataPtr aSketchData = theSketch->data();
+ if (!aSketchData || !aSketchData->isValid())
+ return false; // the sketch is incorrect
+
+ // Get parameters of workplane
+ std::shared_ptr<ModelAPI_Attribute> aDirX = aSketchData->attribute(
+ SketchPlugin_Sketch::DIRX_ID());
+ std::shared_ptr<ModelAPI_Attribute> aNorm = aSketchData->attribute(
+ SketchPlugin_Sketch::NORM_ID());
+ std::shared_ptr<ModelAPI_Attribute> anOrigin = aSketchData->attribute(
+ SketchPlugin_Sketch::ORIGIN_ID());
+ // Create SolveSpace entity corresponding to the sketch origin
+ if (!createEntity(anOrigin, theEntities, theParameters))
+ return false;
+ Slvs_hEntity anOriginID = theEntities.back().h;
+ // Create SolveSpace entity corresponding the the sketch normal
+ if (!createNormal(aNorm, aDirX, theEntities, theParameters))
+ return false;
+ Slvs_hEntity aNormalID = theEntities.back().h;
-std::shared_ptr<GeomAPI_Pnt2d> SketchSolver_Builder::point(EntityWrapperPtr theEntity) const
+ // Create workplane
+ Slvs_hEntity aWorkplaneID = theEntities.back().h + 1;
+ Slvs_Entity aWorkplane = Slvs_MakeWorkplane(aWorkplaneID, SLVS_G_UNKNOWN, anOriginID, aNormalID);
+ theEntities.push_back(aWorkplane);
+ return true;
+}
+
+bool SketchSolver_Builder::createEntity(
+ AttributePtr theAttribute,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters)
{
- if (theEntity->type() != ENTITY_POINT)
- return std::shared_ptr<GeomAPI_Pnt2d>();
-
- double aXY[2];
- std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
- for (int i = 0; i < 2 && anIt != aParams.end(); ++i, ++anIt)
- aXY[i] = (*anIt)->value();
- if (anIt != aParams.end())
- return std::shared_ptr<GeomAPI_Pnt2d>();
-
- return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aXY[0], aXY[1]));
+ Slvs_hEntity anEntID = theEntities.empty() ? 0 : theEntities.back().h;
+ Slvs_hParam aParamID = theParameters.empty() ? 0 : theParameters.back().h;
+
+ // Point in 3D
+ std::shared_ptr<GeomDataAPI_Point> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
+ if (aPoint) {
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->x()));
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->y()));
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint->z()));
+ theEntities.push_back(Slvs_MakePoint3d(++anEntID, SLVS_G_UNKNOWN,
+ aParamID-2, aParamID-1, aParamID));
+ return true;
+ }
+ // Point in 2D
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+ if (aPoint2D) {
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint2D->x()));
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aPoint2D->y()));
+ theEntities.push_back(Slvs_MakePoint2d(++anEntID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+ aParamID-1, aParamID));
+ return true;
+ }
+ // Scalar value (used for the distance entities)
+ AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+ if (aScalar) {
+ theParameters.push_back(Slvs_MakeParam(++aParamID, SLVS_G_UNKNOWN, aScalar->value()));
+ theEntities.push_back(Slvs_MakeDistance(++anEntID, SLVS_G_UNKNOWN,
+ SLVS_E_UNKNOWN, aParamID));
+ return true;
+ }
+ // unknown attribute type
+ return false;
}
-std::shared_ptr<GeomAPI_Lin2d> SketchSolver_Builder::line(EntityWrapperPtr theEntity) const
+bool SketchSolver_Builder::createEntity(
+ FeaturePtr theFeature,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters)
{
- if (theEntity->type() != ENTITY_LINE)
- return std::shared_ptr<GeomAPI_Lin2d>();
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
- std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 2 && anIt != aSubs.end(); ++i, ++anIt)
- aPoints[i] = point(*anIt);
- if (anIt != aSubs.end())
- return std::shared_ptr<GeomAPI_Lin2d>();
-
- return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0], aPoints[1]));
+ if (!theFeature->data()->isValid())
+ return false;
+
+ // SketchPlugin features
+ std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
+ SketchPlugin_Feature>(theFeature);
+ if (!aFeature)
+ return false;
+
+ // Verify the feature by its kind
+ const std::string& aFeatureKind = aFeature->getKind();
+ DataPtr aData = aFeature->data();
+ // Line
+ if (aFeatureKind == SketchPlugin_Line::ID()) {
+ AttributePtr aStart = aData->attribute(SketchPlugin_Line::START_ID());
+ AttributePtr aEnd = aData->attribute(SketchPlugin_Line::END_ID());
+ if (!aStart->isInitialized() || !aEnd->isInitialized())
+ return false;
+ if (!createEntity(aStart, theEntities, theParameters) ||
+ !createEntity(aEnd, theEntities, theParameters))
+ return false;
+ Slvs_hEntity aLineID = theEntities.back().h + 1;
+ theEntities.push_back(Slvs_MakeLineSegment(aLineID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+ aLineID-2, aLineID-1));
+ }
+ // Circle
+ else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+ AttributePtr aCenter = aData->attribute(SketchPlugin_Circle::CENTER_ID());
+ AttributePtr aRadius = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
+ if (!aCenter->isInitialized() || !aRadius->isInitialized())
+ return false;
+ if (!createEntity(aCenter, theEntities, theParameters) ||
+ !createEntity(aRadius, theEntities, theParameters))
+ return false;
+ Slvs_hEntity aCircID = theEntities.back().h;
+ theEntities.push_back(Slvs_MakeCircle(aCircID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN, aCircID-2,
+ SLVS_E_UNKNOWN, aCircID-1));
+ }
+ // Arc
+ else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+ AttributePtr aCenter = aData->attribute(SketchPlugin_Arc::CENTER_ID());
+ AttributePtr aStart = aData->attribute(SketchPlugin_Arc::START_ID());
+ AttributePtr aEnd = aData->attribute(SketchPlugin_Arc::END_ID());
+ if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
+ return false;
+ if (!createEntity(aCenter, theEntities, theParameters) ||
+ !createEntity(aStart, theEntities, theParameters) ||
+ !createEntity(aEnd, theEntities, theParameters))
+ return false;
+ Slvs_hEntity anArcID = theEntities.back().h;
+ theEntities.push_back(Slvs_MakeArcOfCircle(anArcID, SLVS_G_UNKNOWN, SLVS_E_UNKNOWN,
+ SLVS_E_UNKNOWN, anArcID-3, anArcID-2, anArcID-1));
+ }
+ // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+ else if (aFeatureKind == SketchPlugin_Point::ID()) {
+ AttributePtr aPoint = aData->attribute(SketchPlugin_Point::COORD_ID());
+ if (!aPoint->isInitialized() ||
+ !createEntity(aPoint, theEntities, theParameters))
+ return false;
+ // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier.
+ // No need to add another entity.
+ }
+ return true;
}
+bool SketchSolver_Builder::createNormal(
+ AttributePtr theNormal,
+ AttributePtr theDirX,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters)
+{
+ std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
+ std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
+ if (!aDirX || (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) ||
+ !aNorm->isInitialized())
+ return false;
+ // calculate Y direction
+ std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
+
+ // quaternion parameters of normal vector
+ double qw, qx, qy, qz;
+ Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
+ &qx, &qy, &qz);
+ double aNormCoord[4] = { qw, qx, qy, qz };
+
+ // Create parameters of the normal
+ Slvs_hParam aCurParam = theParameters.back().h;
+ for (int i = 0; i < 4; i++)
+ theParameters.push_back(Slvs_MakeParam(++aCurParam, SLVS_G_UNKNOWN, aNormCoord[i]));
+
+ // Create a normal
+ Slvs_hEntity aCurEntity = theEntities.back().h + 1;
+ Slvs_Entity aNormal = Slvs_MakeNormal3d(aCurEntity, SLVS_G_UNKNOWN,
+ aCurParam-3, aCurParam-2, aCurParam-1, aCurParam);
+ theEntities.push_back(aNormal);
+ return true;
+}
#ifndef SketchSolver_Builder_H_
#define SketchSolver_Builder_H_
+#include "SketchSolver.h"
#include <SketchSolver_Constraint.h>
+
#include <SketchPlugin_Constraint.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
+#include <ModelAPI_CompositeFeature.h>
/** \class SketchSolver_Builder
* \ingroup Plugins
- * \brief Abstract class for builders of solver's entities
+ * \brief Create bridges between SketchPlugin constraints and SolveSpace constraints
*/
class SketchSolver_Builder
{
+private:
+ /// Default constructor
+ SketchSolver_Builder() {}
+
public:
- /// \brief Creates a storage specific for used solver
- virtual StoragePtr createStorage(const GroupID& theGroup) const = 0;
- /// \brief Creates specific solver
- virtual SolverPtr createSolver() const = 0;
+ /// \brief Returns single instance of builder
+ static SketchSolver_Builder* getInstance();
/// \brief Creates a solver's constraint using given SketchPlugin constraint
/// or returns empty pointer if not all attributes are correct
- SolverConstraintPtr createConstraint(ConstraintPtr theConstraint) const;
+ SolverConstraintPtr createConstraint(ConstraintPtr theConstraint);
/// \brief Creates temporary constraint to fix the placement of the feature
- SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const;
+ SolverConstraintPtr createRigidConstraint(FeaturePtr theFixedFeature);
/// \brief Creates temporary constraint to fix the feature after movement
- SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const;
-
-//// /// \brief Creates constraint for parametrically given attribute
-//// SolverConstraintPtr createParametricConstraint(AttributePtr theAttribute) const;
-
- /// \brief Creates new constraint(s) using given parameters
- /// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
- /// \param theType [in] type of constraint
- /// \param theValue [in] numeric characteristic of constraint (e.g. distance or radius) if applicable
- /// \param theEntity1 [in] first attribute of constraint
- /// \param theEntity2 [in] second attribute of constraint
- /// \param theEntity3 [in] third attribute of constraint
- /// \param theEntity4 [in] fourth attribute of constraint
- /// \return Created list of wrappers of constraints applicable for specific solver.
- /// Most of constraint types lead to single constraint, but there are some kind of
- /// constraints (e.g. mirror), which may produce couple of constraints.
- virtual std::list<ConstraintWrapperPtr>
- createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroup,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
- const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
- const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const = 0;
-
- /// \brief Creates new multi-translation or multi-rotation constraint
- /// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
- /// \param theType [in] type of constraint
- /// \param theValue [in] numeric characteristic of constraint (angle for multi-rotation) if applicable
- /// \param thePoint1 [in] center for multi-rotation or start point for multi-translation
- /// \param thePoint2 [in] end point for multi-translation (empty for multi-rotation)
- /// \param theTrsfEnt [in] list of transformed entities
- virtual std::list<ConstraintWrapperPtr>
- createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroup,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& thePoint1,
- const EntityWrapperPtr& thePoint2,
- const std::list<EntityWrapperPtr>& theTrsfEnt) const = 0;
-
- /// \brief Update flags for several kinds of constraints
- virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const = 0;
-
- /// \brief Creates a feature using list of already created attributes
- /// \param theFeature [in] feature to create
- /// \param theAttributes [in] attributes of the feature
- /// \param theGroupID [in] group the feature belongs to
- /// \param theSketchID [in] sketch the feature belongs to
- /// \return Created wrapper of the feature applicable for specific solver
- virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
- /// \brief Creates an attribute
- /// \param theAttribute [in] attribute to create
- /// \param theGroup [in] group the attribute belongs to
- /// \param theSketchID [in] sketch the attribute belongs to
- /// \return Created wrapper of the attribute applicable for specific solver
- virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
- const GroupID& theGroup,
- const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
-
- /// \brief Convert entity to point
- /// \return empty pointer if the entity is not a point
- SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const;
- /// \brief Convert entity to line
- /// \return empty pointer if the entity is not a line
- SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const;
+ SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature);
+
+ /// \brief Creates constraint for parametrically given attribute
+ SolverConstraintPtr createParametricConstraint(AttributePtr theAttribute);
+
+ /// \brief Converts sketch parameters to the list of SolveSpace entities.
+ /// Identifiers of entities and parameters are local. They should be changed while adding into storage.
+ /// The sketch entity goes last.
+ /// \param[in] theSketch the element to be converted
+ /// \param[out] theEntities created list of entities
+ /// \param[out] theParameters created list of parameters of the entities
+ /// \return \c true if workplane created
+ bool createWorkplane(CompositeFeaturePtr theSketch,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters);
+
+ /// \brief Converts attribute to the list of entities.
+ /// Identifiers are local (see createWorkplane).
+ /// The main entity goes last.
+ bool createEntity(AttributePtr theAttribute,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters);
+ /// \brief Converts feature to the list of entities.
+ /// Identifiers are local (see createWorkplane).
+ /// The main entity goes last.
+ bool createEntity(FeaturePtr theFeature,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters);
+
+ /// \brief Converts normal and OX direction to the list of entities representing a normal in SolveSpace.
+ /// Identifiers are local (see createWorkplane).
+ /// The main entity goes last.
+ bool createNormal(AttributePtr theNormal,
+ AttributePtr theDirX,
+ std::vector<Slvs_Entity>& theEntities,
+ std::vector<Slvs_Param>& theParameters);
+
+private:
+ static SketchSolver_Builder* mySelf;
};
-typedef std::shared_ptr<SketchSolver_Builder> BuilderPtr;
-
#endif
#include <SketchSolver_Constraint.h>
#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintVertical.h>
-
#include <GeomAPI_Dir2d.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
SketchSolver_Constraint::SketchSolver_Constraint(
ConstraintPtr theConstraint)
: myBaseConstraint(theConstraint),
- myGroupID(GID_UNKNOWN),
- myType(CONSTRAINT_UNKNOWN)
+ myGroup(0)
{
}
-void SketchSolver_Constraint::process(StoragePtr theStorage,
- const GroupID& theGroupID,
- const EntityID& theSketchID)
+SketchSolver_Constraint::~SketchSolver_Constraint()
+{
+ std::map<AttributePtr, Slvs_hParam>::const_iterator anIt1 = myValueMap.begin();
+ for (; anIt1 != myValueMap.end(); anIt1++)
+ myStorage->removeParameter(anIt1->second);
+ myValueMap.clear();
+
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator anIt2 = myAttributeMap.begin();
+ for (; anIt2 != myAttributeMap.end(); anIt2++)
+ myStorage->removeEntity(anIt2->second);
+ myAttributeMap.clear();
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator anIt3 = myFeatureMap.begin();
+ while (!myFeatureMap.empty()) {
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt3->first);
+ Slvs_hEntity anEnt = anIt3->second;
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aRemIt = anIt3++;
+ myFeatureMap.erase(aRemIt);
+ if (!myGroup->isInteract(aFeature))
+ myStorage->removeEntity(anEnt);
+ }
+
+ std::vector<Slvs_hConstraint>::const_iterator anIt4 = mySlvsConstraints.begin();
+ for (; anIt4 != mySlvsConstraints.end(); anIt4++)
+ myStorage->removeConstraint(*anIt4);
+ mySlvsConstraints.clear();
+}
+
+void SketchSolver_Constraint::setStorage(StoragePtr theStorage)
{
myStorage = theStorage;
- myGroupID = theGroupID;
- mySketchID = theSketchID;
- // Process constraint according to its type
process();
}
+void SketchSolver_Constraint::setGroup(SketchSolver_Group* theGroup)
+{
+ myGroup = theGroup;
+ process();
+}
-SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint)
+void SketchSolver_Constraint::addFeature(FeaturePtr theFeature)
{
- const std::string& aType = theConstraint->getKind();
- if (aType == SketchPlugin_ConstraintCoincidence::ID())
- return CONSTRAINT_COINCIDENCE;
- else if (aType == SketchPlugin_ConstraintRigid::ID())
- return CONSTRAINT_FIXED;
- else if (aType == SketchPlugin_ConstraintHorizontal::ID())
- return CONSTRAINT_HORIZONTAL;
- else if (aType == SketchPlugin_ConstraintVertical::ID())
- return CONSTRAINT_VERTICAL;
- else if (aType == SketchPlugin_ConstraintAngle::ID())
- return CONSTRAINT_ANGLE;
- else if (aType == SketchPlugin_ConstraintDistance::ID())
- return CONSTRAINT_DISTANCE;
- else if (aType == SketchPlugin_ConstraintEqual::ID())
- return CONSTRAINT_EQUAL;
- else if (aType == SketchPlugin_ConstraintLength::ID())
- return CONSTRAINT_PT_PT_DISTANCE;
- else if (aType == SketchPlugin_ConstraintMirror::ID())
- return CONSTRAINT_SYMMETRIC;
- else if (aType == SketchPlugin_ConstraintParallel::ID())
- return CONSTRAINT_PARALLEL;
- else if (aType == SketchPlugin_ConstraintPerpendicular::ID())
- return CONSTRAINT_PERPENDICULAR;
- else if (aType == SketchPlugin_ConstraintRadius::ID())
- return CONSTRAINT_RADIUS;
- else if (aType == SketchPlugin_ConstraintTangent::ID())
- return CONSTRAINT_TANGENT;
- return CONSTRAINT_UNKNOWN;
+ int aType;
+ changeEntity(theFeature, aType);
}
+
void SketchSolver_Constraint::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are assigned
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
-//// if (!myConstraints.empty()) // some data is changed, update constraint
-//// update();
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- SketchSolver_ConstraintType aConstrType = getType();
- double aValue;
- std::vector<EntityWrapperPtr> anAttributes;
+ int aConstrType = getType();
+ double aValue = 0.0;
+ std::vector<Slvs_hEntity> anAttributes;
getAttributes(aValue, anAttributes);
if (!myErrorMsg.empty())
return;
- if (anAttributes.empty()) {
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
- return;
- }
- if (aConstrType == CONSTRAINT_UNKNOWN)
+ if (aConstrType == SLVS_C_UNKNOWN)
aConstrType = getType();
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aNewConstraints = aBuilder->createConstraint(
- myBaseConstraint, myGroupID, mySketchID, aConstrType,
- aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
- myStorage->addConstraint(myBaseConstraint, aNewConstraints);
+ Slvs_hGroup aGroupID = myGroup->getId();
+ Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+ Slvs_Constraint aConstraint;
+ if (mySlvsConstraints.empty())
+ aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, aGroupID, aConstrType, aWorkplaneID,
+ aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+ else {
+ aConstraint = myStorage->getConstraint(mySlvsConstraints[0]);
+ aConstraint.valA = aValue;
+ static const int aNbAttrs = 6;
+ Slvs_hEntity* aConstrAttrs[aNbAttrs] = {
+ &aConstraint.ptA, &aConstraint.ptB,
+ &aConstraint.entityA, &aConstraint.entityB,
+ &aConstraint.entityC, &aConstraint.entityD};
+ std::vector<Slvs_hEntity>::const_iterator anIter = anAttributes.begin();
+ for (int i = 0; i < aNbAttrs && anIter != anAttributes.end(); i++, anIter++)
+ *(aConstrAttrs[i]) = *anIter;
+ }
+ Slvs_hConstraint anID = myStorage->addConstraint(aConstraint);
+ if (mySlvsConstraints.empty())
+ mySlvsConstraints.push_back(anID);
+ else
+ mySlvsConstraints[0] = anID;
adjustConstraint();
}
-////bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
-////{
-//// std::set<Slvs_hEntity> aCurAttrs; // list of currently used attributes
-//// std::vector<Slvs_hConstraint>::const_iterator aConstrIter = mySlvsConstraints.begin();
-//// for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
-//// Slvs_Constraint aConstr = myStorage->getConstraint(*aConstrIter);
-//// if (aConstr.ptA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptA);
-//// if (aConstr.ptB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptB);
-//// if (aConstr.entityA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityA);
-//// if (aConstr.entityB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityB);
-//// if (aConstr.entityC != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityC);
-//// if (aConstr.entityD != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityD);
-//// }
-//// // Check the attrbutes of constraint are changed
-//// ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-//// std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
-//// std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
-//// for (; anAttrIter != anAttrList.end(); anAttrIter++) {
-//// AttributeRefAttrPtr aRefAttr =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
-//// if (aRefAttr) {
-//// if (aRefAttr->isObject()) {
-//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFIt = myFeatureMap.find(aFeature);
-//// if (aFeature) {
-//// if (aFIt == myFeatureMap.end())
-//// return true;
-//// // Additional check the points of entity
-//// if (aCurAttrs.find(aFIt->second) == aCurAttrs.end()) {
-//// Slvs_Entity anEntity = myStorage->getEntity(aFIt->second);
-//// bool isFound = false;
-//// for (int i = 0; i < 4 && !isFound; i++)
-//// if (anEntity.point[i] != SLVS_E_UNKNOWN &&
-//// aCurAttrs.find(anEntity.point[i]) != aCurAttrs.end())
-//// isFound = true;
-//// if (!isFound)
-//// return true;
-//// }
-//// }
-//// } else if (aRefAttr->attr()) {
-//// std::map<AttributePtr, Slvs_hEntity>::iterator anAIt = myAttributeMap.find(aRefAttr->attr());
-//// if (anAIt == myAttributeMap.end() || aCurAttrs.find(anAIt->second) == aCurAttrs.end())
-//// return true;
-//// }
-//// }
-//// AttributeRefListPtr aRefList =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
-//// if (aRefList) {
-//// std::list<ObjectPtr> anItems = aRefList->list();
-//// std::list<ObjectPtr>::iterator anIt = anItems.begin();
-//// for (; anIt != anItems.end(); anIt++) {
-//// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
-//// if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
-//// return true;
-//// }
-//// }
-//// }
-//// return false;
-////}
-
-void SketchSolver_Constraint::update()
+bool SketchSolver_Constraint::checkAttributesChanged(ConstraintPtr theConstraint)
+{
+ std::set<Slvs_hEntity> aCurAttrs; // list of currently used attributes
+ std::vector<Slvs_hConstraint>::const_iterator aConstrIter = mySlvsConstraints.begin();
+ for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
+ Slvs_Constraint aConstr = myStorage->getConstraint(*aConstrIter);
+ if (aConstr.ptA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptA);
+ if (aConstr.ptB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.ptB);
+ if (aConstr.entityA != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityA);
+ if (aConstr.entityB != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityB);
+ if (aConstr.entityC != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityC);
+ if (aConstr.entityD != SLVS_E_UNKNOWN) aCurAttrs.insert(aConstr.entityD);
+ }
+ // Check the attrbutes of constraint are changed
+ ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+ std::list<AttributePtr> anAttrList = aConstraint->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+ for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+ if (aRefAttr) {
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFIt = myFeatureMap.find(aFeature);
+ if (aFeature) {
+ if (aFIt == myFeatureMap.end())
+ return true;
+ // Additional check the points of entity
+ if (aCurAttrs.find(aFIt->second) == aCurAttrs.end()) {
+ Slvs_Entity anEntity = myStorage->getEntity(aFIt->second);
+ bool isFound = false;
+ for (int i = 0; i < 4 && !isFound; i++)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN &&
+ aCurAttrs.find(anEntity.point[i]) != aCurAttrs.end())
+ isFound = true;
+ if (!isFound)
+ return true;
+ }
+ }
+ } else if (aRefAttr->attr()) {
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAIt = myAttributeMap.find(aRefAttr->attr());
+ if (anAIt == myAttributeMap.end() || aCurAttrs.find(anAIt->second) == aCurAttrs.end())
+ return true;
+ }
+ }
+ AttributeRefListPtr aRefList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
+ if (aRefList) {
+ std::list<ObjectPtr> anItems = aRefList->list();
+ std::list<ObjectPtr>::iterator anIt = anItems.begin();
+ for (; anIt != anItems.end(); anIt++) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
{
cleanErrorMsg();
+ bool needToRebuild = (theConstraint && theConstraint != myBaseConstraint);
+ if (!needToRebuild)
+ needToRebuild = checkAttributesChanged(theConstraint);
+ if (needToRebuild) {
+ if (theConstraint && theConstraint->getKind() != myBaseConstraint->getKind())
+ return;
+ remove(myBaseConstraint);
+ if (theConstraint)
+ myBaseConstraint = theConstraint;
+ process();
+ return;
+ }
- std::list<ConstraintWrapperPtr> aWrapper = myStorage->constraint(myBaseConstraint);
- AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
- if (aValueAttr) {
- std::list<ConstraintWrapperPtr>::iterator aWIt = aWrapper.begin();
- for (; aWIt != aWrapper.end(); ++aWIt)
- (*aWIt)->setValue(aValueAttr->value());
+ // Update all attributes
+ int aType;
+ std::map<Slvs_hEntity, Slvs_hEntity> aRelocationMap;
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIter = myFeatureMap.begin();
+ for (; aFeatIter != myFeatureMap.end(); aFeatIter++) {
+ Slvs_hEntity aPrevID = aFeatIter->second;
+ aFeatIter->second = changeEntity(aFeatIter->first, aType);
+ if (aFeatIter->second != aPrevID)
+ aRelocationMap[aPrevID] = aFeatIter->second;
+ }
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
+ for (; anAttrIter != myAttributeMap.end(); anAttrIter++) {
+ Slvs_hEntity aPrevID = anAttrIter->second;
+ anAttrIter->second = changeEntity(anAttrIter->first, aType);
+ if (anAttrIter->second != aPrevID)
+ aRelocationMap[aPrevID] = anAttrIter->second;
}
- myStorage->addConstraint(myBaseConstraint, aWrapper);
+ // Value if exists
+ DataPtr aData = myBaseConstraint->data();
+ if (!aData) return;
+ AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
+ double aValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+ // Update constraint
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+ Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
+ if (aValueAttr) {
+ aConstraint.valA = aValue;
+ if (aConstraint.type == SLVS_C_DIAMETER)
+ aConstraint.valA *= 2.0;
+ }
+ Slvs_hEntity* aCoeffs[6] = {
+ &aConstraint.ptA, &aConstraint.ptB,
+ &aConstraint.entityA, &aConstraint.entityB,
+ &aConstraint.entityC, &aConstraint.entityD};
+ for (int i = 0; i < 6; i++) {
+ if (*(aCoeffs[i]) == SLVS_E_UNKNOWN)
+ continue;
+ std::map<Slvs_hEntity, Slvs_hEntity>::iterator aFound = aRelocationMap.find(*(aCoeffs[i]));
+ if (aFound != aRelocationMap.end())
+ *(aCoeffs[i]) = aFound->second;
+ }
+ *aCIter = myStorage->addConstraint(aConstraint);
+ }
adjustConstraint();
}
-bool SketchSolver_Constraint::remove()
+bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
{
cleanErrorMsg();
- return myStorage->removeConstraint(myBaseConstraint);
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ if (mySlvsConstraints.empty())
+ return true;
+ bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints.front());
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+ mySlvsConstraints.clear();
+ return true;
+}
+
+void SketchSolver_Constraint::cleanRemovedEntities()
+{
+ std::set<Slvs_hParam> aRemovedParams;
+ std::set<Slvs_hEntity> aRemovedEntities;
+ std::set<Slvs_hConstraint> aRemovedConstraints;
+ myStorage->getRemoved(aRemovedParams, aRemovedEntities, aRemovedConstraints);
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+ while (aFeatIt != myFeatureMap.end()) {
+ if (aRemovedEntities.find(aFeatIt->second) == aRemovedEntities.end()) {
+ aFeatIt++;
+ continue;
+ }
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aTmpIter = aFeatIt++;
+ myFeatureMap.erase(aTmpIter);
+ }
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = myAttributeMap.begin();
+ while (anAttrIt != myAttributeMap.end()) {
+ if (aRemovedEntities.find(anAttrIt->second) == aRemovedEntities.end()) {
+ anAttrIt++;
+ continue;
+ }
+ std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIt++;
+ myAttributeMap.erase(aTmpIter);
+ }
+ std::map<AttributePtr, Slvs_hParam>::iterator aValIt = myValueMap.begin();
+ while (aValIt != myValueMap.end()) {
+ if (aRemovedParams.find(aValIt->second) == aRemovedParams.end()) {
+ aValIt++;
+ continue;
+ }
+ std::map<AttributePtr, Slvs_hParam>::iterator aTmpIter = aValIt++;
+ myValueMap.erase(aTmpIter);
+ }
+ for (size_t i = 0; i < mySlvsConstraints.size(); i++)
+ if (aRemovedConstraints.find(mySlvsConstraints[i]) != aRemovedConstraints.end()) {
+ mySlvsConstraints.erase(mySlvsConstraints.begin() + i);
+ i--;
+ }
}
void SketchSolver_Constraint::getAttributes(
double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+ std::vector<Slvs_hEntity>& theAttributes)
{
static const int anInitNbOfAttr = 4;
- theAttributes.assign(anInitNbOfAttr, EntityWrapperPtr());
+ theAttributes.assign(anInitNbOfAttr, SLVS_E_UNKNOWN);
DataPtr aData = myBaseConstraint->data();
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- myType = TYPE(myBaseConstraint);
AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- aData->attribute(SketchPlugin_Constraint::VALUE()));
+ aData->attribute(SketchPlugin_Constraint::VALUE()));
theValue = aValueAttr ? aValueAttr->value() : 0.0;
int aPtInd = 0; // index of first point in the list of attributes
- int aEntInd = 2; // index of first entity in the list of attributes
+ int aEntInd = 2; // index of first antity in the list of attributes
std::list<AttributePtr> aConstrAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
std::list<AttributePtr>::iterator anIter = aConstrAttrs.begin();
for (; anIter != aConstrAttrs.end(); anIter++) {
return;
}
- myStorage->update(*anIter, myGroupID);
- EntityWrapperPtr anEntity = myStorage->entity(*anIter);
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
+ if (anEntity == SLVS_E_UNKNOWN)
+ anEntity = changeEntity(aRefAttr, aType);
+ else {
+ Slvs_Entity anEnt = myStorage->getEntity(anEntity);
+ aType = anEnt.type;
+ }
- SketchSolver_EntityType aType = anEntity->type();
- if (aType == ENTITY_UNKNOWN)
+ if (aType == SLVS_E_UNKNOWN)
continue;
- else if (aType == ENTITY_POINT)
+ else if (aType == SLVS_E_POINT_IN_2D || aType == SLVS_E_POINT_IN_3D)
theAttributes[aPtInd++] = anEntity; // the point is created
else { // another entity (not a point) is created
if (aEntInd < anInitNbOfAttr)
}
}
-bool SketchSolver_Constraint::isUsed(FeaturePtr theFeature) const
+Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttribute, int& theType)
{
- const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
- for (; aCIt != aCList.end(); ++aCIt)
- if ((*aCIt)->isUsed(theFeature))
- return true;
-
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anAttrIt = anAttrList.begin();
- for (; anAttrIt != anAttrList.end(); ++ anAttrIt)
- if (isUsed(*anAttrIt))
- return true;
+ // Convert the object of the attribute to the feature
+ FeaturePtr aFeature;
+ if (theAttribute->isObject() && theAttribute->object()) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ theAttribute->object());
+ if (!aRC) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return SLVS_E_UNKNOWN;
+ }
+ std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
+ aFeature = aDoc->feature(aRC);
- return false;
+ return changeEntity(aFeature, theType);
+ }
+
+ return changeEntity(theAttribute->attr(), theType);
+}
+
+Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
+{
+ Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+ if (!theEntity || !isInitialized(theEntity)) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return SLVS_E_UNKNOWN;
+ }
+
+ // If the entity is already in the group, try to find it
+ std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
+ myAttributeMap.find(theEntity);
+ Slvs_Entity aCurrentEntity;
+ aCurrentEntity.h = SLVS_E_UNKNOWN;
+ if (anEntIter != myAttributeMap.end())
+ aCurrentEntity = myStorage->getEntity(anEntIter->second);
+ else {
+ aResult = myGroup->getAttributeId(theEntity);
+ if (aResult != SLVS_E_UNKNOWN) {
+ Slvs_Entity anEnt = myStorage->getEntity(aResult);
+ theType = anEnt.type;
+ myAttributeMap[theEntity] = aResult;
+ return aResult;
+ }
+ }
+
+ Slvs_hGroup aGroupID = myGroup->getId();
+ // do not update entity from another group
+ if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
+ return aCurrentEntity.h;
+
+ // Point in 3D
+ std::shared_ptr<GeomDataAPI_Point> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
+ if (aPoint) {
+ double aXYZ[3] = {aPoint->x(), aPoint->y(), aPoint->z()};
+ Slvs_hParam aParams[3];
+ for (int i = 0; i < 3; i++) {
+ Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+ myStorage->getParameter(aCurrentEntity.param[i]) :
+ Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+ aPar.val = aXYZ[i];
+ aParams[i] = myStorage->addParameter(aPar);
+ }
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+ aCurrentEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, aGroupID, aParams[0], aParams[1], aParams[2]);
+ else { // update entity data
+ for (int i = 0; i < 3; i++)
+ aCurrentEntity.param[i] = aParams[i];
+ }
+ aResult = myStorage->addEntity(aCurrentEntity);
+ } else {
+ // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
+ Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+ if (aWorkplaneID == SLVS_E_UNKNOWN)
+ return SLVS_E_UNKNOWN;
+
+ // Point in 2D
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
+ if (aPoint2D) {
+ double aXY[2] = {aPoint2D->x(), aPoint2D->y()};
+ Slvs_hParam aParams[2];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+ myStorage->getParameter(aCurrentEntity.param[i]) :
+ Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+ aPar.val = aXY[i];
+ aParams[i] = myStorage->addParameter(aPar);
+ }
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+ aCurrentEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aParams[0], aParams[1]);
+ else { // update entity data
+ for (int i = 0; i < 2; i++)
+ aCurrentEntity.param[i] = aParams[i];
+ }
+ aResult = myStorage->addEntity(aCurrentEntity);
+ } else {
+ // Scalar value (used for the distance entities)
+ AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
+ if (aScalar) {
+ Slvs_Param aParam = aCurrentEntity.h != SLVS_E_UNKNOWN ?
+ myStorage->getParameter(aCurrentEntity.param[0]) :
+ Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
+ aParam.val = aScalar->value();
+ Slvs_hParam aValue = myStorage->addParameter(aParam);
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+ aCurrentEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aValue);
+ else
+ aCurrentEntity.param[0] = aValue;
+ aResult = myStorage->addEntity(aCurrentEntity);
+ }
+ }
+ }
+
+ myAttributeMap[theEntity] = aResult;
+ theType = aCurrentEntity.type;
+ return aResult;
}
-bool SketchSolver_Constraint::isUsed(AttributePtr theAttribute) const
+Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
- anAttribute = aRefAttr->attr();
+ Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+ if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
+ return SLVS_E_UNKNOWN;
+ // If the entity is already in the group, try to find it
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
+ Slvs_Entity aCurrentEntity;
+ aCurrentEntity.h = SLVS_E_UNKNOWN;
+ if (anEntIter != myFeatureMap.end())
+ aCurrentEntity = myStorage->getEntity(anEntIter->second);
+ else {
+ aResult = myGroup->getFeatureId(theEntity);
+ if (aResult != SLVS_E_UNKNOWN) {
+ Slvs_Entity anEnt = myStorage->getEntity(aResult);
+ theType = anEnt.type;
+ myFeatureMap[theEntity] = aResult;
+ return aResult;
+ }
+ }
+
+ Slvs_hGroup aGroupID = myGroup->getId();
+ // do not update entity from another group
+ if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
+ return aCurrentEntity.h;
+
+ Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
+ DataPtr aData = theEntity->data();
+
+ // SketchPlugin features
+ const std::string& aFeatureKind = theEntity->getKind();
+ AttributePtr anAttribute;
+ int anAttrType;
+ // Line
+ if (aFeatureKind == SketchPlugin_Line::ID()) {
+ anAttribute = aData->attribute(SketchPlugin_Line::START_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+ anAttribute = aData->attribute(SketchPlugin_Line::END_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
+ aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
+ else {
+ aCurrentEntity.point[0] = aStart;
+ aCurrentEntity.point[1] = aEnd;
+ }
+ aResult = myStorage->addEntity(aCurrentEntity);
+ }
+ // Circle
+ else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+ anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+ anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+ Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+ aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+ aCenter, aWorkplane.normal, aRadius);
+ } else {
+ aCurrentEntity.point[0] = aCenter;
+ aCurrentEntity.distance = aRadius;
+ }
+ aResult = myStorage->addEntity(aCurrentEntity);
+ }
+ // Arc
+ else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+ anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
+
+ anAttribute = aData->attribute(SketchPlugin_Arc::START_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
+
+ anAttribute = aData->attribute(SketchPlugin_Arc::END_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
+
+ if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
+ Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
+ aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
+ aWorkplane.normal, aCenter, aStart, aEnd);
+ } else {
+ aCurrentEntity.point[0] = aCenter;
+ aCurrentEntity.point[1] = aStart;
+ aCurrentEntity.point[2] = aEnd;
+ }
+ aResult = myStorage->addEntity(aCurrentEntity);
+ }
+ // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+ else if (aFeatureKind == SketchPlugin_Point::ID()) {
+ anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID());
+ if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
+ // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
+ aResult = changeEntity(anAttribute, anAttrType);
+ aCurrentEntity.type = SLVS_E_POINT_IN_3D;
+ }
+
+ if (aResult != SLVS_E_UNKNOWN) {
+ myFeatureMap[theEntity] = aResult;
+ theType = aCurrentEntity.type;
}
+ return aResult;
+}
- const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
- for (; aCIt != aCList.end(); ++aCIt)
- if ((*aCIt)->isUsed(theAttribute))
- return true;
+std::list<ConstraintPtr> SketchSolver_Constraint::constraints() const
+{
+ std::list<ConstraintPtr> aConstraints;
+ aConstraints.push_back(myBaseConstraint);
+ return aConstraints;
+}
+
+void SketchSolver_Constraint::refresh()
+{
+ cleanErrorMsg();
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
+ while (anAttrIter != myAttributeMap.end()) {
+ std::shared_ptr<GeomDataAPI_Point> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttrIter->first);
+ Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
+ if (anEntity.h == SLVS_E_UNKNOWN) {
+ std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIter++;
+ myAttributeMap.erase(aTmpIter);
+ continue;
+ }
+ if (aPoint) {
+ double aXYZ[3];
+ for (int i = 0; i < 3; i++) {
+ Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
+ aXYZ[i] = aPar.val;
+ }
+ if (fabs(aPoint->x() - aXYZ[0]) > tolerance ||
+ fabs(aPoint->y() - aXYZ[1]) > tolerance ||
+ fabs(aPoint->z() - aXYZ[2]) > tolerance)
+ aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
+ } else {
+ // Point in 2D
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
+ if (aPoint2D) {
+ double aXY[2];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
+ aXY[i] = aPar.val;
+ }
+ if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
+ fabs(aPoint2D->y() - aXY[1]) > tolerance)
+ aPoint2D->setValue(aXY[0], aXY[1]);
+ } else {
+ // Scalar value (used for the distance entities)
+ AttributeDoublePtr aScalar =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
+ if (aScalar) {
+ Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
+ if (fabs(aScalar->value() - aPar.val) > tolerance)
+ aScalar->setValue(aPar.val);
+ }
+ }
+ }
+ anAttrIter++;
+ }
+
+ std::map<AttributePtr, Slvs_hParam>::iterator aValIter = myValueMap.begin();
+ for (; aValIter != myValueMap.end(); aValIter++) {
+ AttributeDoublePtr aScalar =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
+ if (aScalar) {
+ Slvs_Param aPar = myStorage->getParameter(anAttrIter->second);
+ aScalar->setValue(aPar.val);
+ }
+ }
+}
+
+Slvs_hEntity SketchSolver_Constraint::getId(FeaturePtr theFeature) const
+{
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIter = myFeatureMap.find(theFeature);
+ if (aFIter == myFeatureMap.end())
+ return SLVS_E_UNKNOWN;
+ //// check the Feature is really in the storage
+ //Slvs_Entity anEntity = myStorage->getEntity(aFIter->second);
+ //if (anEntity.h == SLVS_E_UNKNOWN) {
+ // // rebuild feature
+ // int aType;
+ // anEntity.h = const_cast<SketchSolver_Constraint*>(this)->changeEntity(aFIter->first, aType);
+ // const_cast<SketchSolver_Constraint*>(this)->myFeatureMap[theFeature] = anEntity.h;
+ //}
+ //return anEntity.h;
+ return aFIter->second;
+}
+
+Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const
+{
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.find(theAttribute);
+ if (anAttrIter == myAttributeMap.end())
+ return SLVS_E_UNKNOWN;
+ return anAttrIter->second;
+}
+
+bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute)
+{
+ if (theAttribute->isInitialized())
+ return true;
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return false;
}
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttribute, int& theType)
-////{
-//// // Convert the object of the attribute to the feature
-//// FeaturePtr aFeature;
-//// if (theAttribute->isObject() && theAttribute->object()) {
-//// ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
-//// theAttribute->object());
-//// if (!aRC) {
-//// myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-//// return SLVS_E_UNKNOWN;
-//// }
-//// std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
-//// aFeature = aDoc->feature(aRC);
-////
-//// return changeEntity(aFeature, theType);
-//// }
-////
-//// return changeEntity(theAttribute->attr(), theType);
-////}
-////
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
-////{
-//// Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-//// if (!theEntity || !isInitialized(theEntity)) {
-//// myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-//// return SLVS_E_UNKNOWN;
-//// }
-////
-//// // If the entity is already in the group, try to find it
-//// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
-//// myAttributeMap.find(theEntity);
-//// Slvs_Entity aCurrentEntity;
-//// aCurrentEntity.h = SLVS_E_UNKNOWN;
-//// if (anEntIter != myAttributeMap.end())
-//// aCurrentEntity = myStorage->getEntity(anEntIter->second);
-//// else {
-//// aResult = myGroup->getAttributeId(theEntity);
-//// if (aResult != SLVS_E_UNKNOWN) {
-//// Slvs_Entity anEnt = myStorage->getEntity(aResult);
-//// theType = anEnt.type;
-//// myAttributeMap[theEntity] = aResult;
-//// return aResult;
-//// }
-//// }
-////
-//// Slvs_hGroup aGroupID = myGroup->getId();
-//// // do not update entity from another group
-//// if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
-//// return aCurrentEntity.h;
-////
-//// // Point in 3D
-//// std::shared_ptr<GeomDataAPI_Point> aPoint =
-//// std::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
-//// if (aPoint) {
-//// double aXYZ[3] = {aPoint->x(), aPoint->y(), aPoint->z()};
-//// Slvs_hParam aParams[3];
-//// for (int i = 0; i < 3; i++) {
-//// Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-//// myStorage->getParameter(aCurrentEntity.param[i]) :
-//// Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-//// aPar.val = aXYZ[i];
-//// aParams[i] = myStorage->addParameter(aPar);
-//// }
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-//// aCurrentEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, aGroupID, aParams[0], aParams[1], aParams[2]);
-//// else { // update entity data
-//// for (int i = 0; i < 3; i++)
-//// aCurrentEntity.param[i] = aParams[i];
-//// }
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// } else {
-//// // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
-//// Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
-//// if (aWorkplaneID == SLVS_E_UNKNOWN)
-//// return SLVS_E_UNKNOWN;
-////
-//// // Point in 2D
-//// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
-//// if (aPoint2D) {
-//// double aXY[2] = {aPoint2D->x(), aPoint2D->y()};
-//// Slvs_hParam aParams[2];
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-//// myStorage->getParameter(aCurrentEntity.param[i]) :
-//// Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-//// aPar.val = aXY[i];
-//// aParams[i] = myStorage->addParameter(aPar);
-//// }
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-//// aCurrentEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aParams[0], aParams[1]);
-//// else { // update entity data
-//// for (int i = 0; i < 2; i++)
-//// aCurrentEntity.param[i] = aParams[i];
-//// }
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// } else {
-//// // Scalar value (used for the distance entities)
-//// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
-//// if (aScalar) {
-//// Slvs_Param aParam = aCurrentEntity.h != SLVS_E_UNKNOWN ?
-//// myStorage->getParameter(aCurrentEntity.param[0]) :
-//// Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
-//// aParam.val = aScalar->value();
-//// Slvs_hParam aValue = myStorage->addParameter(aParam);
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-//// aCurrentEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aValue);
-//// else
-//// aCurrentEntity.param[0] = aValue;
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// }
-//// }
-//// }
-////
-//// myAttributeMap[theEntity] = aResult;
-//// theType = aCurrentEntity.type;
-//// return aResult;
-////}
-////
-////Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
-////{
-//// Slvs_hEntity aResult = SLVS_E_UNKNOWN;
-//// if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
-//// return SLVS_E_UNKNOWN;
-//// // If the entity is already in the group, try to find it
-//// std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
-//// Slvs_Entity aCurrentEntity;
-//// aCurrentEntity.h = SLVS_E_UNKNOWN;
-//// if (anEntIter != myFeatureMap.end())
-//// aCurrentEntity = myStorage->getEntity(anEntIter->second);
-//// else {
-//// aResult = myGroup->getFeatureId(theEntity);
-//// if (aResult != SLVS_E_UNKNOWN) {
-//// Slvs_Entity anEnt = myStorage->getEntity(aResult);
-//// theType = anEnt.type;
-//// myFeatureMap[theEntity] = aResult;
-//// return aResult;
-//// }
-//// }
-////
-//// Slvs_hGroup aGroupID = myGroup->getId();
-//// // do not update entity from another group
-//// if (aCurrentEntity.h != SLVS_E_UNKNOWN && aGroupID != aCurrentEntity.group)
-//// return aCurrentEntity.h;
-////
-//// Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
-//// DataPtr aData = theEntity->data();
-////
-//// // SketchPlugin features
-//// const std::string& aFeatureKind = theEntity->getKind();
-//// AttributePtr anAttribute;
-//// int anAttrType;
-//// // Line
-//// if (aFeatureKind == SketchPlugin_Line::ID()) {
-//// anAttribute = aData->attribute(SketchPlugin_Line::START_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-////
-//// anAttribute = aData->attribute(SketchPlugin_Line::END_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
-//// aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
-//// else {
-//// aCurrentEntity.point[0] = aStart;
-//// aCurrentEntity.point[1] = aEnd;
-//// }
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// }
-//// // Circle
-//// else if (aFeatureKind == SketchPlugin_Circle::ID()) {
-//// anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-////
-//// anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-//// Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-//// aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-//// aCenter, aWorkplane.normal, aRadius);
-//// } else {
-//// aCurrentEntity.point[0] = aCenter;
-//// aCurrentEntity.distance = aRadius;
-//// }
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// }
-//// // Arc
-//// else if (aFeatureKind == SketchPlugin_Arc::ID()) {
-//// anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
-////
-//// anAttribute = aData->attribute(SketchPlugin_Arc::START_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
-////
-//// anAttribute = aData->attribute(SketchPlugin_Arc::END_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
-////
-//// if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
-//// Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
-//// aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
-//// aWorkplane.normal, aCenter, aStart, aEnd);
-//// } else {
-//// aCurrentEntity.point[0] = aCenter;
-//// aCurrentEntity.point[1] = aStart;
-//// aCurrentEntity.point[2] = aEnd;
-//// }
-//// aResult = myStorage->addEntity(aCurrentEntity);
-//// }
-//// // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
-//// else if (aFeatureKind == SketchPlugin_Point::ID()) {
-//// anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID());
-//// if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN;
-//// // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
-//// aResult = changeEntity(anAttribute, anAttrType);
-//// aCurrentEntity.type = SLVS_E_POINT_IN_3D;
-//// }
-////
-//// if (aResult != SLVS_E_UNKNOWN) {
-//// myFeatureMap[theEntity] = aResult;
-//// theType = aCurrentEntity.type;
-//// }
-//// return aResult;
-////}
-////
-////bool SketchSolver_Constraint::hasConstraint(ConstraintPtr theConstraint) const
-////{
-//// std::list<ConstraintPtr>::const_iterator anIt = myConstraints.begin();
-//// for (; anIt != myConstraints.end(); ++anIt)
-//// if (*anIt == theConstraint)
-//// return true;
-//// return false;
-////}
-////
-////void SketchSolver_Constraint::refresh()
-////{
-//// cleanErrorMsg();
-//// std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
-//// while (anAttrIter != myAttributeMap.end()) {
-//// std::shared_ptr<GeomDataAPI_Point> aPoint =
-//// std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttrIter->first);
-//// Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
-//// if (anEntity.h == SLVS_E_UNKNOWN) {
-//// std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIter++;
-//// myAttributeMap.erase(aTmpIter);
-//// continue;
-//// }
-//// if (aPoint) {
-//// double aXYZ[3];
-//// for (int i = 0; i < 3; i++) {
-//// Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
-//// aXYZ[i] = aPar.val;
-//// }
-//// if (fabs(aPoint->x() - aXYZ[0]) > tolerance ||
-//// fabs(aPoint->y() - aXYZ[1]) > tolerance ||
-//// fabs(aPoint->z() - aXYZ[2]) > tolerance)
-//// aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
-//// } else {
-//// // Point in 2D
-//// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
-//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
-//// if (aPoint2D) {
-//// double aXY[2];
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
-//// aXY[i] = aPar.val;
-//// }
-//// if (fabs(aPoint2D->x() - aXY[0]) > tolerance ||
-//// fabs(aPoint2D->y() - aXY[1]) > tolerance)
-//// aPoint2D->setValue(aXY[0], aXY[1]);
-//// } else {
-//// // Scalar value (used for the distance entities)
-//// AttributeDoublePtr aScalar =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
-//// if (aScalar) {
-//// Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
-//// if (fabs(aScalar->value() - aPar.val) > tolerance)
-//// aScalar->setValue(aPar.val);
-//// }
-//// }
-//// }
-//// anAttrIter++;
-//// }
-////
-//// std::map<AttributePtr, Slvs_hParam>::iterator aValIter = myValueMap.begin();
-//// for (; aValIter != myValueMap.end(); aValIter++) {
-//// AttributeDoublePtr aScalar =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
-//// if (aScalar) {
-//// Slvs_Param aPar = myStorage->getParameter(anAttrIter->second);
-//// aScalar->setValue(aPar.val);
-//// }
-//// }
-////}
-
-////bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute)
-////{
-//// if (theAttribute->isInitialized())
-//// return true;
-//// myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-//// return false;
-////}
-////
-////
-////void SketchSolver_Constraint::calculateMiddlePoint(
-//// const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const
-////{
-//// if (theEntity.type == SLVS_E_LINE_SEGMENT) {
-//// double aStartEndXY[2][2];
-//// Slvs_Entity aPoint;
-//// for (int i = 0; i < 2; i++) {
-//// aPoint = myStorage->getEntity(theEntity.point[i]);
-//// for (int j = 0; j < 2; j++)
-//// aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val;
-//// }
-//// theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0];
-//// theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1];
-//// } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) {
-//// double anArcPoint[3][2];
-//// Slvs_Entity aPoint;
-//// for (int i = 0; i < 3; i++) {
-//// aPoint = myStorage->getEntity(theEntity.point[i]);
-//// for (int j = 0; j < 2; j++)
-//// anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val;
-//// }
-//// // project last point of arc on the arc
-//// double x = anArcPoint[1][0] - anArcPoint[0][0];
-//// double y = anArcPoint[1][1] - anArcPoint[0][1];
-//// double aRad = sqrt(x*x + y*y);
-//// x = anArcPoint[2][0] - anArcPoint[0][0];
-//// y = anArcPoint[2][1] - anArcPoint[0][1];
-//// double aNorm = sqrt(x*x + y*y);
-//// if (aNorm >= tolerance) {
-//// anArcPoint[2][0] = x * aRad / aNorm;
-//// anArcPoint[2][1] = y * aRad / aNorm;
-//// }
-//// anArcPoint[1][0] -= anArcPoint[0][0];
-//// anArcPoint[1][1] -= anArcPoint[0][1];
-//// if (theCoeff < tolerance) {
-//// theX = anArcPoint[0][0] + anArcPoint[1][0];
-//// theY = anArcPoint[0][1] + anArcPoint[1][1];
-//// return;
-//// } else if (1 - theCoeff < tolerance) {
-//// theX = anArcPoint[0][0] + anArcPoint[2][0];
-//// theY = anArcPoint[0][1] + anArcPoint[2][1];
-//// return;
-//// }
-////
-//// std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
-//// std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
-//// double anAngle = aStartDir->angle(aEndDir);
-//// if (anAngle < 0)
-//// anAngle += 2.0 * PI;
-//// anAngle *= theCoeff;
-//// double aCos = cos(anAngle);
-//// double aSin = sin(anAngle);
-//// theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
-//// theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
-//// }
-////}
+
+void SketchSolver_Constraint::calculateMiddlePoint(
+ const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const
+{
+ if (theEntity.type == SLVS_E_LINE_SEGMENT) {
+ double aStartEndXY[2][2];
+ Slvs_Entity aPoint;
+ for (int i = 0; i < 2; i++) {
+ aPoint = myStorage->getEntity(theEntity.point[i]);
+ for (int j = 0; j < 2; j++)
+ aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+ }
+ theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0];
+ theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1];
+ } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) {
+ double anArcPoint[3][2];
+ Slvs_Entity aPoint;
+ for (int i = 0; i < 3; i++) {
+ aPoint = myStorage->getEntity(theEntity.point[i]);
+ for (int j = 0; j < 2; j++)
+ anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val;
+ }
+ // project last point of arc on the arc
+ double x = anArcPoint[1][0] - anArcPoint[0][0];
+ double y = anArcPoint[1][1] - anArcPoint[0][1];
+ double aRad = sqrt(x*x + y*y);
+ x = anArcPoint[2][0] - anArcPoint[0][0];
+ y = anArcPoint[2][1] - anArcPoint[0][1];
+ double aNorm = sqrt(x*x + y*y);
+ if (aNorm >= tolerance) {
+ anArcPoint[2][0] = x * aRad / aNorm;
+ anArcPoint[2][1] = y * aRad / aNorm;
+ }
+ anArcPoint[1][0] -= anArcPoint[0][0];
+ anArcPoint[1][1] -= anArcPoint[0][1];
+ if (theCoeff < tolerance) {
+ theX = anArcPoint[0][0] + anArcPoint[1][0];
+ theY = anArcPoint[0][1] + anArcPoint[1][1];
+ return;
+ } else if (1 - theCoeff < tolerance) {
+ theX = anArcPoint[0][0] + anArcPoint[2][0];
+ theY = anArcPoint[0][1] + anArcPoint[2][1];
+ return;
+ }
+
+ std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+ std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+ double anAngle = aStartDir->angle(aEndDir);
+ if (anAngle < 0)
+ anAngle += 2.0 * PI;
+ anAngle *= theCoeff;
+ double aCos = cos(anAngle);
+ double aSin = sin(anAngle);
+ theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+ theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
+ }
+}
void SketchSolver_Constraint::makeTemporary() const
{
- myStorage->setTemporary(myBaseConstraint);
+ std::vector<Slvs_hConstraint>::const_iterator anIt = mySlvsConstraints.begin();
+ for (; anIt != mySlvsConstraints.end(); anIt++)
+ myStorage->addTemporaryConstraint(*anIt);
}
#include <string>
#include <vector>
+class SketchSolver_Group;
+
/** \class SketchSolver_Constraint
* \ingroup Plugins
- * \brief Converts SketchPlugin constraint to the constraint applicable for solver
+ * \brief Stores mapping between SketchPlugin and SolveSpace constraints data
*/
class SketchSolver_Constraint
{
protected:
/// Default constructor
- SketchSolver_Constraint()
- : myGroupID(GID_UNKNOWN),
- myType(CONSTRAINT_UNKNOWN)
- {}
-
-public:
+ SketchSolver_Constraint() {}
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_Constraint(ConstraintPtr theConstraint);
+ SketchSolver_Constraint(ConstraintPtr theConstraint);
- virtual ~SketchSolver_Constraint() {}
+public:
+ virtual ~SketchSolver_Constraint();
- /// \brief Initializes parameters and start constraint creation
- /// \param theStorage [in] storage where to place new constraint
- /// \param theGroupID [in] group for constraint
- /// \param theSketchID [in] sketch for constraint
- void process(StoragePtr theStorage, const GroupID& theGroupID, const EntityID& theSketchID);
+ /// \brief Initializes the storage of SolveSpace constraints
+ void setStorage(StoragePtr theStorage);
+ /// \brief Initializes group ID for this constraint
+ void setGroup(SketchSolver_Group* theGroup);
/// \brief Update constraint
- SKETCHSOLVER_EXPORT virtual void update();
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
/// \brief Tries to remove constraint
/// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
- SKETCHSOLVER_EXPORT virtual bool remove();
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
- /// \brief Obtain a type of SketchPlugin constraint
- SKETCHSOLVER_EXPORT static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
+ /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
+ virtual void refresh();
/// \brief Returns the type of constraint
-//// virtual SketchSolver_ConstraintType getType() const = 0;
- virtual SketchSolver_ConstraintType getType() const
- { return myType; }
+ virtual int getType() const = 0;
/// \brief The constraint is made temporary
void makeTemporary() const;
- /// \brief Verify the feature or any its attribute is used by constraint
- bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used by constraint
- bool isUsed(AttributePtr theAttribute) const;
+ /// \brief Checks the constraint is used by current object
+ virtual bool hasConstraint(ConstraintPtr theConstraint) const
+ { return theConstraint == myBaseConstraint; }
+
+ /// \brief Return list of SketchPlugin constraints attached to this object
+ virtual std::list<ConstraintPtr> constraints() const;
-//// /// \brief Checks the constraint is used by current object
-//// SKETCHSOLVER_EXPORT virtual bool hasConstraint(ConstraintPtr theConstraint) const;
-////
-//// /// \brief Return list of SketchPlugin constraints attached to this object
-//// virtual const std::list<ConstraintPtr>& constraints() const
-//// { return myConstraints; }
+ /// \brief Return identifier of SolveSpace entity relating to the feature
+ Slvs_hEntity getId(FeaturePtr theFeature) const;
+ /// \brief Return identifier of SolveSpace entity relating to the attribute
+ Slvs_hEntity getId(AttributePtr theAttribute) const;
+
+ /// \brief Adds a feature to constraint and create its analogue in SolveSpace
+ virtual void addFeature(FeaturePtr theFeature);
/// \brief Shows error message
const std::string& error() const
{ return myErrorMsg; }
protected:
- /// \brief Converts SketchPlugin constraint to a list of solver's constraints
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
- /// \brief Generate list of attributes of constraint in order useful for constraints
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
-//// /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
-//// /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
-//// /// \return \c true if some attributes are changed
-//// virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
+ /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
+ /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
+ /// \return \c true if some attributes are changed
+ virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
/// \brief This method is used in derived objects to check consistency of constraint.
/// E.g. the distance between line and point may be signed.
virtual void adjustConstraint()
{}
+ /// \brief Create or change SlveSpace entity according to the given attribute
+ /// \param[in] theAttribute reference to the entity to be changed
+ /// \param[out] theType type of created entity
+ /// \return identifier of created/updated entity
+ Slvs_hEntity changeEntity(AttributeRefAttrPtr theAttribute, int& theType);
+ /// \brief Create or change SlveSpace entity according to the given attribute
+ Slvs_hEntity changeEntity(AttributePtr theAttribute, int& theType);
+ /// \brief Create or change SlveSpace entity according to the given feature
+ Slvs_hEntity changeEntity(FeaturePtr theFeature, int& theType);
+
+ /// \brief Calculate middle point on the specified entity
+ /// \param[in] theEntity arc or line
+ /// \param[in] theCoeff is a value in [0.0, 1.0] which shows the position of the point on the entity (0.0 - start point, 1.0 - end point)
+ /// \param[out] theX X coordinate of middle point
+ /// \param[out] theY Y coordinate of middle point
+ void calculateMiddlePoint(const Slvs_Entity& theEntity, double theCoeff,
+ double& theX, double& theY) const;
+
+ /// \brief Removes the links to unused entities
+ void cleanRemovedEntities();
+
/// \brief Removes last error
void cleanErrorMsg()
{ myErrorMsg.clear(); }
-protected:
- GroupID myGroupID; ///< identifier of the group, the constraint belongs to
- EntityID mySketchID; ///< identifier of the sketch, the constraint belongs to
- ConstraintPtr myBaseConstraint; ///< base SketchPlugin constraint
- StoragePtr myStorage; ///< storage, which contains all information about entities and constraints
- SketchSolver_ConstraintType myType; ///< type of constraint
+private:
+ /// \brief Sets error, if the attribute is not initialized
+ bool isInitialized(AttributePtr theAttribute);
- std::string myErrorMsg; ///< error message
+protected:
+ SketchSolver_Group* myGroup; ///< the group which contains current constraint
+ ConstraintPtr myBaseConstraint; ///< SketchPlugin constraint
+ std::vector<Slvs_hConstraint> mySlvsConstraints; ///< list of indices of SolveSpace constraints, together which equivalent to SketchPlugin constraint
+ std::map<FeaturePtr, Slvs_hEntity> myFeatureMap; ///< map feature to the entity it represents
+ std::map<AttributePtr, Slvs_hEntity> myAttributeMap; ///< map attribute to the corresponding entity
+ std::map<AttributePtr, Slvs_hParam> myValueMap; ///< list of attributes, which represents single value (e.g. distance) used in constraint
+ StoragePtr myStorage; ///< storage, which contains all information about entities and constraints in current group
+
+ std::string myErrorMsg; ///< error message
};
typedef std::shared_ptr<SketchSolver_Constraint> SolverConstraintPtr;
-/////** \class SketchSolver_ConstraintParallel
-//// * \ingroup Plugins
-//// * \brief Convert Parallel constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintParallel : public SketchSolver_Constraint
-////{
-////public:
-//// /// Constructor based on SketchPlugin constraint
-//// SketchSolver_ConstraintParallel(ConstraintPtr theConstraint) :
-//// SketchSolver_Constraint(theConstraint)
-//// {}
-////
-//// virtual int getType() const
-//// { return SLVS_C_PARALLEL; }
-////};
-////
-////
-/////** \class SketchSolver_ConstraintPerpendicular
-//// * \ingroup Plugins
-//// * \brief Convert Perpendicular constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintPerpendicular : public SketchSolver_Constraint
-////{
-////public:
-//// /// Constructor based on SketchPlugin constraint
-//// SketchSolver_ConstraintPerpendicular(ConstraintPtr theConstraint) :
-//// SketchSolver_Constraint(theConstraint)
-//// {}
-////
-//// virtual int getType() const
-//// { return SLVS_C_PERPENDICULAR; }
-////};
-////
-////
-/////** \class SketchSolver_ConstraintHorizontal
-//// * \ingroup Plugins
-//// * \brief Convert Horizontal constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintHorizontal : public SketchSolver_Constraint
-////{
-////public:
-//// /// Constructor based on SketchPlugin constraint
-//// SketchSolver_ConstraintHorizontal(ConstraintPtr theConstraint) :
-//// SketchSolver_Constraint(theConstraint)
-//// {}
-////
-//// virtual int getType() const
-//// { return SLVS_C_HORIZONTAL; }
-////};
-////
-////
-/////** \class SketchSolver_ConstraintVertical
-//// * \ingroup Plugins
-//// * \brief Convert Vertical constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintVertical : public SketchSolver_Constraint
-////{
-////public:
-//// /// Constructor based on SketchPlugin constraint
-//// SketchSolver_ConstraintVertical(ConstraintPtr theConstraint) :
-//// SketchSolver_Constraint(theConstraint)
-//// {}
-////
-//// virtual int getType() const
-//// { return SLVS_C_VERTICAL; }
-////};
-////
-////
-/////** \class SketchSolver_ConstraintRadius
-//// * \ingroup Plugins
-//// * \brief Convert Radius constraint to SolveSpace structure
-//// */
-////class SketchSolver_ConstraintRadius : public SketchSolver_Constraint
-////{
-////public:
-//// /// Constructor based on SketchPlugin constraint
-//// SketchSolver_ConstraintRadius(ConstraintPtr theConstraint) :
-//// SketchSolver_Constraint(theConstraint)
-//// {}
-////
-//// virtual int getType() const
-//// { return SLVS_C_DIAMETER; }
-////
-//// virtual void adjustConstraint()
-//// {
-//// AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-//// myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
-//// Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
-//// aConstraint.valA = 2.0 * aValueAttr->value();
-//// myStorage->updateConstraint(aConstraint);
-//// }
-////};
+/** \class SketchSolver_ConstraintParallel
+ * \ingroup Plugins
+ * \brief Convert Parallel constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintParallel : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintParallel(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_PARALLEL; }
+};
+
+
+/** \class SketchSolver_ConstraintPerpendicular
+ * \ingroup Plugins
+ * \brief Convert Perpendicular constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintPerpendicular : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintPerpendicular(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_PERPENDICULAR; }
+};
+
+
+/** \class SketchSolver_ConstraintHorizontal
+ * \ingroup Plugins
+ * \brief Convert Horizontal constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintHorizontal : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintHorizontal(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_HORIZONTAL; }
+};
+
+
+/** \class SketchSolver_ConstraintVertical
+ * \ingroup Plugins
+ * \brief Convert Vertical constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintVertical : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintVertical(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_VERTICAL; }
+};
+
+
+/** \class SketchSolver_ConstraintRadius
+ * \ingroup Plugins
+ * \brief Convert Radius constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintRadius : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintRadius(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_DIAMETER; }
+
+ virtual void adjustConstraint()
+ {
+ AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
+ Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+ aConstraint.valA = 2.0 * aValueAttr->value();
+ myStorage->updateConstraint(aConstraint);
+ }
+};
#endif
#include <SketchSolver_ConstraintAngle.h>
-#include <SketchSolver_Manager.h>
#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Lin2d.h>
#include <cmath>
void SketchSolver_ConstraintAngle::getAttributes(
- double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+ double& theValue, std::vector<Slvs_hEntity>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
void SketchSolver_ConstraintAngle::adjustConstraint()
{
static const double aTol = 1000. * tolerance;
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- if (fabs(myAngle - aConstraint->value()) < aTol)
- return;
- myAngle = aConstraint->value();
-
-//// Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+ Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
bool isFixed[2][2];
std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
- const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
- for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
- const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
- for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt) {
- isFixed[i][j] = ((*aLPIt)->group() != myGroupID);
- aPoints[i][j] = aBuilder->point(*aLPIt);
+ Slvs_hConstraint aFixedConstraint;
+ Slvs_hEntity anEnt[2] = {aConstraint.entityA, aConstraint.entityB};
+ for (int i = 0; i < 2; i++) {
+ const Slvs_Entity& aLine = myStorage->getEntity(anEnt[i]);
+ double aCoef = -1.0;
+ for (int j = 0; j < 2; j++, aCoef += 2.0) {
+ const Slvs_Entity& aPoint = myStorage->getEntity(aLine.point[j]);
+ double aCoords[2];
+ for (int k = 0; k < 2; k++)
+ aCoords[k] = myStorage->getParameter(aPoint.param[k]).val;
+ isFixed[i][j] = myStorage->isPointFixed(aPoint.h, aFixedConstraint, true);
+ aPoints[i][j] = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCoords[0], aCoords[1]));
}
}
- if (isFixed[0][0] && isFixed[0][1] && isFixed[1][0] && isFixed[1][1])
- return; // both lines are fixed => no need to update them
-
std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
}
}
-//// aConstraint.other = false;
-//// for (int i = 0; i < 2; i++)
-//// if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
-//// aConstraint.other = !aConstraint.other;
-//// myStorage->updateConstraint(aConstraint);
-////
-//// bool isChanged = fabs(myAngle - aConstraint.valA) > aTol;
-//// // myAngle should be updated even if the angle of constraint is changed too little
-//// myAngle = aConstraint.valA;
-//// if (!isChanged)
-//// return; // the angle was not changed, no need to recalculate positions of lines
+ aConstraint.other = false;
+ for (int i = 0; i < 2; i++)
+ if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
+ aConstraint.other = !aConstraint.other;
+ myStorage->updateConstraint(aConstraint);
+
+ bool isChanged = fabs(myAngle - aConstraint.valA) > aTol;
+ // myAngle should be updated even if the angle of constraint is changed too little
+ myAngle = aConstraint.valA;
+ if (!isChanged)
+ return; // the angle was not changed, no need to recalculate positions of lines
+
+ if (isFixed[0][0] && isFixed[0][1] && isFixed[1][0] && isFixed[1][1])
+ return; // both lines are fixed => no need to update them
// Recalculate positions of lines to avoid conflicting constraints
// while changing angle value several times
}
// Update positions of points
- std::list<EntityWrapperPtr>::const_iterator anUpdLine = aConstrLines.begin();
- if (aLineToUpd > 0) ++anUpdLine;
- const std::list<EntityWrapperPtr>& anUpdPoints = (*anUpdLine)->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aPIt = anUpdPoints.begin();
- for (int i = 0; aPIt != anUpdPoints.end(); ++aPIt, ++i) {
- double aCoord[2] = {aNewPoints[i]->x(), aNewPoints[i]->y()};
- const std::list<ParameterWrapperPtr>& aParams = (*aPIt)->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aParIt = aParams.begin();
- for (int j = 0; aParIt != aParams.end(); ++j, ++aParIt)
- (*aParIt)->setValue(aCoord[j]);
+ const Slvs_Entity& anUpdLine = myStorage->getEntity(anEnt[aLineToUpd]);
+ Slvs_Param aParam;
+ for (int i = 0; i < 2; i++) {
+ const Slvs_Entity& aPoint = myStorage->getEntity(anUpdLine.point[i]);
+ aParam = myStorage->getParameter(aPoint.param[0]);
+ aParam.val = aNewPoints[i]->x();
+ myStorage->updateParameter(aParam);
+ aParam = myStorage->getParameter(aPoint.param[1]);
+ aParam.val = aNewPoints[i]->y();
+ myStorage->updateParameter(aParam);
}
-
- aBuilder->adjustConstraint(aConstraint);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
}
myAngle(0.0)
{}
+ virtual int getType() const
+ { return SLVS_C_ANGLE; }
+
/// \brief This method is used in derived objects to check consistence of constraint.
virtual void adjustConstraint();
protected:
- /// \brief Generate list of attributes of constraint in order useful for constraints
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
private:
double myAngle;
#include <SketchSolver_ConstraintCoincidence.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
+#include <SketchSolver_Group.h>
-////#include <SketchPlugin_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////
-////#include <map>
+#include <SketchPlugin_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <map>
void SketchSolver_ConstraintCoincidence::getAttributes(
double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+ std::vector<Slvs_hEntity>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
- if (!myErrorMsg.empty() || !theAttributes[0]) {
- theAttributes.clear();
+ if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
return;
- }
- if (theAttributes[1]) {
- myType = CONSTRAINT_PT_PT_COINCIDENT;
- // Set the slave (second) point the same as master (first) point.
- // This will allow to skip adding point-point coincidence to the set of constraints
- // and give us speed-up in solving the set of equations
- myStorage->addCoincidentPoints(theAttributes[0], theAttributes[1]);
+ if (theAttributes[1] != SLVS_E_UNKNOWN) {
+ myType = SLVS_C_POINTS_COINCIDENT;
+
+ // set coordinates of slave (second) point equal to the master (first) point
+ Slvs_Entity aFirst = myStorage->getEntity(theAttributes[0]);
+ Slvs_Entity aSecond = myStorage->getEntity(theAttributes[1]);
+ for (int i = 0; i < 4; i++)
+ if (aFirst.param[i] != SLVS_E_UNKNOWN && aSecond.param[i] != SLVS_E_UNKNOWN) {
+ Slvs_Param aPar1 = myStorage->getParameter(aFirst.param[i]);
+ Slvs_Param aPar2 = myStorage->getParameter(aSecond.param[i]);
+ aPar2.val = aPar1.val;
+ myStorage->updateParameter(aPar2);
+ }
}
- else if (theAttributes[2]) {
+ else if (theAttributes[2] != SLVS_E_UNKNOWN) {
// check the type of entity (line or circle)
- SketchSolver_EntityType anEntType = theAttributes[2]->type();
- if (anEntType == ENTITY_LINE)
- myType = CONSTRAINT_PT_ON_LINE;
- else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC)
- myType = CONSTRAINT_PT_ON_CIRCLE;
+ Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
+ if (anEnt.type == SLVS_E_LINE_SEGMENT)
+ myType = SLVS_C_PT_ON_LINE;
+ else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
+ myType = SLVS_C_PT_ON_CIRCLE;
else
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
} else
}
-static bool isBase(const std::list<ConstraintWrapperPtr>& theConstraints, AttributePtr theAttribute)
+bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
{
- AttributePtr anAttribute = theAttribute;
- FeaturePtr aFeature;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- else
- anAttribute = aRefAttr->attr();
+ if (myBaseConstraint == theConstraint)
+ return true;
+ return myExtraCoincidence.find(theConstraint) != myExtraCoincidence.end();
+}
+
+std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
+{
+ std::list<ConstraintPtr> aConstraints;
+ aConstraints.push_back(myBaseConstraint);
+ std::map<ConstraintPtr, Slvs_hConstraint>::const_iterator anIt = myExtraCoincidence.begin();
+ for (; anIt != myExtraCoincidence.end(); anIt++)
+ aConstraints.push_back(anIt->first);
+ return aConstraints;
+}
+
+bool SketchSolver_ConstraintCoincidence::isCoincide(
+ std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
+{
+ std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
+ for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
+ if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
+ return true;
+ return false;
+}
+
+void SketchSolver_ConstraintCoincidence::attach(
+ std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
+{
+ cleanErrorMsg();
+ // Remove constraints from theConstraint
+ std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
+ for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
+ theConstraint->myStorage->removeConstraint(*aCIter);
+
+ if (myStorage == theConstraint->myStorage) {
+ // Clean removed items
+ std::set<Slvs_hParam> aRemParams;
+ std::set<Slvs_hEntity> aRemEnts;
+ std::set<Slvs_hConstraint> aRemConstr;
+ theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
+
+ if (!aRemEnts.empty()) {
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
+ while (aFeatIt != theConstraint->myFeatureMap.end()) {
+ if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
+ // remove feature
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
+ theConstraint->myFeatureMap.erase(aRemoveIt);
+ } else
+ ++aFeatIt;
+ }
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
+ while (anAttrIt != theConstraint->myAttributeMap.end()) {
+ if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
+ // remove attribute
+ std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
+ theConstraint->myAttributeMap.erase(aRemoveIt);
+ } else
+ ++anAttrIt;
+ }
+ }
}
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = theConstraints.begin();
- for (; aCIt != theConstraints.end(); ++aCIt) {
- std::list<EntityWrapperPtr> aSubs = (*aCIt)->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++aSIt)
- if ((aFeature && (*aSIt)->isBase(aFeature)) ||
- (!aFeature && (*aSIt)->isBase(anAttribute)))
- return true;
+ // Copy data.
+ addConstraint(theConstraint->myBaseConstraint);
+ std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
+ theConstraint->myExtraCoincidence.begin();
+ for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
+ addConstraint(aConstrIter->first);
+ // Clear the lists to not remove the entities on destruction
+ theConstraint->mySlvsConstraints.clear();
+ theConstraint->myFeatureMap.clear();
+ theConstraint->myAttributeMap.clear();
+}
+
+Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
+ Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
+{
+ if (thePoint1 == thePoint2)
+ return SLVS_E_UNKNOWN;
+
+ bool hasDuplicated = myStorage->hasDuplicatedConstraint();
+ Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
+ if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
+ // the duplicated constraint appears
+ myStorage->removeConstraint(aNewID);
+ return SLVS_E_UNKNOWN;
+ }
+ mySlvsConstraints.push_back(aNewID);
+ return aNewID;
+}
+
+Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
+ Slvs_hEntity thePoint, Slvs_hEntity theEntity)
+{
+ // Check the point is not coincident with boundaries of the entity
+ Slvs_Entity anEnt = myStorage->getEntity(theEntity);
+ int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
+ for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
+ if (anEnt.point[aPos] == thePoint ||
+ myStorage->isCoincident(anEnt.point[aPos], thePoint))
+ return SLVS_E_UNKNOWN;
+
+ bool hasDuplicated = myStorage->hasDuplicatedConstraint();
+ Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+ Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
+ SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
+ Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
+ theEntity, SLVS_E_UNKNOWN);
+ Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
+ if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
+ // the duplicated constraint appears
+ myStorage->removeConstraint(aNewID);
+ return SLVS_E_UNKNOWN;
+ }
+ mySlvsConstraints.push_back(aNewID);
+ return aNewID;
+}
+
+void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
+{
+ if (mySlvsConstraints.empty()) {
+ // This constraint is empty, rebuild it from scratch
+ myBaseConstraint = theConstraint;
+ process();
+ return;
+ }
+
+ std::list<AttributePtr> anAttrList =
+ theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anIter = anAttrList.begin();
+ std::vector<Slvs_hEntity> aPoints;
+ Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
+ int anEntType;
+ for (; anIter != anAttrList.end(); anIter++) {
+ Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (!aRefAttr)
+ continue;
+
+ AttributePtr aPointAttr;
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound =
+ myFeatureMap.find(aFeature);
+ if (aFeatFound != myFeatureMap.end())
+ anEntity = aFeatFound->second;
+ else {
+ anEntity = myGroup->getFeatureId(aFeature);
+ if (anEntity == SLVS_E_UNKNOWN)
+ anEntity = changeEntity(aFeature, anEntType);
+ else {
+ myFeatureMap[aFeature] = anEntity;
+ // Obtain relations between attributes of the feature and SolveSpace entities
+ std::list<AttributePtr> anAttrList =
+ aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+ for (; anIt != anAttrList.end(); ++anIt) {
+ Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
+ if (anAttrID != SLVS_E_UNKNOWN)
+ myAttributeMap[*anIt] = anAttrID;
+ }
+ }
+ }
+ // If the feature is a point, add it to the list of coincident points
+ if (aFeature->getKind() == SketchPlugin_Point::ID()) {
+ aPointID = anEntity;
+ anEntity = SLVS_E_UNKNOWN;
+ aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
+ }
+ } else {
+ aPointAttr = aRefAttr->attr();
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
+ myAttributeMap.find(aPointAttr);
+ if (anAttrFound != myAttributeMap.end())
+ aPointID = anAttrFound->second;
+ else {
+ aPointID = myGroup->getAttributeId(aPointAttr);
+ if (aPointID == SLVS_E_UNKNOWN)
+ aPointID = changeEntity(aPointAttr, anEntType);
+ }
+ }
+
+ if (aPointAttr) { // the point is found
+ aPoints.push_back(aPointID);
+ myCoincidentPoints.insert(aPointAttr);
+ myAttributeMap[aPointAttr] = aPointID;
+ }
+ }
+
+ Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
+ if (anEntity != SLVS_E_UNKNOWN)
+ aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
+ else { // coincidence between two points
+ Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
+ std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
+ for (; aPtIter != aPoints.end(); aPtIter++) {
+ Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
+ if (aC != SLVS_E_UNKNOWN)
+ aNewConstr = aC;
+ }
+ }
+ myExtraCoincidence[theConstraint] = aNewConstr;
+}
+
+void SketchSolver_ConstraintCoincidence::process()
+{
+ SketchSolver_Constraint::process();
+
+ // Fill the list of coincident points
+ std::list<AttributePtr> anAttrList =
+ myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anIt = anAttrList.begin();
+ for (; anIt != anAttrList.end(); anIt++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
+ if (!aRefAttr || aRefAttr->isObject())
+ continue;
+ myCoincidentPoints.insert(aRefAttr->attr());
}
- return false;
}
-////bool SketchSolver_ConstraintCoincidence::isCoincide(
-//// std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
-////{
-//// std::list<ConstraintPtr>::const_iterator anOtherCIt = theConstraint->myConstraints.begin();
-//// for (; anOtherCIt != theConstraint->myConstraints.end(); ++anOtherCIt) {
-//// std::list<ConstraintPtr>::const_iterator aCIt = myConstraints.begin();
-//// for (; aCIt != myConstraints.end(); ++aCIt) {
-//// std::list<ConstraintWrapperPtr> aWrappers = myStorage->constraint(*aCIt);
-//// if (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_A())) ||
-//// (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_B()))))
-//// return true;
-//// }
-//// }
-//// return false;
-////}
-////
-////void SketchSolver_ConstraintCoincidence::attach(
-//// std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
-////{
-//// cleanErrorMsg();
-//// ConstraintWrapperPtr aFirstConstraint = myStorage->constraint(myConstraints.front()).front();
-//// EntityWrapperPtr aMasterPoint = aFirstConstraint->entities().front();
-////
-//// // Set points from theConstraint equal to master point
-//// const std::list<ConstraintPtr>& anOtherConstraints = theConstraint->myConstraints;
-//// std::list<ConstraintPtr>::const_iterator anOtherCIt = anOtherConstraints.begin();
-//// bool isFirstUpd = false;
-//// for (; anOtherCIt != anOtherConstraints.end(); ++anOtherCIt) {
-//// std::list<ConstraintWrapperPtr> aSolverConstraints = myStorage->constraint(*anOtherCIt);
-//// std::list<ConstraintWrapperPtr>::iterator aSCIt = aSolverConstraints.begin();
-//// // First point in each constraint is the same (master point of theConstraint),
-//// // it should be updated only once.
-//// if (!isFirstUpd) {
-//// EntityWrapperPtr anOtherMasterPoint = (*aSCIt)->entities().front();
-//// myStorage->addCoincidentPoints(aMasterPoint, anOtherMasterPoint);
-//// isFirstUpd = true;
-//// }
-//// // Update all slave points
-//// for (; aSCIt != aSolverConstraints.end(); ++aSCIt) {
-//// std::list<EntityWrapperPtr> aSubs = (*aSCIt)->entities();
-//// std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
-//// for (++aSubIt; aSubIt != aSubs.end(); ++aSubIt)
-//// myStorage->addCoincidentPoints(aMasterPoint, *aSubIt);
-//// }
-//// // add constraint to myConstraints
-//// myConstraints.push_back(*anOtherCIt);
-//// }
-////
-//// // Remove constraints from theConstraint
-//// std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
-//// for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
-//// theConstraint->myStorage->removeConstraint(*aCIter);
-////
-//// if (myStorage == theConstraint->myStorage) {
-//// // Clean removed items
-//// std::set<Slvs_hParam> aRemParams;
-//// std::set<Slvs_hEntity> aRemEnts;
-//// std::set<Slvs_hConstraint> aRemConstr;
-//// theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
-////
-//// if (!aRemEnts.empty()) {
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
-//// while (aFeatIt != theConstraint->myFeatureMap.end()) {
-//// if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
-//// // remove feature
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
-//// theConstraint->myFeatureMap.erase(aRemoveIt);
-//// } else
-//// ++aFeatIt;
-//// }
-//// std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
-//// while (anAttrIt != theConstraint->myAttributeMap.end()) {
-//// if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
-//// // remove attribute
-//// std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
-//// theConstraint->myAttributeMap.erase(aRemoveIt);
-//// } else
-//// ++anAttrIt;
-//// }
-//// }
-//// }
-////
-//// // Copy data.
-//// addConstraint(theConstraint->myBaseConstraint);
-//// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
-//// theConstraint->myExtraCoincidence.begin();
-//// for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
-//// addConstraint(aConstrIter->first);
-//// // Clear the lists to not remove the entities on destruction
-//// theConstraint->mySlvsConstraints.clear();
-//// theConstraint->myFeatureMap.clear();
-//// theConstraint->myAttributeMap.clear();
-////}
+bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (mySlvsConstraints.empty())
+ return true;
+ ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+ int aPos = -1; // position of constraint in the list (-1 for base constraint)
+ std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
+ if (aConstraint != myBaseConstraint) {
+ anExtraIt = myExtraCoincidence.find(aConstraint);
+ if (anExtraIt == myExtraCoincidence.end())
+ return false; // there is no constraint, which is specified to remove
+ else {
+ bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
+ if (!isEmpty) {
+ isEmpty = true;
+ for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
+ if (mySlvsConstraints[aPos] == anExtraIt->second) {
+ isEmpty = false;
+ break;
+ }
+ aPos -= 1;
+ }
+ myExtraCoincidence.erase(anExtraIt);
+ if (isEmpty)
+ return false;
+ }
+ }
-////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
-//// Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
-////{
-//// if (thePoint1 == thePoint2)
-//// return SLVS_E_UNKNOWN;
-////
-//// bool hasDuplicated = myStorage->hasDuplicatedConstraint();
-//// Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-//// SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
-//// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
-//// if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
-//// // the duplicated constraint appears
-//// myStorage->removeConstraint(aNewID);
-//// return SLVS_E_UNKNOWN;
-//// }
-//// mySlvsConstraints.push_back(aNewID);
-//// return aNewID;
-////}
-////
-////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
-//// Slvs_hEntity thePoint, Slvs_hEntity theEntity)
-////{
-//// // Check the point is not coincident with boundaries of the entity
-//// Slvs_Entity anEnt = myStorage->getEntity(theEntity);
-//// int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
-//// for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
-//// if (anEnt.point[aPos] == thePoint ||
-//// myStorage->isCoincident(anEnt.point[aPos], thePoint))
-//// return SLVS_E_UNKNOWN;
-////
-//// bool hasDuplicated = myStorage->hasDuplicatedConstraint();
-//// Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
-//// Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
-//// SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
-//// Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-//// aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
-//// theEntity, SLVS_E_UNKNOWN);
-//// Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
-//// if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
-//// // the duplicated constraint appears
-//// myStorage->removeConstraint(aNewID);
-//// return SLVS_E_UNKNOWN;
-//// }
-//// mySlvsConstraints.push_back(aNewID);
-//// return aNewID;
-////}
-////
-////void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
-////{
-//// if (mySlvsConstraints.empty()) {
-//// // This constraint is empty, rebuild it from scratch
-//// myBaseConstraint = theConstraint;
-//// process();
-//// return;
-//// }
-////
-//// std::list<AttributePtr> anAttrList =
-//// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-//// std::list<AttributePtr>::iterator anIter = anAttrList.begin();
-//// std::vector<Slvs_hEntity> aPoints;
-//// Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
-//// int anEntType;
-//// for (; anIter != anAttrList.end(); anIter++) {
-//// Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
-//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
-//// if (!aRefAttr)
-//// continue;
-////
-//// AttributePtr aPointAttr;
-//// if (aRefAttr->isObject()) {
-//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-//// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound =
-//// myFeatureMap.find(aFeature);
-//// if (aFeatFound != myFeatureMap.end())
-//// anEntity = aFeatFound->second;
-//// else {
-//// anEntity = myGroup->getFeatureId(aFeature);
-//// if (anEntity == SLVS_E_UNKNOWN)
-//// anEntity = changeEntity(aFeature, anEntType);
-//// else {
-//// myFeatureMap[aFeature] = anEntity;
-//// // Obtain relations between attributes of the feature and SolveSpace entities
-//// std::list<AttributePtr> anAttrList =
-//// aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-//// std::list<AttributePtr>::iterator anIt = anAttrList.begin();
-//// for (; anIt != anAttrList.end(); ++anIt) {
-//// Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
-//// if (anAttrID != SLVS_E_UNKNOWN)
-//// myAttributeMap[*anIt] = anAttrID;
-//// }
-//// }
-//// }
-//// // If the feature is a point, add it to the list of coincident points
-//// if (aFeature->getKind() == SketchPlugin_Point::ID()) {
-//// aPointID = anEntity;
-//// anEntity = SLVS_E_UNKNOWN;
-//// aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
-//// }
-//// } else {
-//// aPointAttr = aRefAttr->attr();
-//// std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
-//// myAttributeMap.find(aPointAttr);
-//// if (anAttrFound != myAttributeMap.end())
-//// aPointID = anAttrFound->second;
-//// else {
-//// aPointID = myGroup->getAttributeId(aPointAttr);
-//// if (aPointID == SLVS_E_UNKNOWN)
-//// aPointID = changeEntity(aPointAttr, anEntType);
-//// }
-//// }
-////
-//// if (aPointAttr) { // the point is found
-//// aPoints.push_back(aPointID);
-//// myCoincidentPoints.insert(aPointAttr);
-//// myAttributeMap[aPointAttr] = aPointID;
-//// }
-//// }
-////
-//// Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
-//// if (anEntity != SLVS_E_UNKNOWN)
-//// aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
-//// else { // coincidence between two points
-//// Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
-//// std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
-//// for (; aPtIter != aPoints.end(); aPtIter++) {
-//// Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
-//// if (aC != SLVS_E_UNKNOWN)
-//// aNewConstr = aC;
-//// }
-//// }
-//// myExtraCoincidence[theConstraint] = aNewConstr;
-////}
+ bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
+ mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
+ if (aPos < 0 && !myExtraCoincidence.empty()) {
+ anExtraIt = myExtraCoincidence.begin();
+ // Remove invalid constraints
+ while (anExtraIt != myExtraCoincidence.end()) {
+ if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
+ std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+ if (aTempIt->first != SLVS_E_UNKNOWN) {
+ myStorage->removeConstraint(aTempIt->second);
+ std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
+ for (; anIt != mySlvsConstraints.end(); anIt++)
+ if (*anIt == aTempIt->second) {
+ mySlvsConstraints.erase(anIt);
+ break;
+ }
+ }
+ myExtraCoincidence.erase(aTempIt);
+ continue;
+ }
+ anExtraIt++;
+ }
+ // Find first non-extra conststraint
+ anExtraIt = myExtraCoincidence.begin();
+ while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
+ anExtraIt++;
+ if (anExtraIt != myExtraCoincidence.end()) {
+ // Need to specify another base coincidence constraint
+ myBaseConstraint = anExtraIt->first;
+ myExtraCoincidence.erase(anExtraIt);
+ if (mySlvsConstraints.empty()) {
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
+ for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
+ Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
+ aConstr.ptA = aBase.ptA;
+ myStorage->updateConstraint(aConstr);
+ }
+ }
+ }
+ }
+ // Clear removed attributes
+ std::set<Slvs_hParam> aParamRemoved;
+ std::set<Slvs_hEntity> anEntRemoved;
+ std::set<Slvs_hConstraint> aConstrRemoved;
+ myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
+ while (anAttrIter != myAttributeMap.end()) {
+ if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
+ std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
+ myCoincidentPoints.erase(aTempIt->first);
+ myAttributeMap.erase(aTempIt);
+ continue;
+ }
+ anAttrIter++;
+ }
-////bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
-////{
-//// cleanErrorMsg();
-//// if (mySlvsConstraints.empty())
-//// return true;
-//// ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-//// int aPos = -1; // position of constraint in the list (-1 for base constraint)
-//// std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
-//// if (aConstraint != myBaseConstraint) {
-//// anExtraIt = myExtraCoincidence.find(aConstraint);
-//// if (anExtraIt == myExtraCoincidence.end())
-//// return false; // there is no constraint, which is specified to remove
-//// else {
-//// bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
-//// if (!isEmpty) {
-//// isEmpty = true;
-//// for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
-//// if (mySlvsConstraints[aPos] == anExtraIt->second) {
-//// isEmpty = false;
-//// break;
-//// }
-//// aPos -= 1;
-//// }
-//// myExtraCoincidence.erase(anExtraIt);
-//// if (isEmpty)
-//// return false;
-//// }
-//// }
-////
-//// bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
-//// mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
-//// if (aPos < 0 && !myExtraCoincidence.empty()) {
-//// anExtraIt = myExtraCoincidence.begin();
-//// // Remove invalid constraints
-//// while (anExtraIt != myExtraCoincidence.end()) {
-//// if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
-//// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-//// if (aTempIt->first != SLVS_E_UNKNOWN) {
-//// myStorage->removeConstraint(aTempIt->second);
-//// std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
-//// for (; anIt != mySlvsConstraints.end(); anIt++)
-//// if (*anIt == aTempIt->second) {
-//// mySlvsConstraints.erase(anIt);
-//// break;
-//// }
-//// }
-//// myExtraCoincidence.erase(aTempIt);
-//// continue;
-//// }
-//// anExtraIt++;
-//// }
-//// // Find first non-extra conststraint
-//// anExtraIt = myExtraCoincidence.begin();
-//// while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
-//// anExtraIt++;
-//// if (anExtraIt != myExtraCoincidence.end()) {
-//// // Need to specify another base coincidence constraint
-//// myBaseConstraint = anExtraIt->first;
-//// myExtraCoincidence.erase(anExtraIt);
-//// if (mySlvsConstraints.empty()) {
-//// std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
-//// Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
-//// for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
-//// Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
-//// aConstr.ptA = aBase.ptA;
-//// myStorage->updateConstraint(aConstr);
-//// }
-//// }
-//// }
-//// }
-//// // Clear removed attributes
-//// std::set<Slvs_hParam> aParamRemoved;
-//// std::set<Slvs_hEntity> anEntRemoved;
-//// std::set<Slvs_hConstraint> aConstrRemoved;
-//// myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
-//// std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
-//// while (anAttrIter != myAttributeMap.end()) {
-//// if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
-//// std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
-//// myCoincidentPoints.erase(aTempIt->first);
-//// myAttributeMap.erase(aTempIt);
-//// continue;
-//// }
-//// anAttrIter++;
-//// }
-////
-//// // Go through remaining extra coincidence and try to add or remove them
-//// anExtraIt = myExtraCoincidence.begin();
-//// while (anExtraIt != myExtraCoincidence.end()) {
-//// if (anExtraIt->first == SLVS_E_UNKNOWN) {
-//// if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
-//// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-//// myExtraCoincidence.erase(aTempIt);
-//// continue;
-//// }
-//// if (mySlvsConstraints.empty()) {
-//// myBaseConstraint = anExtraIt->first;
-//// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
-//// myExtraCoincidence.erase(aTempIt);
-//// process();
-//// continue;
-//// } else
-//// addConstraint(anExtraIt->first);
-//// }
-//// anExtraIt++;
-//// }
-//// return mySlvsConstraints.empty();
-////}
+ // Go through remaining extra coincidence and try to add or remove them
+ anExtraIt = myExtraCoincidence.begin();
+ while (anExtraIt != myExtraCoincidence.end()) {
+ if (anExtraIt->first == SLVS_E_UNKNOWN) {
+ if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
+ std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+ myExtraCoincidence.erase(aTempIt);
+ continue;
+ }
+ if (mySlvsConstraints.empty()) {
+ myBaseConstraint = anExtraIt->first;
+ std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
+ myExtraCoincidence.erase(aTempIt);
+ process();
+ continue;
+ } else
+ addConstraint(anExtraIt->first);
+ }
+ anExtraIt++;
+ }
+ return mySlvsConstraints.empty();
+}
#include "SketchSolver.h"
#include <SketchSolver_Constraint.h>
+#include <SketchSolver_Storage.h>
/** \class SketchSolver_ConstraintCoincidence
* \ingroup Plugins
{
public:
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
- SketchSolver_Constraint(theConstraint)
+ SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint),
+ myType(SLVS_C_UNKNOWN)
{}
-//// /// \brief Tries to remove constraint
-//// /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-//// virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
-
-//// /// \brief Checks the constraint is used by current object
-//// virtual bool hasConstraint(ConstraintPtr theConstraint) const;
-////
-//// /// \brief Return list of SketchPlugin constraints attached to this object
-//// virtual std::list<ConstraintPtr> constraints() const;
-////
-//// /// \brief Verifies the two Coincidence constraints are intersects (have shared point)
-//// bool isCoincide(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const;
-////
-//// /// \brief Append all data of coincidence constraint to the current
-//// void attach(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint);
+ virtual int getType() const
+ { return myType; }
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Checks the constraint is used by current object
+ virtual bool hasConstraint(ConstraintPtr theConstraint) const;
+
+ /// \brief Return list of SketchPlugin constraints attached to this object
+ virtual std::list<ConstraintPtr> constraints() const;
+
+ /// \brief Verifies the two Coincidence constraints are intersects (have shared point)
+ bool isCoincide(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const;
+
+ /// \brief Append all data of coincidence constaint to the current
+ void attach(std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint);
protected:
-//// /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
-//// virtual void process();
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
- /// \brief Generate list of attributes of constraint in order useful for constraints
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
-
-//// /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
-//// /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
-//// /// \param[out] theAttributes list of attributes to be filled
-//// virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
-////
-////private:
-//// /// \brief Creates new coincidence constraint
-//// Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
-////
-//// /// \brief Create full SolveSpace structure according to given constraint
-//// void addConstraint(ConstraintPtr theConstraint);
-////
-//// /// \brief Create constraint of point coincident to the line or circle
-//// Slvs_hConstraint addPointOnEntity(Slvs_hEntity thePoint, Slvs_hEntity theEntity);
-////
-////private:
-//// int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
-//// std::map<ConstraintPtr, Slvs_hConstraint> myExtraCoincidence; ///< multiple coincidence of points
-//// std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
+private:
+ /// \brief Creates new coincidence constraint
+ Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
+
+ /// \brief Create full SolveSpace structure according to given constraint
+ void addConstraint(ConstraintPtr theConstraint);
+
+ /// \brief Create constraint of point concident to the line or circle
+ Slvs_hConstraint addPointOnEntity(Slvs_hEntity thePoint, Slvs_hEntity theEntity);
+
+private:
+ int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
+ std::map<ConstraintPtr, Slvs_hConstraint> myExtraCoincidence; ///< multiple coincidence of points
+ std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
};
#endif
#include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
#include <math.h>
-void SketchSolver_ConstraintDistance::getAttributes(
- double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintDistance::process()
{
- SketchSolver_Constraint::getAttributes(theValue, theAttributes);
- if (!myErrorMsg.empty() || !theAttributes[0]) {
- theAttributes.clear();
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- if (theAttributes[1])
- myType = CONSTRAINT_PT_PT_DISTANCE;
- else if (theAttributes[2] && theAttributes[2]->type() == ENTITY_LINE)
- myType = CONSTRAINT_PT_LINE_DISTANCE;
- else
- theAttributes.clear();
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Obtain entities to identify the type of distance
+ static const int aNbPoints = 2;
+ Slvs_hEntity aPoint[aNbPoints] = {SLVS_E_UNKNOWN, SLVS_E_UNKNOWN};
+ Slvs_hEntity aLine = SLVS_E_UNKNOWN;
+ myType = SLVS_C_PT_PT_DISTANCE;
+ int aPtPos = 0;
+ std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+ for (; anEntIter != anEntities.end(); anEntIter++) {
+ if (*anEntIter == SLVS_E_UNKNOWN)
+ continue;
+ Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+ if (anEnt.type == SLVS_E_POINT_IN_2D || anEnt.type == SLVS_E_POINT_IN_3D) {
+ if (aPtPos >= aNbPoints) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ aPoint[aPtPos++] = *anEntIter;
+ }
+ else if (anEnt.type == SLVS_E_LINE_SEGMENT) {
+ if (myType == SLVS_C_PT_LINE_DISTANCE) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ aLine = *anEntIter;
+ myType = SLVS_C_PT_LINE_DISTANCE;
+ }
+ }
+
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue, aPoint[0], aPoint[1], aLine, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
myPrevValue = 0.0;
+ adjustConstraint();
}
void SketchSolver_ConstraintDistance::adjustConstraint()
{
// Adjust point-line distance
- if (getType() != CONSTRAINT_PT_LINE_DISTANCE)
+ if (getType() != SLVS_C_PT_LINE_DISTANCE)
return;
// Check the sign of distance is changed
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- if (fabs(myPrevValue) == fabs(aConstraint->value())) {
- aConstraint->setValue(myPrevValue);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
+ Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+ if (fabs(myPrevValue) == fabs(aConstraint.valA)) {
+ aConstraint.valA = myPrevValue;
+ myStorage->updateConstraint(aConstraint);
return;
}
// Get constraint parameters and check the sign of constraint value
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::shared_ptr<GeomAPI_Pnt2d> aPoint;
- std::shared_ptr<GeomAPI_Lin2d> aLine;
- std::list<EntityWrapperPtr> aSubs = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++aSIt) {
- if ((*aSIt)->type() == ENTITY_POINT)
- aPoint = aBuilder->point(*aSIt);
- else if ((*aSIt)->type() == ENTITY_LINE)
- aLine = aBuilder->line(*aSIt);
- }
-
- std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
- std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
- if (aPtLineVec->cross(aLineVec) * aConstraint->value() < 0.0 || myIsNegative) {
- aConstraint->setValue(aConstraint->value() * (-1.0));
- myStorage->addConstraint(myBaseConstraint, aConstraint);
- myIsNegative = true;
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+ aConstraint = myStorage->getConstraint(*aCIter);
+ Slvs_Entity aLine = myStorage->getEntity(aConstraint.entityA);
+ // Obtain point and line coordinates
+ Slvs_hEntity aPointID[3] = {aConstraint.ptA, aLine.point[0], aLine.point[1]};
+ std::shared_ptr<GeomAPI_XY> aPoints[3];
+ for (int i = 0; i < 3; i++) {
+ Slvs_Entity aPoint = myStorage->getEntity(aPointID[i]);
+ Slvs_Param aParams[2] = {
+ myStorage->getParameter(aPoint.param[0]),
+ myStorage->getParameter(aPoint.param[1])};
+ aPoints[i] = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aParams[0].val, aParams[1].val));
+ }
+ std::shared_ptr<GeomAPI_XY> aLineVec = aPoints[2]->decreased(aPoints[1]);
+ std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoints[0]->decreased(aPoints[1]);
+ if (aPtLineVec->cross(aLineVec) * aConstraint.valA < 0.0 || myIsNegative) {
+ aConstraint.valA *= -1.0;
+ myStorage->updateConstraint(aConstraint);
+ myIsNegative = true;
+ }
}
}
-void SketchSolver_ConstraintDistance::update()
+void SketchSolver_ConstraintDistance::update(ConstraintPtr theConstraint)
{
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- myPrevValue = aConstraint->value();
-
- SketchSolver_Constraint::update();
+ Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front());
+ myPrevValue = aConstraint.valA;
+ SketchSolver_Constraint::update(theConstraint);
}
/// Constructor based on SketchPlugin constraint
SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
SketchSolver_Constraint(theConstraint),
+ myType(SLVS_C_UNKNOWN),
myIsNegative(false)
{}
/// \brief Update constraint
- virtual void update();
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ virtual int getType() const
+ {return myType; }
protected:
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
/// \brief This method is used in derived objects to check consistence of constraint.
/// E.g. the distance between line and point may be signed.
virtual void adjustConstraint();
private:
+ int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
bool myIsNegative; ///< \c true, if the point if placed rightside of line direction (SLVS_C_PT_LINE_DISTANCE only)
};
#include <SketchSolver_ConstraintEqual.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-void SketchSolver_ConstraintEqual::getAttributes(
- double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+
+void SketchSolver_ConstraintEqual::process()
{
- SketchSolver_Constraint::getAttributes(theValue, theAttributes);
- if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
- theAttributes.clear();
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty())
+ return;
// Check the quantity of entities of each type
int aNbLines = 0;
int aNbArcs = 0;
int aNbCircs = 0;
bool isArcFirst = false; // in line-arc equivalence, the line should be first
- std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin() + 2;
- for (; anAttrIt != theAttributes.end(); ++anAttrIt) {
- SketchSolver_EntityType aType = (*anAttrIt)->type();
- if (aType == ENTITY_LINE)
- ++aNbLines;
- else if (aType == ENTITY_CIRCLE)
- ++aNbCircs;
- else if (aType == ENTITY_ARC) {
- ++aNbArcs;
+ std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+ for (; anEntIter != anEntities.end(); anEntIter++) {
+ Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+ if (anEnt.type == SLVS_E_LINE_SEGMENT)
+ aNbLines++;
+ else if (anEnt.type == SLVS_E_CIRCLE)
+ aNbCircs++;
+ else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
+ aNbArcs++;
isArcFirst = (aNbLines == 0);
}
}
if (aNbLines + aNbArcs + aNbCircs != 2 ||
- (aNbLines == aNbCircs && aNbArcs == 0)) {
+ (aNbLines == aNbCircs && aNbArcs == 0)) {
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
return;
}
switch (aNbLines) {
case 0:
- myType = CONSTRAINT_EQUAL_RADIUS;
+ myType = SLVS_C_EQUAL_RADIUS;
break;
case 1:
- myType = CONSTRAINT_EQUAL_LINE_ARC;
+ myType = SLVS_C_EQUAL_LINE_ARC_LEN;
if (isArcFirst) { // change the order of arc and line
- EntityWrapperPtr aTmp = theAttributes[2];
- theAttributes[2] = theAttributes[3];
- theAttributes[3] = aTmp;
+ Slvs_hEntity aTmp = anEntities[2];
+ anEntities[2] = anEntities[3];
+ anEntities[3] = aTmp;
}
break;
default:
- myType = CONSTRAINT_EQUAL_LINES;
+ myType = SLVS_C_EQUAL_LENGTH_LINES;
break;
}
+
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue,
+ anEntities[0], anEntities[1], anEntities[2], anEntities[3]);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ adjustConstraint();
}
+
SketchSolver_Constraint(theConstraint)
{}
+ virtual int getType() const
+ { return myType; }
+
protected:
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+private:
+ int myType; ///< type of constraint (applicable: SLVS_C_EQUAL_LENGTH_LINES, SLVS_C_EQUAL_RADIUS, SLVS_C_EQUAL_LINE_ARC_LEN)
};
#endif
--- /dev/null
+#include <SketchSolver_ConstraintFillet.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+
+void SketchSolver_ConstraintFillet::getAttributes(
+ double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+{
+ theAttributes.clear();
+
+ DataPtr aData = myBaseConstraint->data();
+ AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aData->attribute(SketchPlugin_Constraint::VALUE()));
+ theValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+ std::list<AttributePtr> aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anIter = aBaseAttrs.begin();
+ for (; anIter != aBaseAttrs.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (!aRefAttr || !aRefAttr->isInitialized()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
+ if (anEntity == SLVS_E_UNKNOWN)
+ anEntity = changeEntity(aRefAttr, aType);
+
+ if (aType == SLVS_E_UNKNOWN)
+ continue;
+ theAttributes.push_back(anEntity);
+ }
+
+ // Fillet objects
+ AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
+ if (!aFilletRefList || !aFilletRefList->isInitialized()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ std::list<ObjectPtr> aFilletList = aFilletRefList->list();
+ if (aFilletList.size() < theAttributes.size() + 1) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ FeaturePtr aFilletFeature;
+ ResultConstructionPtr aRC;
+ int aType;
+ std::list<ObjectPtr>::iterator aFilIter = aFilletList.begin();
+ for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) {
+ aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aFilIter);
+ aFilletFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*aFilIter);
+ if (!aFilletFeature) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType);
+ theAttributes.push_back(anEntity);
+ }
+}
+
+void SketchSolver_ConstraintFillet::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ double aValue;
+ std::vector<Slvs_hEntity> anEntID;
+ getAttributes(aValue, anEntID);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Obtain the entities itself:
+ // First two are base entities
+ // Second two are trimmed them
+ // Last one is a fillet arc
+ std::vector<Slvs_Entity> anEntities;
+ std::vector<Slvs_hEntity>::iterator anIt = anEntID.begin();
+ for (; anIt != anEntID.end(); anIt++)
+ anEntities.push_back(myStorage->getEntity(*anIt));
+
+ // Check the base entities have a coincident point
+ Slvs_hEntity aPointsToFind[4];
+ for (int i = 0; i < 2; i++) {
+ int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+ aPointsToFind[2*i] = anEntities[i].point[aShift];
+ aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
+ }
+ // Search coincident points
+ int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last)
+ bool isPointFound = false;
+ for (int i = 0; i < 2 && !isPointFound; i++)
+ for (int j = 2; j < 4 && !isPointFound; j++)
+ if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
+ aCoincInd[0] = i;
+ aCoincInd[1] = j - 2;
+ isPointFound = true;
+ }
+ if (!isPointFound) {
+ // There is no coincident points between tangential objects. Generate error message
+ myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
+ return;
+ }
+
+ // For correct result, move floating points of fillet on the middle points of base objects
+ Slvs_Entity aPoint;
+ Slvs_Param aParam;
+ double anArcPoints[3][2];
+ for (int i = 0; i < 2; i++) {
+ calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]);
+ aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]);
+ for (int j = 0; j < 2; j++) {
+ aParam = myStorage->getParameter(aPoint.param[j]);
+ aParam.val = anArcPoints[i+1][j];
+ aPoint.param[j] = myStorage->updateParameter(aParam);
+ }
+ }
+ anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]);
+ anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]);
+ // Check the arc is need to be reversed
+ double aSharedPoint[2];
+ aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]);
+ for (int j = 0; j < 2; j++)
+ aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val;
+ double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) -
+ (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]);
+ if (aCross < 0.0) { // reverse fillet arc
+ double aTmp;
+ for (int j = 0; j < 2; j++) {
+ aTmp = anArcPoints[1][j];
+ anArcPoints[1][j] = anArcPoints[2][j];
+ anArcPoints[2][j] = aTmp;
+ }
+ }
+ // update fillet arc coordinates
+ for (int indArcPt = 0; indArcPt < 3; indArcPt++) {
+ aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]);
+ for (int j = 0; j < 2; j++) {
+ aParam = myStorage->getParameter(aPoint.param[j]);
+ aParam.val = anArcPoints[indArcPt][j];
+ aPoint.param[j] = myStorage->updateParameter(aParam);
+ }
+ }
+
+ for (int indEnt = 0; indEnt < 2; indEnt++) {
+ int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+ // one point of fillet object should be coincident with the point on base, non-coincident with another base object
+ Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift];
+ Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift];
+ Slvs_Constraint aCoincConstr = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+ 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aCoincConstr.h = myStorage->addConstraint(aCoincConstr);
+ mySlvsConstraints.push_back(aCoincConstr.h);
+
+ // another point of fillet object should be placed on the base object
+ Slvs_Constraint aPonCurveConstr;
+ if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) {
+ // centers of arcs should be coincident
+ aBaseID = anEntities[indEnt].point[0];
+ aFilletID = anEntities[2 + indEnt].point[0];
+ aPonCurveConstr = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(),
+ 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ } else {
+ aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]];
+ aPonCurveConstr = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(),
+ 0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN);
+ }
+ aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr);
+ mySlvsConstraints.push_back(aPonCurveConstr.h);
+ }
+}
+
+bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+ std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+ mySlvsConstraints.clear();
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+ return true;
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintFillet.h
+// Created: 1 Apr 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintFillet_H_
+#define SketchSolver_ConstraintFillet_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintFillet
+ * \ingroup Plugins
+ * \brief Convert fillet constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintFillet : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintFillet(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_FILLET; }
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ ///
+ /// Parameter theAttributes contains 5 elements:
+ /// Two first entities in theAttributes list correspond to base features of fillet,
+ /// the next two entities represent trimmed base features and the last one is a fillet arc.
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+};
+
+#endif
+++ /dev/null
-#include <SketchSolver_ConstraintFixed.h>
-#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeDouble.h>
-
-#include <math.h>
-
-SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
- : SketchSolver_Constraint()
-{
- myBaseConstraint = theConstraint;
- myType = CONSTRAINT_FIXED;
- myFixedAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- theConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
-}
-
-SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
- : SketchSolver_Constraint(),
- myBaseFeature(theFeature)
-{
- myType = CONSTRAINT_FIXED;
- process();
-}
-
-void SketchSolver_ConstraintFixed::process()
-{
- cleanErrorMsg();
- if ((!myBaseConstraint && !myBaseFeature) || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are assigned
- return;
- }
-//// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-//// update(myBaseConstraint);
-
- ParameterWrapperPtr aValue;
- std::vector<EntityWrapperPtr> anEntities;
- getAttributes(aValue, anEntities);
- if (!myErrorMsg.empty() || anEntities.empty())
- return;
- fixFeature(anEntities.front());
-}
-
-////static void fixEntity(StoragePtr theStorage, const Slvs_hEntity& theEntID)
-////{
-//// Slvs_Entity anEntity = theStorage->getEntity(theEntID);
-//// anEntity.group = SLVS_G_OUTOFGROUP;
-//// theStorage->updateEntity(anEntity);
-//// // move out of group all sub-entities
-//// for (int i = 0; i < 4; ++i)
-//// if (anEntity.point[i] != SLVS_E_UNKNOWN)
-//// fixEntity(theStorage, anEntity.point[i]);
-//// // move out of group the radius of circle
-//// if (anEntity.distance != SLVS_E_UNKNOWN)
-//// fixEntity(theStorage, anEntity.distance);
-//// // move out of group parameters
-//// for (int i = 0; i < 4; ++i)
-//// if (anEntity.param[i] != SLVS_E_UNKNOWN) {
-//// Slvs_Param aParam = theStorage->getParameter(anEntity.param[i]);
-//// aParam.group = SLVS_G_OUTOFGROUP;
-//// theStorage->updateParameter(aParam);
-//// }
-////}
-
-void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
-{
- // extract feature from the group
- if (theFeature->baseAttribute())
- myStorage->update(theFeature->baseAttribute(), GID_OUTOFGROUP);
- else
- myStorage->update(theFeature->baseFeature(), GID_OUTOFGROUP);
-}
-
-////Slvs_hEntity SketchSolver_ConstraintFixed::fixedEntity() const
-////{
-//// Slvs_hEntity anEntID = SLVS_E_UNKNOWN;
-//// if (myBaseConstraint) {
-//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-//// myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-//// if (aRefAttr->isObject()) {
-//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-//// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(aFeature);
-//// if (aFound != myFeatureMap.end())
-//// anEntID = aFound->second;
-//// } else {
-//// std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(aRefAttr->attr());
-//// if (aFound != myAttributeMap.end())
-//// anEntID = aFound->second;
-//// }
-//// }
-//// else if (myBaseFeature) {
-//// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(myBaseFeature);
-//// if (aFound != myFeatureMap.end())
-//// anEntID = aFound->second;
-//// }
-//// return anEntID;
-////}
-
-void SketchSolver_ConstraintFixed::getAttributes(
- ParameterWrapperPtr& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
-{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- EntityWrapperPtr aSolverEntity;
- if (myBaseFeature) {
- // The feature is fixed.
- myStorage->update(myBaseFeature, myGroupID);
- aSolverEntity = myStorage->entity(myBaseFeature);
- } else if (myBaseConstraint) {
- // Constraint Fixed is added by user.
- // Get the attribute of constraint (it should be alone in the list of constraints).
- AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A());
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
- if (!aRefAttr || !aRefAttr->isInitialized()) {
- myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
- return;
- }
-
- myStorage->update(anAttr, myGroupID);
- aSolverEntity = myStorage->entity(anAttr);
- } else
- myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-
- if (aSolverEntity)
- theAttributes.push_back(aSolverEntity);
-}
-
-
-bool SketchSolver_ConstraintFixed::remove()
-{
- cleanErrorMsg();
- // Move fixed entities back to the current group
- FeaturePtr aFeature = myBaseFeature;
- if (myBaseConstraint && myFixedAttribute && myFixedAttribute->isObject())
- aFeature = ModelAPI_Feature::feature(myFixedAttribute->object());
- if (aFeature)
- myStorage->update(aFeature, myGroupID);
-
- // Remove constraint or base feature
- if (myBaseConstraint) {
- bool isRemoved = false;
- if (aFeature)
- isRemoved = myStorage->removeEntity(aFeature);
- return SketchSolver_Constraint::remove() || isRemoved;
- } else if (myBaseFeature)
- myStorage->removeEntity(myBaseFeature);
- return true;
-}
-
-////Slvs_hConstraint SketchSolver_ConstraintFixed::fixPoint(const Slvs_hEntity& thePointID)
-////{
-//// if (thePointID == SLVS_E_UNKNOWN)
-//// return SLVS_C_UNKNOWN;
-////
-//// Slvs_Constraint aConstraint;
-//// Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
-//// bool isFixed = myStorage->isPointFixed(thePointID, aConstrID, true);
-//// bool isForceUpdate = (isFixed && !myBaseConstraint &&
-//// myStorage->isTemporary(aConstrID));
-//// if (!isForceUpdate) { // create new constraint
-//// if (isFixed) return aConstrID;
-//// aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
-//// 0.0, thePointID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aConstraint.h = myStorage->addConstraint(aConstraint);
-//// mySlvsConstraints.push_back(aConstraint.h);
-//// if (!myBaseConstraint)
-//// myStorage->addConstraintWhereDragged(aConstraint.h);
-//// } else { // update already existent constraint
-//// if (!isFixed || aConstrID == SLVS_C_UNKNOWN || myBaseConstraint)
-//// return SLVS_C_UNKNOWN;
-//// aConstraint = myStorage->getConstraint(aConstrID);
-//// aConstraint.ptA = thePointID;
-//// myStorage->addConstraint(aConstraint);
-//// if (!myBaseConstraint)
-//// myStorage->addConstraintWhereDragged(aConstraint.h);
-//// }
-//// return aConstraint.h;
-////}
-////
-////void SketchSolver_ConstraintFixed::fixLine(const Slvs_Entity& theLine)
-////{
-//// Slvs_Constraint anEqual;
-//// if (myStorage->isAxisParallel(theLine.h)) {
-//// // Fix one point and a line length
-//// Slvs_hConstraint aFixed;
-//// if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) &&
-//// !myStorage->isPointFixed(theLine.point[1], aFixed, true))
-//// fixPoint(theLine.point[0]);
-//// if (!myStorage->isUsedInEqual(theLine.h, anEqual)) {
-//// // Check the distance is not set yet
-//// std::list<Slvs_Constraint> aDistConstr = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
-//// std::list<Slvs_Constraint>::const_iterator aDIt = aDistConstr.begin();
-//// for (; aDIt != aDistConstr.end(); aDIt++)
-//// if ((aDIt->ptA == theLine.point[0] && aDIt->ptB == theLine.point[1]) ||
-//// (aDIt->ptA == theLine.point[1] && aDIt->ptB == theLine.point[0]))
-//// return;
-//// // Calculate distance between points on the line
-//// double aCoords[4];
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]);
-//// for (int j = 0; j < 2; j++) {
-//// Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]);
-//// aCoords[2*i+j] = aParam.val;
-//// }
-//// }
-//// double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
-//// (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
-//// // fix line length
-//// Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-//// SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength,
-//// theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aDistance.h = myStorage->addConstraint(aDistance);
-//// mySlvsConstraints.push_back(aDistance.h);
-//// }
-//// return;
-//// }
-//// else if (myStorage->isUsedInEqual(theLine.h, anEqual)) {
-//// // Check another entity of Equal is already fixed
-//// Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
-//// if (myStorage->isEntityFixed(anOtherEntID, true)) {
-//// // Fix start point of the line (if end point is not fixed yet) ...
-//// Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
-//// bool isFixed = myStorage->isPointFixed(theLine.point[1], anEndFixedID, true);
-//// if (isFixed == SLVS_E_UNKNOWN)
-//// fixPoint(theLine.point[0]);
-//// // ... and create fixed point lying on this line
-//// Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
-//// // Firstly, search already fixed point on line
-//// bool isPonLineFixed = false;
-//// Slvs_hEntity aFixedPoint;
-//// std::list<Slvs_Constraint> aPonLineList = myStorage->getConstraintsByType(SLVS_C_PT_ON_LINE);
-//// std::list<Slvs_Constraint>::const_iterator aPLIter = aPonLineList.begin();
-//// for (; aPLIter != aPonLineList.end() && !isPonLineFixed; aPLIter++)
-//// if (aPLIter->entityA == theLine.h) {
-//// isPonLineFixed = myStorage->isPointFixed(aPLIter->ptA, anEndFixedID);
-//// aFixedPoint = aPLIter->ptA;
-//// }
-////
-//// if (isPonLineFixed) { // update existent constraint
-//// myStorage->copyEntity(aPointToCopy, aFixedPoint);
-//// } else { // create new constraint
-//// Slvs_hEntity aCopied = myStorage->copyEntity(aPointToCopy);
-//// Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE,
-//// myGroup->getWorkplaneId(), 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
-//// aPonLine.h = myStorage->addConstraint(aPonLine);
-//// mySlvsConstraints.push_back(aPonLine.h);
-//// fixPoint(aCopied);
-//// }
-//// return;
-//// }
-//// }
-////
-//// for (int i = 0; i < 2; i++)
-//// fixPoint(theLine.point[i]);
-////}
-////
-////void SketchSolver_ConstraintFixed::fixCircle(const Slvs_Entity& theCircle)
-////{
-//// bool isFixRadius = true;
-//// // Verify the arc is under Equal constraint
-//// Slvs_Constraint anEqual;
-//// if (myStorage->isUsedInEqual(theCircle.h, anEqual)) {
-//// // Check another entity of Equal is already fixed
-//// Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
-//// if (myStorage->isEntityFixed(anOtherEntID, true))
-//// isFixRadius = false;
-//// }
-////
-//// fixPoint(theCircle.point[0]);
-////
-//// if (isFixRadius) {
-//// // Search the radius is already fixed
-//// std::list<Slvs_Constraint> aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-//// std::list<Slvs_Constraint>::const_iterator aDiamIter = aDiamConstr.begin();
-//// for (; aDiamIter != aDiamConstr.end(); aDiamIter++)
-//// if (aDiamIter->entityA == theCircle.h)
-//// return;
-////
-//// // Fix radius of a circle
-//// AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
-//// myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
-//// Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
-//// myGroup->getWorkplaneId(), aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
-//// myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
-//// aFixedR.h = myStorage->addConstraint(aFixedR);
-//// mySlvsConstraints.push_back(aFixedR.h);
-//// }
-////}
-////
-////void SketchSolver_ConstraintFixed::fixArc(const Slvs_Entity& theArc)
-////{
-//// bool isFixRadius = true;
-//// std::list<Slvs_hEntity> aPointsToFix;
-//// aPointsToFix.push_back(theArc.point[1]);
-//// aPointsToFix.push_back(theArc.point[2]);
-////
-//// // Verify the arc is under Equal constraint
-//// Slvs_Constraint anEqual;
-//// if (myStorage->isUsedInEqual(theArc.h, anEqual)) {
-//// // Check another entity of Equal is already fixed
-//// Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
-//// if (myStorage->isEntityFixed(anOtherEntID, true)) {
-//// isFixRadius = false;
-//// Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
-//// if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
-//// aPointsToFix.pop_back();
-//// aPointsToFix.push_back(theArc.point[0]);
-//// }
-//// }
-//// }
-////
-//// Slvs_hConstraint aConstrID;
-//// int aNbPointsToFix = 2; // number of fixed points for the arc
-//// if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
-//// aNbPointsToFix--;
-////
-//// // Radius of the arc
-//// FeaturePtr aFeature = myFeatureMap.begin()->first;
-//// std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-//// aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
-//// std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-//// aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
-//// double aRadius = aCenter->distance(aStart);
-////
-//// // Update end point of the arc to be on a curve
-//// std::shared_ptr<GeomAPI_Pnt2d> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-//// aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
-//// double aDistance = anEnd->distance(aCenter);
-//// std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
-//// if (aDistance < tolerance)
-//// aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
-//// else
-//// aDir = aDir->multiplied(aRadius / aDistance);
-//// double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
-//// Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]);
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]);
-//// aParam.val = xy[i];
-//// myStorage->updateParameter(aParam);
-//// }
-////
-//// std::list<Slvs_hEntity>::iterator aPtIt = aPointsToFix.begin();
-//// for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
-//// fixPoint(*aPtIt);
-////
-//// if (isFixRadius) {
-//// // Fix radius of the arc
-//// bool isExists = false;
-//// std::list<Slvs_Constraint> aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-//// std::list<Slvs_Constraint>::iterator anIt = aDiamConstraints.begin();
-//// for (; anIt != aDiamConstraints.end() && !isExists; anIt++)
-//// if (anIt->entityA == theArc.h)
-//// isExists = true;
-//// if (!isExists) {
-//// Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
-//// myGroup->getWorkplaneId(), aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
-//// myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
-//// aFixedR.h = myStorage->addConstraint(aFixedR);
-//// mySlvsConstraints.push_back(aFixedR.h);
-//// if (!myBaseConstraint)
-//// myStorage->addConstraintWhereDragged(aFixedR.h);
-//// }
-//// }
-////}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_ConstraintFixed.h
-// Created: 30 Mar 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintFixed_H_
-#define SketchSolver_ConstraintFixed_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_Constraint.h>
-
-/** \class SketchSolver_ConstraintFixed
- * \ingroup Plugins
- * \brief Stores data of the Fixed constraint
- *
- * Fixed constraint may have NULL basic SketchPlugin constraint,
- * because the Fixed constraint may be temporary for correct moving of objects.
- *
- * Fixed constraint does not create a constraint, but builds the entities in separate group,
- * so they will not be moved while resolving the set of constraints.
- */
-class SketchSolver_ConstraintFixed : public SketchSolver_Constraint
-{
-public:
- /// Creates constraint to manage the given constraint from plugin
- SketchSolver_ConstraintFixed(ConstraintPtr theConstraint);
- /// Creates temporary constraint based on feature
- SketchSolver_ConstraintFixed(FeaturePtr theFeature);
-
- /// \brief Tries to remove constraint
- /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
- virtual bool remove();
-
-protected:
- /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process();
-
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(ParameterWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes);
-
- /// \brief Fixed feature basing on its type
- /// \param theFeature [in] feature, converted to solver specific format
- virtual void fixFeature(EntityWrapperPtr theFeature);
-
-//// /// \brief Fix given point
-//// /// \return ID of the Fixed constraint
-//// Slvs_hConstraint fixPoint(const Slvs_hEntity& thePointID);
-////
-//// /// \brief Returns ID of fixed entity
-//// Slvs_hEntity fixedEntity() const;
-////
-//// /// \brief Fixing line position (start and end points)
-//// void fixLine(const Slvs_Entity& theLine);
-//// /// \brief Fixing circle (center and radius)
-//// void fixCircle(const Slvs_Entity& theCircle);
-//// /// \brief The arc is fixed differently to avoid SolveSpace problems (overconstraint)
-//// ///
-//// /// There will be fixed start and end points and the radius of the arc.
-//// void fixArc(const Slvs_Entity& theArc);
-
-protected:
- FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
-
-private:
- AttributeRefAttrPtr myFixedAttribute; ///< attribute of a fixed constraint (for correct remove)
-};
-
-#endif
#include <SketchSolver_ConstraintLength.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-void SketchSolver_ConstraintLength::getAttributes(
- double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintLength::process()
{
- SketchSolver_Constraint::getAttributes(theValue, theAttributes);
- if (!myErrorMsg.empty() || !theAttributes[2] ||
- theAttributes[2]->type() != ENTITY_LINE) {
- theAttributes.clear();
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- // Get boundary points of line segment and create point-point distance constraint
- std::list<EntityWrapperPtr> aSubs = theAttributes[2]->subEntities();
- theAttributes.assign(theAttributes.size(), EntityWrapperPtr());
- std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin();
- std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
- for (; aSubIt != aSubs.end(); ++aSubIt, ++anAttrIt)
- *anAttrIt = *aSubIt;
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Check the entity is a line
+ Slvs_Entity aLine = myStorage->getEntity(anEntities[2]);
+ if (aLine.type != SLVS_E_LINE_SEGMENT){
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
- myType = CONSTRAINT_PT_PT_DISTANCE;
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue,
+ aLine.point[0], aLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintLength::adjustConstraint()
+{
+ // No need to store the line, which length is constrained
+ // Upd: The line need to be stored to check that constraint
+ // is changed/unchanged during modifications in GUI
+ //myFeatureMap.clear();
}
SketchSolver_Constraint(theConstraint)
{}
+ virtual int getType() const
+ { return SLVS_C_PT_PT_DISTANCE; }
+
protected:
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ /// E.g. the distance between line and point may be signed.
+ virtual void adjustConstraint();
};
#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintManager.cpp
+// Created: 08 May 2014
+// Author: Artem ZHIDKOV
+
+#include "SketchSolver_ConstraintManager.h"
+
+#include <Events_Loop.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Attribute.h>
+
+#include <SketchPlugin_Constraint.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Sketch.h>
+#include <SketchPlugin_Feature.h>
+
+#include <list>
+#include <set>
+#include <memory>
+
+// Initialization of constraint manager self pointer
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::_self = 0;
+
+/// Global constraint manager object
+SketchSolver_ConstraintManager* myManager = SketchSolver_ConstraintManager::Instance();
+
+
+// ========================================================
+// ========= SketchSolver_ConstraintManager ===============
+// ========================================================
+SketchSolver_ConstraintManager* SketchSolver_ConstraintManager::Instance()
+{
+ if (!_self)
+ _self = new SketchSolver_ConstraintManager();
+ return _self;
+}
+
+SketchSolver_ConstraintManager::SketchSolver_ConstraintManager()
+{
+ myGroups.clear();
+ myIsComputed = false;
+
+ // Register in event loop
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
+}
+
+SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager()
+{
+ myGroups.clear();
+}
+
+// ============================================================================
+// Function: processEvent
+// Class: SketchSolver_Session
+// Purpose: listen the event loop and process the message
+// ============================================================================
+void SketchSolver_ConstraintManager::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ if (myIsComputed)
+ return;
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
+ || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)
+ || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
+ std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
+
+ // Shows the message has at least one feature applicable for solver
+ bool hasProperFeature = false;
+
+ bool isMovedEvt = theMessage->eventID()
+ == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
+ if (isMovedEvt) {
+ std::set<ObjectPtr>::iterator aFeatIter;
+ for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+ std::shared_ptr<SketchPlugin_Feature> aSFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (aSFeature) {
+ moveEntity(aSFeature);
+ hasProperFeature = true;
+ }
+ }
+ } else {
+ std::list<FeaturePtr> aSketchFeatures = SketchSolver_Group::selectApplicableFeatures(aFeatures);
+ std::list<FeaturePtr>::iterator aFeatIter = aSketchFeatures.begin();
+ for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) {
+ if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) {
+ std::shared_ptr<ModelAPI_CompositeFeature> aSketch =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIter);
+ hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
+ continue;
+ }
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (!aFeature)
+ continue;
+ hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature;
+ }
+ }
+
+ // Solve the set of constraints
+ if (hasProperFeature)
+ resolveConstraints(isMovedEvt); // send update for movement in any case
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+ std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+ const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
+
+ // Find SketchPlugin_Sketch::ID() in groups. The constraint groups should be updated when an object removed from Sketch
+ std::set<std::string>::const_iterator aFGrIter;
+ for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
+ if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
+ aFGrIter->compare(ModelAPI_Feature::group()) == 0)
+ break;
+
+ if (aFGrIter != aFeatureGroups.end()) {
+ std::vector<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
+ std::vector<SketchSolver_Group*> aSeparatedGroups;
+ while (aGroupIter != myGroups.end()) {
+ if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed
+ delete *aGroupIter;
+ int aShift = aGroupIter - myGroups.begin();
+ myGroups.erase(aGroupIter);
+ aGroupIter = myGroups.begin() + aShift;
+ continue;
+ }
+ if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group
+ (*aGroupIter)->splitGroup(aSeparatedGroups);
+ }
+ aGroupIter++;
+ }
+ if (aSeparatedGroups.size() > 0)
+ myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
+ }
+ }
+}
+
+// ============================================================================
+// Function: changeWorkplane
+// Class: SketchSolver_Session
+// Purpose: update workplane by given parameters of the sketch
+// ============================================================================
+bool SketchSolver_ConstraintManager::changeWorkplane(CompositeFeaturePtr theSketch)
+{
+ bool aResult = true; // changed when a workplane wrongly updated
+ bool isUpdated = false;
+ // Try to update specified workplane in all groups
+ std::vector<SketchSolver_Group*>::iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
+ isUpdated = true;
+ if (!(*aGroupIter)->updateWorkplane())
+ aResult = false;
+ }
+ // If the workplane is not updated, so this is a new workplane
+ if (!isUpdated) {
+ SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch);
+ // Verify that the group is created successfully
+ if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) {
+ delete aNewGroup;
+ return false;
+ }
+ myGroups.push_back(aNewGroup);
+ }
+ return aResult;
+}
+
+// ============================================================================
+// Function: changeConstraintOrEntity
+// Class: SketchSolver_Session
+// Purpose: create/update the constraint or the feature and place it into appropriate group
+// ============================================================================
+bool SketchSolver_ConstraintManager::changeConstraintOrEntity(
+ std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+ // Search the groups which this feature touches
+ std::set<Slvs_hGroup> aGroups;
+ findGroups(theFeature, aGroups);
+
+ std::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+
+ // Process the groups list
+ if (aGroups.size() == 0) {
+ // There are no groups applicable for this constraint => create new one
+ // The group will be created only for constraints, not for features
+ if (!aConstraint) return false;
+ std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(aConstraint);
+ if (!aWP)
+ return false;
+ SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
+ if (!aGroup->changeConstraint(aConstraint)) {
+ delete aGroup;
+ return false;
+ }
+ myGroups.push_back(aGroup);
+ return true;
+ } else if (aGroups.size() == 1) { // Only one group => add feature into it
+ Slvs_hGroup aGroupId = *(aGroups.begin());
+ std::vector<SketchSolver_Group*>::iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ if ((*aGroupIter)->getId() == aGroupId) {
+ // If the group is empty, the feature is not added (the constraint only)
+ if (!aConstraint && !(*aGroupIter)->isEmpty())
+ return (*aGroupIter)->updateFeature(theFeature);
+ return (*aGroupIter)->changeConstraint(aConstraint);
+ }
+ } else if (aGroups.size() > 1) { // Several groups applicable for this feature => need to merge them
+ std::set<Slvs_hGroup>::const_iterator aGroupsIter = aGroups.begin();
+
+ // Search first group
+ std::vector<SketchSolver_Group*>::iterator aFirstGroupIter;
+ for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++)
+ if ((*aFirstGroupIter)->getId() == *aGroupsIter)
+ break;
+ if (aFirstGroupIter == myGroups.end())
+ return false;
+
+ // Append other groups to the first one
+ std::vector<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter + 1;
+ for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
+ for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
+ if ((*anOtherGroupIter)->getId() == *aGroupsIter)
+ break;
+ if (anOtherGroupIter == myGroups.end()) { // Group disappears
+ anOtherGroupIter = aFirstGroupIter + 1;
+ continue;
+ }
+
+ (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
+ int aShiftFirst = aFirstGroupIter - myGroups.begin();
+ int aShiftOther = anOtherGroupIter - myGroups.begin();
+ delete *anOtherGroupIter;
+ myGroups.erase(anOtherGroupIter);
+ aFirstGroupIter = myGroups.begin() + aShiftFirst;
+ anOtherGroupIter = myGroups.begin() + aShiftOther;
+ }
+
+ if (aConstraint)
+ return (*aFirstGroupIter)->changeConstraint(aConstraint);
+ return (*aFirstGroupIter)->updateFeature(theFeature);
+ }
+
+ // Something goes wrong
+ return false;
+}
+
+// ============================================================================
+// Function: moveEntity
+// Class: SketchSolver_Session
+// Purpose: update element moved on the sketch, which is used by constraints
+// ============================================================================
+void SketchSolver_ConstraintManager::moveEntity(
+ std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+ std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
+ for (; aGroupIt != myGroups.end(); aGroupIt++)
+ if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
+ (*aGroupIt)->moveFeature(theFeature);
+}
+
+// ============================================================================
+// Function: findGroups
+// Class: SketchSolver_Session
+// Purpose: search groups of entities interacting with given feature
+// ============================================================================
+void SketchSolver_ConstraintManager::findGroups(
+ std::shared_ptr<SketchPlugin_Feature> theFeature,
+ std::set<Slvs_hGroup>& theGroupIDs) const
+{
+ std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
+
+ SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint
+ std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) {
+ if (!(*aGroupIter)->isEmpty())
+ theGroupIDs.insert((*aGroupIter)->getId());
+ else if (!anEmptyGroup)
+ anEmptyGroup = *aGroupIter;
+ }
+
+ // When only empty group is found, use it
+ if (anEmptyGroup && theGroupIDs.empty())
+ theGroupIDs.insert(anEmptyGroup->getId());
+}
+
+// ============================================================================
+// Function: findWorkplane
+// Class: SketchSolver_Session
+// Purpose: search workplane containing given feature
+// ============================================================================
+std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_ConstraintManager
+::findWorkplane(std::shared_ptr<SketchPlugin_Feature> theFeature) const
+{
+ // Already verified workplanes
+ std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
+
+ std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
+ std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
+ if (aVerified.find(aWP) != aVerified.end())
+ continue;
+
+ DataPtr aData = aWP->data();
+ if (aData->isValid()) {
+ std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
+ std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
+ std::list<ObjectPtr>::const_iterator anIter;
+ for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
+ if (*anIter == theFeature)
+ return aWP; // workplane is found
+ }
+ aVerified.insert(aWP);
+ }
+
+ return std::shared_ptr<ModelAPI_CompositeFeature>();
+}
+
+// ============================================================================
+// Function: resolveConstraints
+// Class: SketchSolver_Session
+// Purpose: change entities according to available constraints
+// ============================================================================
+void SketchSolver_ConstraintManager::resolveConstraints(const bool theForceUpdate)
+{
+ myIsComputed = true;
+ bool needToUpdate = false;
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ // to avoid redisplay of each segment on update by solver one by one in the viewer
+ bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+ if (isUpdateFlushed) {
+ Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+ }
+
+ std::vector<SketchSolver_Group*>::iterator aGroupIter;
+ for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+ if ((*aGroupIter)->resolveConstraints())
+ needToUpdate = true;
+
+ // Features may be updated => now send events, but for all changed at once
+ if (isUpdateFlushed) {
+ Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+ }
+ // Must be before flush because on "Updated" flush the results may be produced
+ // and the creation event is appeared with many new objects. If myIsComputed these
+ // events are missed in processEvents and some elements are not added.
+ myIsComputed = false;
+ if (needToUpdate || theForceUpdate)
+ Events_Loop::loop()->flush(anUpdateEvent);
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintManager.h
+// Created: 08 May 2014
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintManager_H_
+#define SketchSolver_ConstraintManager_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Solver.h>
+#include <SketchSolver_Group.h>
+
+#include <Events_Listener.h>
+#include <SketchPlugin_Constraint.h>
+
+#include <string.h>
+#include <slvs.h>
+
+#include <list>
+#include <map>
+#include <vector>
+#include <set>
+
+/** \class SketchSolver_ConstraintManager
+ * \ingroup Plugins
+ * \brief Listens the changes of SketchPlugin features and transforms the Constraint
+ * feature into the format understandable by SolveSpace library.
+ *
+ * Constraints created for SolveSpace library are divided into the groups.
+ * The division order based on connectedness of the features by the constraints.
+ * The groups may be fused or separated according to the new constraints.
+ *
+ * \remark This is a singleton.
+ */
+class SketchSolver_ConstraintManager : public Events_Listener
+{
+ public:
+ /** \brief Main method to create constraint manager
+ * \return pointer to the singleton
+ */
+ static SketchSolver_ConstraintManager* Instance();
+
+ /** \brief Implementation of Event Listener method
+ * \param[in] theMessage the data of the event
+ */
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+ SketchSolver_ConstraintManager();
+ ~SketchSolver_ConstraintManager();
+
+ /** \brief Adds or updates a constraint or an entity in the suitable group
+ * \param[in] theFeature sketch feature to be changed
+ * \return \c true if the feature changed successfully
+ */
+ bool changeConstraintOrEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
+ /** \brief Removes a constraint from the manager
+ * \param[in] theConstraint constraint to be removed
+ * \return \c true if the constraint removed successfully
+ */
+ bool removeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+ /** \brief Adds or updates a workplane in the manager
+ * \param[in] theSketch the feature to create or update workplane
+ * \return \c true if the workplane changed successfully
+ * \remark Type of theSketch is not verified inside
+ */
+ bool changeWorkplane(CompositeFeaturePtr theSketch);
+
+ /** \brief Removes a workplane from the manager.
+ * All groups based on such workplane will be removed too.
+ * \param[in] theSketch the feature to be removed
+ * \return \c true if the workplane removed successfully
+ */
+ bool removeWorkplane(std::shared_ptr<SketchPlugin_Sketch> theSketch);
+
+ /** \brief Updates entity which is moved in GUI
+ * \param[in] theFeature entity to be updated
+ */
+ void moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
+ /** \brief Goes through the list of groups and solve the constraints
+ * \param theForceUpdate flushes the update event in any case: something changed or not
+ */
+ void resolveConstraints(const bool theForceUpdate);
+
+ private:
+ /** \brief Searches list of groups which interact with specified feature
+ * \param[in] theFeature object to be found
+ * \param[out] theGroups list of group indexes interacted with the feature
+ */
+ void findGroups(std::shared_ptr<SketchPlugin_Feature> theFeature,
+ std::set<Slvs_hGroup>& theGroupIDs) const;
+
+ /** \brief Searches in the list of groups the workplane which constains specified feature
+ * \param[in] theFeature object to be found
+ * \return workplane containing the feature
+ */
+ std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
+ std::shared_ptr<SketchPlugin_Feature> theFeature) const;
+
+ private:
+ static SketchSolver_ConstraintManager* _self; ///< Self pointer to implement singleton functionality
+ std::vector<SketchSolver_Group*> myGroups; ///< Groups of constraints
+ /// true if computation is performed and all "updates" are generated by this algo
+ /// and needs no recomputation
+ bool myIsComputed;
+};
+
+#endif
#include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <cmath>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <cmath>
void SketchSolver_ConstraintMirror::getAttributes(
- EntityWrapperPtr& theMirrorLine,
- std::vector<EntityWrapperPtr>& theBaseEntities,
- std::vector<EntityWrapperPtr>& theMirrorEntities)
+ Slvs_Entity& theMirrorLine,
+ std::vector<Slvs_Entity>& theBaseEntities,
+ std::vector<Slvs_Entity>& theMirrorEntities)
{
- AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
- AttributeRefAttrPtr aMirLineRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aMirLineAttr);
- if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
+ DataPtr aData = myBaseConstraint->data();
+ AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
}
-
- myType = TYPE(myBaseConstraint);
- myStorage->update(aMirLineAttr, myGroupID);
- theMirrorLine = myStorage->entity(aMirLineAttr);
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntity = myGroup->getAttributeId(aMirLineAttr);
+ if (anEntity == SLVS_E_UNKNOWN)
+ anEntity = changeEntity(aMirLineAttr, aType);
+ theMirrorLine = myStorage->getEntity(anEntity);
// Create SolveSpace entity for all features
AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
FeaturePtr aFeature;
+ ResultConstructionPtr aRC;
for (int i = 0; i < 2; i++) {
std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
- std::vector<EntityWrapperPtr>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
+ std::vector<Slvs_Entity>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
for ( ; anIter != aEndIter; anIter++) {
- aFeature = ModelAPI_Feature::feature(*anIter);
+ aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIter);
+ aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*anIter);
if (!aFeature)
continue;
-//// anEntity = changeEntity(aFeature, aType);
-//// // Sort entities by their type
-//// std::vector<Slvs_Entity>::iterator anIt = aList->begin();
-//// for (; anIt != aList->end(); anIt++)
-//// if (aType < anIt->type)
-//// break;
-////// aList->push_back(myStorage->getEntity(anEntity));
-//// aList->insert(anIt, myStorage->getEntity(anEntity));
- myStorage->update(aFeature, myGroupID);
- aList->push_back(myStorage->entity(aFeature));
+ anEntity = changeEntity(aFeature, aType);
+ // Sort entities by their type
+ std::vector<Slvs_Entity>::iterator anIt = aList->begin();
+ for (; anIt != aList->end(); anIt++)
+ if (aType < anIt->type)
+ break;
+// aList->push_back(myStorage->getEntity(anEntity));
+ aList->insert(anIt, myStorage->getEntity(anEntity));
}
}
void SketchSolver_ConstraintMirror::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are assigned
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
-//// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-//// update(myBaseConstraint);
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- EntityWrapperPtr aMirrorLine;
- std::vector<EntityWrapperPtr> aBaseList;
- std::vector<EntityWrapperPtr> aMirrorList;
+ Slvs_Entity aMirrorLine;
+ std::vector<Slvs_Entity> aBaseList;
+ std::vector<Slvs_Entity> aMirrorList;
getAttributes(aMirrorLine, aBaseList, aMirrorList);
if (!myErrorMsg.empty())
return;
return;
}
- std::list<ConstraintWrapperPtr> aNewConstraints;
- SketchSolver_ConstraintType aConstrType = getType();
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aMirConstrList;
-
- std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
- std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
- for (; aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
- if ((*aBIt)->type() == ENTITY_ARC) {
- // add new points on arcs and mirror them
- EntityWrapperPtr aBasePnt = myStorage->calculateMiddlePoint(*aBIt, 0.5);
- EntityWrapperPtr aMirrPnt = myStorage->calculateMiddlePoint(*aMIt, 0.5);
- // point on base arc
- aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
- CONSTRAINT_PT_ON_CIRCLE, 0.0, aBasePnt, EntityWrapperPtr(), *aBIt);
- aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
- // point on mirrored arc
- aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
- CONSTRAINT_PT_ON_CIRCLE, 0.0, aMirrPnt, EntityWrapperPtr(), *aMIt);
- aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
- // mirror these points
- aNewConstraints = aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID,
- aConstrType, 0.0, aBasePnt, aMirrPnt, aMirrorLine);
- aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
- }
- aNewConstraints = aBuilder->createConstraint(
- myBaseConstraint, myGroupID, mySketchID, aConstrType,
- 0.0, *aBIt, *aMIt, aMirrorLine);
- aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
+ Slvs_Constraint aConstraint;
+ // Get coordinates of mirror line points for speed up
+ double aStartEnd[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
+ for (int j = 0; j < 2; j++)
+ aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
}
- myStorage->addConstraint(myBaseConstraint, aMirConstrList);
+ std::vector<Slvs_Entity>::iterator aBaseIter = aBaseList.begin();
+ std::vector<Slvs_Entity>::iterator aMirrorIter = aMirrorList.begin();
+ for (; aBaseIter != aBaseList.end(); aBaseIter++, aMirrorIter++) {
+ // Make aMirrorEnt parameters to be symmetric with aBaseEnt
+ makeMirrorEntity(*aBaseIter, *aMirrorIter, aStartEnd);
+
+ if (aBaseIter->type == SLVS_E_POINT_IN_2D) {
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+ 0.0, aBaseIter->h, aMirrorIter->h, aMirrorLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ } else if (aBaseIter->type == SLVS_E_LINE_SEGMENT) {
+ for (int i = 0; i < 2; i++) {
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+ aBaseIter->point[i], aMirrorIter->point[i], aMirrorLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ } else if (aBaseIter->type == SLVS_E_CIRCLE) {
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+ aBaseIter->point[0], aMirrorIter->point[0], aMirrorLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ // Additional constraint for equal radii
+ Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(),
+ 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseIter->h, aMirrorIter->h);
+ anEqRadConstr.h = myStorage->addConstraint(anEqRadConstr);
+ mySlvsConstraints.push_back(anEqRadConstr.h);
+ } else if (aBaseIter->type == SLVS_E_ARC_OF_CIRCLE) {
+ // Workaround to avoid problems in SolveSpace.
+ // The symmetry of two arcs will be done using symmetry of three points on these arcs:
+ // start point, end point, and any other point on the arc
+ Slvs_hEntity aBaseArcPoints[3] = {
+ aBaseIter->point[1],
+ aBaseIter->point[2],
+ SLVS_E_UNKNOWN};
+ Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point
+ aMirrorIter->point[2],
+ aMirrorIter->point[1],
+ SLVS_E_UNKNOWN};
+
+ Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter};
+ Slvs_hEntity aBothMiddlePoints[2];
+ for (int i = 0; i < 2; i++) {
+ double x, y;
+ calculateMiddlePoint(aBothArcs[i], 0.5, x, y);
+ Slvs_Param aParamX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), x);
+ Slvs_Param aParamY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), y);
+ aParamX.h = myStorage->addParameter(aParamX);
+ aParamY.h = myStorage->addParameter(aParamY);
+ Slvs_Entity aPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aParamX.h, aParamY.h);
+ aBothMiddlePoints[i] = myStorage->addEntity(aPoint);
+ // additional constraint point-on-curve
+ Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_CIRCLE, myGroup->getWorkplaneId(),
+ 0.0, aBothMiddlePoints[i], SLVS_E_UNKNOWN, aBothArcs[i].h, SLVS_E_UNKNOWN);
+ aPonCircConstr.h = myStorage->addConstraint(aPonCircConstr);
+ mySlvsConstraints.push_back(aPonCircConstr.h);
+ if (i == 0) {
+ // additional constraint for the point to be in the middle of a base arc
+ Slvs_Entity aLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aBothArcs[i].point[1], aBothMiddlePoints[i]);
+ aLine1.h = myStorage->addEntity(aLine1);
+ Slvs_Entity aLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aBothArcs[i].point[2], aBothMiddlePoints[i]);
+ aLine2.h = myStorage->addEntity(aLine2);
+ Slvs_Constraint aMiddleConstr = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(),
+ 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aLine1.h, aLine2.h);
+ aMiddleConstr.h = myStorage->addConstraint(aMiddleConstr);
+ mySlvsConstraints.push_back(aMiddleConstr.h);
+ }
+ }
+
+ aBaseArcPoints[2] = aBothMiddlePoints[0];
+ aMirrorArcPoints[2] = aBothMiddlePoints[1];
+ for (int ind = 0; ind < 3; ind++) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0,
+ aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+ }
}
-void SketchSolver_ConstraintMirror::update()
+void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint)
{
cleanErrorMsg();
- AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
- if (aMirroredRefList->size() != myNumberOfObjects) {
- remove();
- process();
- return;
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+ if (aMirroredRefList->size() != myNumberOfObjects) {
+ remove(myBaseConstraint);
+ process();
+ return;
+ }
}
SketchSolver_Constraint::update();
}
-////bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
-////{
-//// cleanErrorMsg();
-//// if (theConstraint && theConstraint != myBaseConstraint)
-//// return false;
-//// bool isFullyRemoved = true;
-//// std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
-//// for (; aCIter != mySlvsConstraints.end(); aCIter++)
-//// isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
-//// mySlvsConstraints.clear();
-////
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
-//// for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
-//// myStorage->removeEntity(aFeatIt->second);
-////
-//// if (isFullyRemoved) {
-//// myFeatureMap.clear();
-//// myAttributeMap.clear();
-//// myValueMap.clear();
-//// } else
-//// cleanRemovedEntities();
-//// return true;
-////}
-////
-////bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
-////{
-//// // First of all, check the mirror line is changed.
-//// // It may be changed to one of mirrored lines, which is already in this constraint
-//// // (this case is not marked as attribute changing)
-//// ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
-//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-//// aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-//// if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
-//// return true;
-//// FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
-//// if (!aMirrorLine)
-//// return true;
-////
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
-//// if (aMirrorIter == myFeatureMap.end())
-//// return true;
-////
-//// // Check the entity is not used as mirror line
-//// std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
-//// for (; aCIter != mySlvsConstraints.end(); aCIter++) {
-//// Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
-//// if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
-//// continue;
-//// if (aMirrorConstr.entityA != aMirrorIter->second)
-//// return true;
-//// else break; // check just one symmetric constraint
-//// }
-////
-//// // Base verification
-//// return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
-////}
-
-////void SketchSolver_ConstraintMirror::makeMirrorEntity(
-//// const Slvs_Entity& theBase,
-//// const Slvs_Entity& theMirror,
-//// const double theMirrorLine[]) const
-////{
-//// Slvs_hEntity aBasePoint[4];
-//// Slvs_hEntity aMirrorPoint[4];
-//// for (int i = 0; i < 4; i++) {
-//// aBasePoint[i] = theBase.point[i];
-//// aMirrorPoint[i] = theMirror.point[i];
-//// }
-//// if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
-//// Slvs_hEntity aTmp = aMirrorPoint[2];
-//// aMirrorPoint[2] = aMirrorPoint[1];
-//// aMirrorPoint[1] = aTmp;
-//// adjustArcPoints(theBase);
-//// }
-//// if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
-//// aBasePoint[0] = theBase.h;
-//// aMirrorPoint[0] = theMirror.h;
-//// }
-////
-//// // Mirror line parameters
-//// std::shared_ptr<GeomAPI_XY> aLinePoints[2];
-//// for (int i = 0; i < 2; i++)
-//// aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
-//// new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
-//// // direction of a mirror line
-//// std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
-//// new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
-//// // orthogonal direction
-//// aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
-////
-//// Slvs_hConstraint aFixed; // transient variable
-//// for (int i = 0; i < 4; i++) {
-//// if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
-//// continue;
-//// // check the mirror point is not fixed
-//// if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
-//// continue;
-////
-//// Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
-//// double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
-//// double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
-//// std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
-////
-//// std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
-//// new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
-//// double aDist = aVec->dot(aDir->xy());
-//// aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
-////
-//// Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
-//// Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
-//// myStorage->updateParameter(aParam);
-//// aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
-//// myStorage->updateParameter(aParam);
-//// }
-////}
-////
-////void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
-////{
-//// Slvs_Param aParam;
-//// Slvs_Entity aPoint;
-//// double anArcParams[3][2];
-//// for (int i = 0; i < 3; i++) {
-//// aPoint = myStorage->getEntity(theArc.point[i]);
-//// for (int j = 0; j < 2; j++) {
-//// aParam = myStorage->getParameter(aPoint.param[j]);
-//// anArcParams[i][j] = aParam.val;
-//// if (i > 0)
-//// anArcParams[i][j] -= anArcParams[0][j];
-//// }
-//// }
-//// double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
-//// double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
-//// if (std::fabs(aRad2 - aDist2) < tolerance)
-//// return; // nothing to update (last point already on the arc)
-//// if (aDist2 < tolerance)
-//// return; // unable to update
-//// double aCoeff = std::sqrt(aRad2 / aDist2);
-//// anArcParams[2][0] *= aCoeff;
-//// anArcParams[2][1] *= aCoeff;
-////
-//// // Update last point
-//// aPoint = myStorage->getEntity(theArc.point[2]);
-//// for (int i = 0; i < 2; i++) {
-//// aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
-//// anArcParams[0][i] + anArcParams[2][i]);
-//// myStorage->updateParameter(aParam);
-//// }
-////}
+bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+ std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+ mySlvsConstraints.clear();
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+ for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+ myStorage->removeEntity(aFeatIt->second);
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+ return true;
+}
+
+bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint)
+{
+ // First of all, check the mirror line is changed.
+ // It may be changed to one of mirrored lines, which is already in this constraint
+ // (this case is not marked as attribute changing)
+ ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
+ return true;
+ FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object());
+ if (!aMirrorLine)
+ return true;
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aMirrorIter = myFeatureMap.find(aMirrorLine);
+ if (aMirrorIter == myFeatureMap.end())
+ return true;
+
+ // Check the entity is not used as mirror line
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+ Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter);
+ if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE)
+ continue;
+ if (aMirrorConstr.entityA != aMirrorIter->second)
+ return true;
+ else break; // check just one symmetric constraint
+ }
+
+ // Base verification
+ return SketchSolver_Constraint::checkAttributesChanged(theConstraint);
+}
+
+void SketchSolver_ConstraintMirror::makeMirrorEntity(
+ const Slvs_Entity& theBase,
+ const Slvs_Entity& theMirror,
+ const double theMirrorLine[]) const
+{
+ Slvs_hEntity aBasePoint[4];
+ Slvs_hEntity aMirrorPoint[4];
+ for (int i = 0; i < 4; i++) {
+ aBasePoint[i] = theBase.point[i];
+ aMirrorPoint[i] = theMirror.point[i];
+ }
+ if (theBase.type == SLVS_E_ARC_OF_CIRCLE) {
+ Slvs_hEntity aTmp = aMirrorPoint[2];
+ aMirrorPoint[2] = aMirrorPoint[1];
+ aMirrorPoint[1] = aTmp;
+ adjustArcPoints(theBase);
+ }
+ if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
+ aBasePoint[0] = theBase.h;
+ aMirrorPoint[0] = theMirror.h;
+ }
+
+ // Mirror line parameters
+ std::shared_ptr<GeomAPI_XY> aLinePoints[2];
+ for (int i = 0; i < 2; i++)
+ aLinePoints[i] = std::shared_ptr<GeomAPI_XY>(
+ new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1]));
+ // direction of a mirror line
+ std::shared_ptr<GeomAPI_Dir2d> aDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0))));
+ // orthogonal direction
+ aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
+
+ Slvs_hConstraint aFixed; // transient variable
+ for (int i = 0; i < 4; i++) {
+ if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
+ continue;
+ // check the mirror point is not fixed
+ if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
+ continue;
+
+ Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
+ double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
+ double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
+ std::shared_ptr<GeomAPI_XY> aPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aBaseX, aBaseY));
+
+ std::shared_ptr<GeomAPI_XY> aVec = std::shared_ptr<GeomAPI_XY>(
+ new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y()));
+ double aDist = aVec->dot(aDir->xy());
+ aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist));
+
+ Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]);
+ Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x());
+ myStorage->updateParameter(aParam);
+ aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y());
+ myStorage->updateParameter(aParam);
+ }
+}
+
+void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
+{
+ Slvs_Param aParam;
+ Slvs_Entity aPoint;
+ double anArcParams[3][2];
+ for (int i = 0; i < 3; i++) {
+ aPoint = myStorage->getEntity(theArc.point[i]);
+ for (int j = 0; j < 2; j++) {
+ aParam = myStorage->getParameter(aPoint.param[j]);
+ anArcParams[i][j] = aParam.val;
+ if (i > 0)
+ anArcParams[i][j] -= anArcParams[0][j];
+ }
+ }
+ double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
+ double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
+ if (std::fabs(aRad2 - aDist2) < tolerance)
+ return; // nothing to update (last point already on the arc)
+ if (aDist2 < tolerance)
+ return; // unable to update
+ double aCoeff = std::sqrt(aRad2 / aDist2);
+ anArcParams[2][0] *= aCoeff;
+ anArcParams[2][1] *= aCoeff;
+
+ // Update last point
+ aPoint = myStorage->getEntity(theArc.point[2]);
+ for (int i = 0; i < 2; i++) {
+ aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
+ anArcParams[0][i] + anArcParams[2][i]);
+ myStorage->updateParameter(aParam);
+ }
+}
void SketchSolver_ConstraintMirror::adjustConstraint()
{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
- for (; aCIt != aConstraints.end(); ++aCIt)
- if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC)
- aBuilder->adjustConstraint(*aCIt);
-
-//// AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
-//// myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
-//// if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
-//// myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-//// return;
-//// }
-//// ResultConstructionPtr aRC =
-//// std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
-//// FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
-//// std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
-//// if (aMirLineIter == myFeatureMap.end())
-//// return;
-//// Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
-////
-//// Slvs_Constraint aMirror;
-//// double aStartEnd[4];
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
-//// for (int j = 0; j < 2; j++)
-//// aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
-//// }
-////
-//// // Calculate length of the mirror line and create temporary constraint
-//// double aLength = sqrt((aStartEnd[2] - aStartEnd[0]) * (aStartEnd[2] - aStartEnd[0]) +
-//// (aStartEnd[3] - aStartEnd[1]) * (aStartEnd[3] - aStartEnd[1]));
-//// if (aLength < tolerance) {
-//// if (myMirrorLineLength < 1.0)
-//// myMirrorLineLength = 1.0;
-//// } else
-//// myMirrorLineLength = aLength;
-//// std::list<Slvs_Constraint> aDist = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
-//// std::list<Slvs_Constraint>::const_iterator aDIt = aDist.begin();
-//// for (; aDIt != aDist.end(); ++aDIt)
-//// if ((aDIt->ptA == aMirrorLine.point[0] && aDIt->ptB == aMirrorLine.point[1]) ||
-//// (aDIt->ptA == aMirrorLine.point[1] && aDIt->ptB == aMirrorLine.point[0]))
-//// break; // length of mirror line is already set
-//// if (aDIt == aDist.end()) {
-//// // check the points of mirror line is not fixed
-//// Slvs_hConstraint aFixed;
-//// if (!myStorage->isPointFixed(aMirrorLine.point[0], aFixed, true) ||
-//// !myStorage->isPointFixed(aMirrorLine.point[1], aFixed, true)) {
-//// // Add length constraint
-//// aMirror = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_PT_DISTANCE,
-//// myGroup->getWorkplaneId(), aLength, aMirrorLine.point[0], aMirrorLine.point[1],
-//// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aMirror.h = myStorage->addConstraint(aMirror);
-//// myStorage->addTemporaryConstraint(aMirror.h);
-//// }
-//// }
-////
-//// // Search mirror between middle points on the arcs and recompute their coordinates
-//// std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
-//// std::list<Slvs_Constraint> aMirrorPonCirc;
-//// std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
-//// std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
-//// for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
-//// aMirror = myStorage->getConstraint(*aConstrIter);
-//// if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
-//// continue;
-//// if (aMirror.entityA != aMirrorLine.h)
-//// continue; // don't update another Mirror constraints
-//// Slvs_Constraint aPonCircA, aPonCircB;
-//// aPonCircA.h = SLVS_E_UNKNOWN;
-//// aPonCircB.h = SLVS_E_UNKNOWN;
-//// std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
-//// for (; aPtIter != aPonCirc.end(); aPtIter++) {
-//// if (aMirror.ptA == aPtIter->ptA)
-//// aPonCircA = *aPtIter;
-//// if (aMirror.ptB == aPtIter->ptA)
-//// aPonCircB = *aPtIter;
-//// }
-//// if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
-//// continue;
-//// aMirrorPonCirc.push_back(aMirror);
-//// // Store point IDs to avoid their recalculation twice
-//// aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
-//// aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
-//// }
-////
-//// // Recalculate positions of mirroring points
-//// std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
-//// std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
-//// for (; aMirIter != aMirrorList.end(); aMirIter++) {
-//// if (aMirIter->entityA != aMirrorLine.h)
-//// continue; // don't update another Mirror constraints
-//// if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
-//// continue; // Avoid mirroring points on circles
-//// Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
-//// Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
-//// makeMirrorEntity(aBase, aMirror, aStartEnd);
-//// }
-////
-//// bool aNeedToResolve = myStorage->isNeedToResolve();
-//// for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
-//// // Make centers of arcs symmetric
-//// Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
-//// Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
-//// Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
-//// Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
-//// makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
-//// // Calculate middle point for base arc and mirrored point on mirror arc
-//// aBasePoint = myStorage->getEntity(aMirIter->ptA);
-//// Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
-//// Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
-//// calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
-//// myStorage->updateParameter(aParamX);
-//// myStorage->updateParameter(aParamY);
-//// aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
-//// aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
-//// aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
-//// calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
-//// myStorage->updateParameter(aParamX);
-//// myStorage->updateParameter(aParamY);
-//// }
-//// // Restore previous value to avoid looped recalculations of sketch
-//// myStorage->setNeedToResolve(aNeedToResolve);
+ AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ ResultConstructionPtr aRC =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aMirLineAttr->object());
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aMirLineAttr->object());
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aMirLineIter = myFeatureMap.find(aFeature);
+ if (aMirLineIter == myFeatureMap.end())
+ return;
+ Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
+
+ Slvs_Constraint aMirror;
+ double aStartEnd[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
+ for (int j = 0; j < 2; j++)
+ aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
+ }
+
+ // Calculate length of the mirror line and create temporary constraint
+ double aLength = sqrt((aStartEnd[2] - aStartEnd[0]) * (aStartEnd[2] - aStartEnd[0]) +
+ (aStartEnd[3] - aStartEnd[1]) * (aStartEnd[3] - aStartEnd[1]));
+ if (aLength < tolerance) {
+ if (myMirrorLineLength < 1.0)
+ myMirrorLineLength = 1.0;
+ } else
+ myMirrorLineLength = aLength;
+ std::list<Slvs_Constraint> aDist = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+ std::list<Slvs_Constraint>::const_iterator aDIt = aDist.begin();
+ for (; aDIt != aDist.end(); ++aDIt)
+ if ((aDIt->ptA == aMirrorLine.point[0] && aDIt->ptB == aMirrorLine.point[1]) ||
+ (aDIt->ptA == aMirrorLine.point[1] && aDIt->ptB == aMirrorLine.point[0]))
+ break; // length of mirror line is already set
+ if (aDIt == aDist.end()) {
+ // check the points of mirror line is not fixed
+ Slvs_hConstraint aFixed;
+ if (!myStorage->isPointFixed(aMirrorLine.point[0], aFixed, true) ||
+ !myStorage->isPointFixed(aMirrorLine.point[1], aFixed, true)) {
+ // Add length constraint
+ aMirror = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_PT_DISTANCE,
+ myGroup->getWorkplaneId(), aLength, aMirrorLine.point[0], aMirrorLine.point[1],
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aMirror.h = myStorage->addConstraint(aMirror);
+ myStorage->addTemporaryConstraint(aMirror.h);
+ }
+ }
+
+ // Search mirror between middle points on the arcs and recompute their coordinates
+ std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
+ std::list<Slvs_Constraint> aMirrorPonCirc;
+ std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
+ std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
+ for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
+ aMirror = myStorage->getConstraint(*aConstrIter);
+ if (aMirror.type != SLVS_C_SYMMETRIC_LINE)
+ continue;
+ if (aMirror.entityA != aMirrorLine.h)
+ continue; // don't update another Mirror constraints
+ Slvs_Constraint aPonCircA, aPonCircB;
+ aPonCircA.h = SLVS_E_UNKNOWN;
+ aPonCircB.h = SLVS_E_UNKNOWN;
+ std::list<Slvs_Constraint>::iterator aPtIter = aPonCirc.begin();
+ for (; aPtIter != aPonCirc.end(); aPtIter++) {
+ if (aMirror.ptA == aPtIter->ptA)
+ aPonCircA = *aPtIter;
+ if (aMirror.ptB == aPtIter->ptA)
+ aPonCircB = *aPtIter;
+ }
+ if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
+ continue;
+ aMirrorPonCirc.push_back(aMirror);
+ // Store point IDs to avoid their recalculation twice
+ aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
+ aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
+ }
+
+ // Recalculate positions of mirroring points
+ std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
+ std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
+ for (; aMirIter != aMirrorList.end(); aMirIter++) {
+ if (aMirIter->entityA != aMirrorLine.h)
+ continue; // don't update another Mirror constraints
+ if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
+ continue; // Avoid mirroring points on circles
+ Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
+ Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
+ makeMirrorEntity(aBase, aMirror, aStartEnd);
+ }
+
+ bool aNeedToResolve = myStorage->isNeedToResolve();
+ for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
+ // Make centers of arcs symmetric
+ Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
+ Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
+ Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
+ Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
+ makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
+ // Calculate middle point for base arc and mirrored point on mirror arc
+ aBasePoint = myStorage->getEntity(aMirIter->ptA);
+ Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
+ Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
+ calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
+ myStorage->updateParameter(aParamX);
+ myStorage->updateParameter(aParamY);
+ aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
+ aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
+ aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
+ calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
+ myStorage->updateParameter(aParamX);
+ myStorage->updateParameter(aParamY);
+ }
+ // Restore previous value to avoid looped recalculations of sketch
+ myStorage->setNeedToResolve(aNeedToResolve);
}
/// Constructor based on SketchPlugin constraint
SketchSolver_ConstraintMirror(ConstraintPtr theConstraint) :
SketchSolver_Constraint(theConstraint),
- myNumberOfObjects(0)////,
-//// myMirrorLineLength(0.0)
+ myNumberOfObjects(0),
+ myMirrorLineLength(0.0)
{}
+ virtual int getType() const
+ { return SLVS_C_SYMMETRIC_LINE; }
+
/// \brief Update constraint
- virtual void update();
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
-//// /// \brief Tries to remove constraint
-//// /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-//// virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
- /// \brief Generate list of attributes of constraint in order useful for constraints
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
{ /* do nothing here */ }
-//// /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
-//// /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
-//// /// \return \c true if some attributes are changed
-//// virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
+ /// \brief Verify the attributes of constraint are changed (and constraint need to rebuild)
+ /// \param[in] theConstraint constraint, which attributes should be checked (if NULL, the myBaseConstraint is used)
+ /// \return \c true if some attributes are changed
+ virtual bool checkAttributesChanged(ConstraintPtr theConstraint);
/// \brief Generate list of entities of mirror constraint
/// \param[out] theMirrorLine entity corresponding to mirror line
/// \param[out] theBaseEntities list of entities to mirror
/// \param[out] theMirrorEntities list of mirrored entities
- void getAttributes(EntityWrapperPtr& theMirrorLine,
- std::vector<EntityWrapperPtr>& theBaseEntities,
- std::vector<EntityWrapperPtr>& theMirrorEntities);
+ void getAttributes(Slvs_Entity& theMirrorLine,
+ std::vector<Slvs_Entity>& theBaseEntities,
+ std::vector<Slvs_Entity>& theMirrorEntities);
/// \brief This method is used in derived objects to check consistence of constraint.
/// E.g. the distance between line and point may be signed.
virtual void adjustConstraint();
private:
-//// /// \brief Change parameters of entities to be symmetric relative a line,
-//// /// given by array of parameters (coordinates of first and last points)
-//// void makeMirrorEntity(const Slvs_Entity& theBase,
-//// const Slvs_Entity& theMirror,
-//// const double theMirrorLine[]) const;
-////
-//// /// \brief Precisely update last point to be on arc
-//// void adjustArcPoints(const Slvs_Entity& theArc) const;
+ /// \brief Change parameters of entities to be symmetric relative a line,
+ /// given by array of parameters (coordinates of first and last points)
+ void makeMirrorEntity(const Slvs_Entity& theBase,
+ const Slvs_Entity& theMirror,
+ const double theMirrorLine[]) const;
+
+ /// \brief Precisely update last point to be on arc
+ void adjustArcPoints(const Slvs_Entity& theArc) const;
private:
size_t myNumberOfObjects; ///< number of previously mirrored objects
-//// double myMirrorLineLength; ///< length of mirror line (should be always greater than 0)
+ double myMirrorLineLength; ///< length of mirror line (should be always greater than 0)
};
#endif
#include <SketchSolver_ConstraintMovement.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
+#include <SketchSolver_Group.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
-#include <GeomDataAPI_Point2D.h>
-
+SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
+ : SketchSolver_ConstraintRigid(theFeature)
+{
+ process();
+}
void SketchSolver_ConstraintMovement::process()
{
cleanErrorMsg();
- if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are initialized
+ if (!myBaseFeature || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- ParameterWrapperPtr aValue;
- getAttributes(aValue, myMovedEntities);
- if (!myErrorMsg.empty() || myMovedEntities.empty()) {
- // Nothing to move, clear the feature to avoid changing its group
- // after removing the Movement constraint.
- myBaseFeature = FeaturePtr();
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ bool isFullyMoved;
+ getAttributes(aValue, anEntities, isFullyMoved);
+ if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
return;
- }
- std::vector<EntityWrapperPtr>::iterator anEntIt = myMovedEntities.begin();
- for (; anEntIt != myMovedEntities.end(); ++anEntIt)
- fixFeature(*anEntIt);
+ if (isFullyMoved)
+ fixFeature();
+ else {
+ std::vector<Slvs_hEntity>::iterator anEntIt = anEntities.begin();
+ for (; anEntIt != anEntities.end(); ++anEntIt)
+ fixPoint(*anEntIt);
+ }
}
-static std::list<EntityWrapperPtr> movedEntities(
- EntityWrapperPtr theOld, StoragePtr theOldStorage,
- EntityWrapperPtr theNew, StoragePtr theNewStorage)
+void SketchSolver_ConstraintMovement::getAttributes(
+ double& theValue,
+ std::vector<Slvs_hEntity>& theAttributes,
+ bool& theIsFullyMoved)
{
- bool isFullyMoved = true;
- std::list<EntityWrapperPtr> aMoved;
- if (theOld->isEqual(theNew))
- return aMoved;
-
- std::list<EntityWrapperPtr> anOldSubs = theOld->subEntities();
- std::list<EntityWrapperPtr> aNewSubs = theNew->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anOldIt = anOldSubs.begin();
- std::list<EntityWrapperPtr>::const_iterator aNewIt = aNewSubs.begin();
- for (; anOldIt != anOldSubs.end() && aNewIt != aNewSubs.end(); ++anOldIt, ++aNewIt) {
- std::list<EntityWrapperPtr> aMovedSubs = movedEntities(
- *anOldIt, theOldStorage, *aNewIt, theNewStorage);
- if (aMovedSubs.size() != 1 || aMovedSubs.front() != *anOldIt)
- isFullyMoved = false;
- aMoved.insert(aMoved.end(), aMovedSubs.begin(), aMovedSubs.end());
+ bool isComplexFeature = false;
+ theValue = 0.0;
+ theIsFullyMoved = true;
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = SLVS_E_UNKNOWN;
+ Slvs_hEntity anEntMaxID = myStorage->entityMaxID();
+ anEntityID = myGroup->getFeatureId(myBaseFeature);
+ if (anEntityID == SLVS_E_UNKNOWN) {
+ anEntityID = changeEntity(myBaseFeature, aType);
+ if (anEntityID == SLVS_E_UNKNOWN) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+
+ // Check the entity is complex
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ if (anEntity.point[0] != SLVS_E_UNKNOWN)
+ isComplexFeature = true;
+ else // simple entity
+ theAttributes.push_back(anEntityID);
}
- if (isFullyMoved) {
- aMoved.clear();
- aMoved.push_back(theOld);
+ else {
+ myFeatureMap[myBaseFeature] = anEntityID;
+ isComplexFeature = true;
+ }
+
+ int aNbOutOfGroup = 0;
+ if (isComplexFeature) {
+ std::list<AttributePtr> aPoints =
+ myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anIt = aPoints.begin();
+ for (; anIt != aPoints.end(); ++anIt) {
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(*anIt);
+ Slvs_hEntity anAttr = aFound != myAttributeMap.end() ?
+ aFound->second : myGroup->getAttributeId(*anIt);
+ Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
+
+ // Check the attribute changes coordinates
+ std::shared_ptr<GeomDataAPI_Point2D> aPt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
+ // Check the entity is not lying in the current group or it is not moved
+ if (anAttr == SLVS_E_UNKNOWN || anAttrEnt.group != myGroup->getId() ||
+ (anAttr <= anEntMaxID && !isMoved(aPt, anAttrEnt))) {
+ if (anAttrEnt.group == SLVS_G_OUTOFGROUP)
+ ++aNbOutOfGroup;
+ theIsFullyMoved = false;
+ }
+ else {
+ theAttributes.push_back(anAttr);
+ // update point coordinates
+ Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr);
+ double aNewPos[2] = {aPt->x(), aPt->y()};
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = myStorage->getParameter(anAttrEnt.param[i]);
+ aParam.val = aNewPos[i];
+ myStorage->updateParameter(aParam);
+ }
+ }
+ }
+ }
+
+ // Additional checking, which leads to fix whole feature, if it has fixed points
+ if (!theIsFullyMoved) {
+ Slvs_Entity aFeature = myStorage->getEntity(anEntityID);
+ int aNbPoints = 4;
+ while (aNbPoints > 0 && aFeature.point[aNbPoints-1] == SLVS_E_UNKNOWN)
+ --aNbPoints;
+ if (aNbPoints == aNbOutOfGroup + (int)theAttributes.size()) {
+ theIsFullyMoved = true;
+ return;
+ }
+ }
+
+ // Leave only points which are used in constraints
+ if (myStorage->isUsedByConstraints(anEntityID))
+ return;
+ std::vector<Slvs_hEntity>::iterator anIt = theAttributes.begin();
+ while (anIt != theAttributes.end()) {
+ if (myStorage->isUsedByConstraints(*anIt))
+ ++anIt;
+ else {
+ int aShift = anIt - theAttributes.begin();
+ theAttributes.erase(anIt);
+ anIt = theAttributes.begin() + aShift;
+ }
}
- return aMoved;
}
+bool SketchSolver_ConstraintMovement::isMoved(
+ std::shared_ptr<GeomDataAPI_Point2D> thePoint, const Slvs_Entity& theEntity)
+{
+ double aDeltaX = myStorage->getParameter(theEntity.param[0]).val;
+ double aDeltaY = myStorage->getParameter(theEntity.param[1]).val;
+ aDeltaX -= thePoint->x();
+ aDeltaY -= thePoint->y();
+ return aDeltaX * aDeltaX + aDeltaY * aDeltaY >= tolerance * tolerance;
+}
-void SketchSolver_ConstraintMovement::getAttributes(
- ParameterWrapperPtr& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
+void SketchSolver_ConstraintMovement::fixFeature()
{
- // There will be build entities, according to the fixed feature, in the separate storage
- // to check whether any point is moved
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- StoragePtr anOtherStorage = aBuilder->createStorage(myGroupID);
- anOtherStorage->setSketch(myStorage->sketch());
- if (!anOtherStorage->update(myBaseFeature, myGroupID))
- return;
- EntityWrapperPtr aNewEntity = anOtherStorage->entity(myBaseFeature);
- EntityWrapperPtr anOldEntity = myStorage->entity(myBaseFeature);
+ Slvs_hEntity anEntID = fixedEntity();
- std::list<EntityWrapperPtr> aMoved;
- if (aNewEntity && anOldEntity)
- aMoved = movedEntities(anOldEntity, myStorage, aNewEntity, anOtherStorage);
- else {
- // get attributes moved
- std::list<AttributePtr> anAttrList =
- myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt) {
- aNewEntity = anOtherStorage->entity(*anIt);
- anOldEntity = myStorage->entity(*anIt);
- if (!aNewEntity || !anOldEntity)
- continue;
- std::list<EntityWrapperPtr> aMovedAttr = movedEntities(
- anOldEntity, myStorage, aNewEntity, anOtherStorage);
- aMoved.insert(aMoved.end(), aMovedAttr.begin(), aMovedAttr.end());
- }
+ std::string aKind;
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIt = myFeatureMap.begin();
+ for (; aFIt != myFeatureMap.end() && aKind.empty(); ++aFIt)
+ if (aFIt->second == anEntID)
+ aKind = aFIt->first->getKind();
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator anAtIt = myAttributeMap.begin();
+ for (; anAtIt != myAttributeMap.end() && aKind.empty(); ++anAtIt)
+ if (anAtIt->second == anEntID)
+ aKind = anAtIt->first->attributeType();
+
+ if (aKind == SketchPlugin_Line::ID()) {
+ Slvs_Entity aLine = myStorage->getEntity(anEntID);
+ fixLine(aLine);
+ }
+ else if (aKind == SketchPlugin_Arc::ID()) {
+ Slvs_Entity anArc = myStorage->getEntity(anEntID);
+ fixArc(anArc);
+ }
+ else if (aKind == SketchPlugin_Circle::ID()) {
+ Slvs_Entity aCirc = myStorage->getEntity(anEntID);
+ fixCircle(aCirc);
+ }
+ else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) {
+ fixPoint(anEntID);
}
- theAttributes.clear();
- theAttributes.insert(theAttributes.begin(), aMoved.begin(), aMoved.end());
}
+
#define SketchSolver_ConstraintMovement_H_
#include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintRigid.h>
+
+#include <GeomDataAPI_Point2D.h>
/** \class SketchSolver_ConstraintMovement
* \ingroup Plugins
- * \brief Stores data to the Fixed constraint for the moved feature only
+ * \brief Stores data of Rigid (Fixed) constraint for the moved feature only
*/
-class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
+class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintRigid
{
private:
/// Creates constraint to manage the given constraint from plugin
SketchSolver_ConstraintMovement(ConstraintPtr theConstraint)
- : SketchSolver_ConstraintFixed(theConstraint)
+ : SketchSolver_ConstraintRigid(theConstraint)
{}
public:
/// Creates temporary constraint based on feature
- SketchSolver_ConstraintMovement(FeaturePtr theFeature)
- : SketchSolver_ConstraintFixed(theFeature)
- {}
+ SketchSolver_ConstraintMovement(FeaturePtr theFeature);
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
/// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled (list of moved entities or attributes)
- virtual void getAttributes(ParameterWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ /// \param[out] theAttributes list of attributes to be filled
+ /// \param[out] theIsFullyMoved shows that the feature is moved, in other case only one point of the feature is shifted
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes, bool& theIsFullyMoved);
+
+ /// \brief Fixed feature basing on its type
+ virtual void fixFeature();
private:
- std::vector<EntityWrapperPtr> myMovedEntities; ///< list of entities that are moved
+ /// \brief Check the coordinates of point are differ than coordinates of correponding SolveSpace entity
+ bool isMoved(std::shared_ptr<GeomDataAPI_Point2D> thePoint, const Slvs_Entity& theEntity);
};
#endif
#include <SketchSolver_ConstraintMulti.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-////#include <SketchPlugin_Arc.h>
-////
-////#include <ModelAPI_AttributeDouble.h>
+#include <SketchPlugin_Arc.h>
+
+#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <math.h>
-
-void SketchSolver_ConstraintMulti::getEntitiesAndCopies(
- std::list< std::list<EntityWrapperPtr> >& theEntAndCopies)
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+void SketchSolver_ConstraintMulti::processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies)
{
- DataPtr aData = myBaseConstraint->data();
-
- // Lists of objects and number of copies
- AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
- myNumberOfObjects = anInitialRefList->size();
- myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
- if (myNumberOfCopies <= 0)
- return;
+ // Keep all objects unchanged (only initial object may be changed by user)
+ myCircsAndCopies.clear();
+ std::vector<std::vector<Slvs_hEntity> >::const_iterator anEntIt = theEntAndCopies.begin();
+ std::vector<Slvs_hEntity>::const_iterator aCpIt;
+ for (; anEntIt != theEntAndCopies.end(); ++anEntIt) {
+ std::vector<Slvs_hEntity> aCircs;
+ aCpIt = anEntIt->begin();
+ // Obtain initial points
+ Slvs_Entity anInitial = myStorage->getEntity(*aCpIt);
+ if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D)
+ myInitialPoints.insert(anInitial.h);
+ else {
+ for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++)
+ myInitialPoints.insert(anInitial.point[i]);
+ }
- AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
- if (!aRefList || aRefList->size() == 0) {
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
- return;
- }
+ // Fix the copies
+ for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) {
+ const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt);
+ std::vector<Slvs_hConstraint> aNewConstr;
+ if (anEntity.type == SLVS_E_CIRCLE) {
+ aCircs.push_back(anEntity.distance);
+ // for circles we fix only center
+ aNewConstr = myStorage->fixEntity(anEntity.point[0]);
+ } else
+ aNewConstr = myStorage->fixEntity(*aCpIt);
+ if (anEntity.type == SLVS_E_ARC_OF_CIRCLE)
+ aCircs.push_back(anEntity.h);
+ mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end());
+ }
- FeaturePtr aFeature;
- std::list<EntityWrapperPtr> anEntities; // list of transformed entities
- std::list<ObjectPtr> anObjectList = aRefList->list();
- std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
- while (anObjIt != anObjectList.end()) {
- anEntities.clear();
- for (int i = 0; i <= myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
- aFeature = ModelAPI_Feature::feature(*anObjIt);
- if (!aFeature)
- continue;
-
- myStorage->update(aFeature);
- anEntities.push_back(myStorage->entity(aFeature));
+ if (!aCircs.empty()) {
+ if (anInitial.type == SLVS_E_CIRCLE)
+ aCircs.insert(aCircs.begin(), anInitial.distance);
+ else
+ aCircs.insert(aCircs.begin(), anInitial.h);
+ myCircsAndCopies.push_back(aCircs);
}
- if (!anEntities.empty())
- theEntAndCopies.push_back(anEntities);
}
}
-
-////void SketchSolver_ConstraintMulti::processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies)
-////{
-//// // Keep all objects unchanged (only initial object may be changed by user)
-//// myCircsAndCopies.clear();
-//// std::vector<std::vector<Slvs_hEntity> >::const_iterator anEntIt = theEntAndCopies.begin();
-//// std::vector<Slvs_hEntity>::const_iterator aCpIt;
-//// for (; anEntIt != theEntAndCopies.end(); ++anEntIt) {
-//// std::vector<Slvs_hEntity> aCircs;
-//// aCpIt = anEntIt->begin();
-//// // Obtain initial points
-//// Slvs_Entity anInitial = myStorage->getEntity(*aCpIt);
-//// if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D)
-//// myInitialPoints.insert(anInitial.h);
-//// else {
-//// for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++)
-//// myInitialPoints.insert(anInitial.point[i]);
-//// }
-////
-//// // Fix the copies
-//// for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) {
-//// const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt);
-//// std::vector<Slvs_hConstraint> aNewConstr;
-//// if (anEntity.type == SLVS_E_CIRCLE) {
-//// aCircs.push_back(anEntity.distance);
-//// // for circles we fix only center
-//// aNewConstr = myStorage->fixEntity(anEntity.point[0]);
-//// } else
-//// aNewConstr = myStorage->fixEntity(*aCpIt);
-//// if (anEntity.type == SLVS_E_ARC_OF_CIRCLE)
-//// aCircs.push_back(anEntity.h);
-//// mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end());
-//// }
-////
-//// if (!aCircs.empty()) {
-//// if (anInitial.type == SLVS_E_CIRCLE)
-//// aCircs.insert(aCircs.begin(), anInitial.distance);
-//// else
-//// aCircs.insert(aCircs.begin(), anInitial.h);
-//// myCircsAndCopies.push_back(aCircs);
-//// }
-//// }
-////}
-
-void SketchSolver_ConstraintMulti::update(bool isForce)
+void SketchSolver_ConstraintMulti::update(ConstraintPtr theConstraint)
{
cleanErrorMsg();
- AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
- if (anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies) {
- remove();
- process();
- return;
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
+ if (anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies) {
+ remove(myBaseConstraint);
+ process();
+ return;
+ }
}
- // update derivative object
updateLocal();
- if (isForce)
- myAdjusted = false;
- // update parent object
SketchSolver_Constraint::update();
}
-////bool SketchSolver_ConstraintMulti::remove()
-////{
-//// cleanErrorMsg();
-//// if (theConstraint && theConstraint != myBaseConstraint)
-//// return false;
-//// bool isFullyRemoved = true;
-//// std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
-//// for (; aCIter != mySlvsConstraints.end(); aCIter++)
-//// isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
-//// mySlvsConstraints.clear();
-////
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
-//// for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
-//// myStorage->removeEntity(aFeatIt->second);
-//// myStorage->removeUnusedEntities();
-////
-//// std::map<FeaturePtr, Slvs_hEntity> aFeatureMapCopy = myFeatureMap;
-////
-//// if (isFullyRemoved) {
-//// myFeatureMap.clear();
-//// myAttributeMap.clear();
-//// myValueMap.clear();
-//// } else
-//// cleanRemovedEntities();
-////
-//// // Restore initial features
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = aFeatureMapCopy.begin();
-//// for (; aFIter != aFeatureMapCopy.end(); ++aFIter)
-//// {
-//// if (myFeatureMap.find(aFIter->first) != myFeatureMap.end())
-//// continue; // the feature was not removed
-//// Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first);
-//// if (anEntity != SLVS_E_UNKNOWN)
-//// myFeatureMap[aFIter->first] = anEntity;
-//// }
-////
-//// // Clear list of rotated points
-//// myPointsAndCopies.clear();
-//// myInitialPoints.clear();
-////
-//// return true;
-////}
-
-////void SketchSolver_ConstraintMulti::addFeature(FeaturePtr theFeature)
-////{
-//// SketchSolver_Constraint::addFeature(theFeature);
-////
-//// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.find(theFeature);
-//// if (aFeatIt == myFeatureMap.end())
-//// return;
-////
-//// // store list of points of the feature
-//// const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second);
-//// for (int i = 0; i < 4; i++)
-//// if (theEntity.point[i] != SLVS_E_UNKNOWN)
-//// myPointsJustUpdated.insert(theEntity.point[i]);
-////}
+bool SketchSolver_ConstraintMulti::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+ std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+ mySlvsConstraints.clear();
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+ for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+ myStorage->removeEntity(aFeatIt->second);
+ myStorage->removeUnusedEntities();
+
+ std::map<FeaturePtr, Slvs_hEntity> aFeatureMapCopy = myFeatureMap;
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ } else
+ cleanRemovedEntities();
+
+ // Restore initial features
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = aFeatureMapCopy.begin();
+ for (; aFIter != aFeatureMapCopy.end(); ++aFIter)
+ {
+ if (myFeatureMap.find(aFIter->first) != myFeatureMap.end())
+ continue; // the feature was not removed
+ Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first);
+ if (anEntity != SLVS_E_UNKNOWN)
+ myFeatureMap[aFIter->first] = anEntity;
+ }
+
+ // Clear list of rotated points
+ myPointsAndCopies.clear();
+ myInitialPoints.clear();
+
+ return true;
+}
+
+void SketchSolver_ConstraintMulti::addFeature(FeaturePtr theFeature)
+{
+ SketchSolver_Constraint::addFeature(theFeature);
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.find(theFeature);
+ if (aFeatIt == myFeatureMap.end())
+ return;
+
+ // store list of points of the feature
+ const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second);
+ for (int i = 0; i < 4; i++)
+ if (theEntity.point[i] != SLVS_E_UNKNOWN)
+ myPointsJustUpdated.insert(theEntity.point[i]);
+}
void SketchSolver_ConstraintMulti::adjustConstraint()
{
if (myAdjusted)
return; // constraint already adjusted, don't do it once again
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin();
- for (; anIt != aConstraints.end(); ++anIt)
- aBuilder->adjustConstraint(*anIt);
- myStorage->addConstraint(myBaseConstraint, aConstraints);
-
-//// double aRelCoord[2] = {0.0, 0.0}; // relative coordinates of point
-//// double anAbsCoord[2] = {0.0, 0.0}; // absolute coordinates of point
-////
-//// std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
-//// std::list<Slvs_Constraint>::const_iterator aCoIt;
-////
-//// // Update positions of all points to satisfy angles
-//// std::vector< std::vector<Slvs_hEntity> >::const_iterator aPointsIter = myPointsAndCopies.begin();
-//// std::vector<Slvs_hEntity>::const_iterator aCopyIter;
-//// for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) {
-//// aCopyIter = aPointsIter->begin();
-//// const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
-//// for (int i = 0; i < 2; i++)
-//// anAbsCoord[i] = myStorage->getParameter(anInitial.param[i]).val;
-//// getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
-////
-//// // if the point is coincident with another one which is temporary fixed (moved by user),
-//// // we will update its position correspondingly
-//// Slvs_hConstraint aFixed;
-//// for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) {
-//// if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) ||
-//// (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) {
-//// Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA;
-//// if (!myStorage->isTemporary(aFixed) &&
-//// myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end())
-//// continue; // nothing to change
-////
-//// const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId);
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]);
-//// const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]);
-//// anInitParam.val = anOtherParam.val;
-//// myStorage->updateParameter(anInitParam);
-//// anAbsCoord[i] = anOtherParam.val;
-//// }
-//// getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
-//// }
-//// }
-////
-//// // update copied points
-//// aCopyIter = aPointsIter->begin();
-//// for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-//// // transform coordinates
-//// transformRelative(aRelCoord[0], aRelCoord[1]);
-//// getAbsolute(aRelCoord[0], aRelCoord[1], anAbsCoord[0], anAbsCoord[1]);
-////
-//// const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter);
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]);
-//// aParam.val = anAbsCoord[i];
-//// myStorage->updateParameter(aParam);
-//// }
-//// }
-//// }
-////
-//// std::list<Slvs_Constraint> aDiamConstr;
-//// for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) {
-//// aCopyIter = aPointsIter->begin();
-//// const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
-//// if (anInitial.type == SLVS_E_DISTANCE) {
-//// const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]);
-//// for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-//// const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter);
-//// Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]);
-//// aCopyRad.val = anInitRad.val;
-//// myStorage->updateParameter(aCopyRad);
-//// }
-//// } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) {
-//// const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]);
-//// const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]);
-////
-//// if (aDiamConstr.empty())
-//// aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
-//// // Calculate diameter of initial arc
-//// double aDiam = 0.0;
-//// for (int i = 0; i < 2; i++) {
-//// double d = myStorage->getParameter(aStartEnt.param[i]).val -
-//// myStorage->getParameter(aCenterEnt.param[i]).val;
-//// aDiam += d * d;
-//// }
-//// aDiam = sqrt(aDiam) * 2.0;
-//// // Update the Diameter constraints of copied arcs
-//// for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
-//// std::list<Slvs_Constraint>::iterator aDCIt = aDiamConstr.begin();
-//// for (; aDCIt != aDiamConstr.end(); ++aDCIt)
-//// if (aDCIt->entityA == *aCopyIter) {
-//// aDCIt->valA = aDiam;
-//// myStorage->updateConstraint(*aDCIt);
-//// aDiamConstr.erase(aDCIt);
-//// break;
-//// }
-//// }
-//// }
-//// }
-////
-//// myPointsJustUpdated.clear();
+ double aRelCoord[2] = {0.0, 0.0}; // relative coordinates of point
+ double anAbsCoord[2] = {0.0, 0.0}; // absolute coordinates of point
+
+ std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+ std::list<Slvs_Constraint>::const_iterator aCoIt;
+
+ // Update positions of all points to satisfy angles
+ std::vector< std::vector<Slvs_hEntity> >::const_iterator aPointsIter = myPointsAndCopies.begin();
+ std::vector<Slvs_hEntity>::const_iterator aCopyIter;
+ for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) {
+ aCopyIter = aPointsIter->begin();
+ const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
+ for (int i = 0; i < 2; i++)
+ anAbsCoord[i] = myStorage->getParameter(anInitial.param[i]).val;
+ getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
+
+ // if the point is coincident with another one which is temporary fixed (moved by user),
+ // we will update its position correspondingly
+ Slvs_hConstraint aFixed;
+ for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) {
+ if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) ||
+ (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) {
+ Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA;
+ if (!myStorage->isTemporary(aFixed) &&
+ myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end())
+ continue; // nothing to change
+
+ const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]);
+ const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]);
+ anInitParam.val = anOtherParam.val;
+ myStorage->updateParameter(anInitParam);
+ anAbsCoord[i] = anOtherParam.val;
+ }
+ getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]);
+ }
+ }
+
+ // update copied points
+ aCopyIter = aPointsIter->begin();
+ for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+ // transform coordinates
+ transformRelative(aRelCoord[0], aRelCoord[1]);
+ getAbsolute(aRelCoord[0], aRelCoord[1], anAbsCoord[0], anAbsCoord[1]);
+
+ const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]);
+ aParam.val = anAbsCoord[i];
+ myStorage->updateParameter(aParam);
+ }
+ }
+ }
+
+ std::list<Slvs_Constraint> aDiamConstr;
+ for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) {
+ aCopyIter = aPointsIter->begin();
+ const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter);
+ if (anInitial.type == SLVS_E_DISTANCE) {
+ const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]);
+ for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+ const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter);
+ Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]);
+ aCopyRad.val = anInitRad.val;
+ myStorage->updateParameter(aCopyRad);
+ }
+ } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) {
+ const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]);
+ const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]);
+
+ if (aDiamConstr.empty())
+ aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+ // Calculate diameter of initial arc
+ double aDiam = 0.0;
+ for (int i = 0; i < 2; i++) {
+ double d = myStorage->getParameter(aStartEnt.param[i]).val -
+ myStorage->getParameter(aCenterEnt.param[i]).val;
+ aDiam += d * d;
+ }
+ aDiam = sqrt(aDiam) * 2.0;
+ // Update the Diameter constraints of copied arcs
+ for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) {
+ std::list<Slvs_Constraint>::iterator aDCIt = aDiamConstr.begin();
+ for (; aDCIt != aDiamConstr.end(); ++aDCIt)
+ if (aDCIt->entityA == *aCopyIter) {
+ aDCIt->valA = aDiam;
+ myStorage->updateConstraint(*aDCIt);
+ aDiamConstr.erase(aDCIt);
+ break;
+ }
+ }
+ }
+ }
+
+ myPointsJustUpdated.clear();
myAdjusted = true;
}
-////void SketchSolver_ConstraintMulti::checkCoincidence()
-////{
-//// std::vector< std::vector<Slvs_hEntity> > aFilteredPoints; // points are filtered by their positions
-////
-//// std::vector< std::vector<Slvs_hEntity> >::const_iterator aPCIt = myPointsAndCopies.begin();
-//// std::vector<Slvs_hEntity>::const_iterator aCIt;
-//// for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) {
-//// aCIt = aPCIt->begin();
-//// // Skip first element, focus the copies only
-//// for (++aCIt; aCIt != aPCIt->end(); ++aCIt) {
-//// std::vector< std::vector<Slvs_hEntity> >::iterator aFilterIt = aFilteredPoints.begin();
-//// for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt)
-//// if (myStorage->isEqual(*aCIt, aFilterIt->front())) {
-//// aFilterIt->push_back(*aCIt);
-//// break;
-//// }
-//// if (aFilterIt == aFilteredPoints.end()) {
-//// std::vector<Slvs_hEntity> aNewFilter(1, *aCIt);
-//// aFilteredPoints.push_back(aNewFilter);
-//// }
-//// }
-//// }
-////
-//// // Check the coicidence of filtered points and remove extra fixation.
-//// // Also check separated points which are not fixed.
-//// std::vector< std::vector<Slvs_hEntity> >::iterator aFPIt = aFilteredPoints.begin();
-//// for (; aFPIt != aFilteredPoints.end(); ++aFPIt) {
-//// if (aFPIt->size() <= 1)
-//// continue;
-//// std::vector<Slvs_hEntity>::iterator anIt1, anIt2;
-//// for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) {
-//// for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) {
-//// Slvs_hConstraint aFixed1, aFixed2;
-//// bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1);
-//// bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2);
-//// if (myStorage->isCoincident(*anIt1, *anIt2)) {
-//// if (!isFixed1 && isFixed2) {
-//// Slvs_hEntity aTmp = *anIt1;
-//// *anIt1 = *anIt2;
-//// *anIt2 = aTmp;
-//// } else if (isFixed1 && isFixed2) {
-//// // remove fixing of the second point
-//// myStorage->removeConstraint(aFixed2);
-//// std::vector<Slvs_hConstraint>::iterator aRemoveIt = mySlvsConstraints.begin();
-//// for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt)
-//// if (*aRemoveIt == aFixed2) {
-//// mySlvsConstraints.erase(aRemoveIt);
-//// break;
-//// }
-//// }
-//// } else {
-//// bool isFixed[2] = {
-//// myStorage->isPointFixed(*anIt1, aFixed1, true),
-//// myStorage->isPointFixed(*anIt2, aFixed2, true)
-//// };
-////
-//// Slvs_hEntity aPoint[2] = {*anIt1, *anIt2};
-//// for (int i = 0; i < 2; i++)
-//// if (!isFixed[i]) {
-//// Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
-//// SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-//// aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aConstraint.h = myStorage->addConstraint(aConstraint);
-//// mySlvsConstraints.push_back(aConstraint.h);
-//// }
-//// }
-//// }
-//// }
-//// }
-////}
+void SketchSolver_ConstraintMulti::checkCoincidence()
+{
+ std::vector< std::vector<Slvs_hEntity> > aFilteredPoints; // points are filtered by their positions
+
+ std::vector< std::vector<Slvs_hEntity> >::const_iterator aPCIt = myPointsAndCopies.begin();
+ std::vector<Slvs_hEntity>::const_iterator aCIt;
+ for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) {
+ aCIt = aPCIt->begin();
+ // Skip first element, focus the copies only
+ for (++aCIt; aCIt != aPCIt->end(); ++aCIt) {
+ std::vector< std::vector<Slvs_hEntity> >::iterator aFilterIt = aFilteredPoints.begin();
+ for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt)
+ if (myStorage->isEqual(*aCIt, aFilterIt->front())) {
+ aFilterIt->push_back(*aCIt);
+ break;
+ }
+ if (aFilterIt == aFilteredPoints.end()) {
+ std::vector<Slvs_hEntity> aNewFilter(1, *aCIt);
+ aFilteredPoints.push_back(aNewFilter);
+ }
+ }
+ }
+
+ // Check the coicidence of filtered points and remove extra fixation.
+ // Also check separated points which are not fixed.
+ std::vector< std::vector<Slvs_hEntity> >::iterator aFPIt = aFilteredPoints.begin();
+ for (; aFPIt != aFilteredPoints.end(); ++aFPIt) {
+ if (aFPIt->size() <= 1)
+ continue;
+ std::vector<Slvs_hEntity>::iterator anIt1, anIt2;
+ for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) {
+ for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) {
+ Slvs_hConstraint aFixed1, aFixed2;
+ bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1);
+ bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2);
+ if (myStorage->isCoincident(*anIt1, *anIt2)) {
+ if (!isFixed1 && isFixed2) {
+ Slvs_hEntity aTmp = *anIt1;
+ *anIt1 = *anIt2;
+ *anIt2 = aTmp;
+ } else if (isFixed1 && isFixed2) {
+ // remove fixing of the second point
+ myStorage->removeConstraint(aFixed2);
+ std::vector<Slvs_hConstraint>::iterator aRemoveIt = mySlvsConstraints.begin();
+ for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt)
+ if (*aRemoveIt == aFixed2) {
+ mySlvsConstraints.erase(aRemoveIt);
+ break;
+ }
+ }
+ } else {
+ bool isFixed[2] = {
+ myStorage->isPointFixed(*anIt1, aFixed1, true),
+ myStorage->isPointFixed(*anIt2, aFixed2, true)
+ };
+
+ Slvs_hEntity aPoint[2] = {*anIt1, *anIt2};
+ for (int i = 0; i < 2; i++)
+ if (!isFixed[i]) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+ }
+ }
+ }
+}
myAdjusted(false)
{}
-//// virtual int getType() const
-//// { return SLVS_C_UNKNOWN; }
+ virtual int getType() const
+ { return SLVS_C_UNKNOWN; }
/// \brief Update constraint
- virtual void update(bool isForce = false);
-
-//// /// \brief Tries to remove constraint
-//// /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
-//// virtual bool remove();
-////
-//// /// \brief Adds a feature to constraint and create its analogue in SolveSpace
-//// virtual void addFeature(FeaturePtr theFeature);
-////
-//// /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
-//// virtual void refresh()
-//// {
-//// myAdjusted = false;
-//// SketchSolver_Constraint::refresh();
-//// }
-
-//// /// \brief Verifies, the coincidence between points of copied entities appears or disappears,
-//// /// and removes or adds fixing of corresponding points.
-//// void checkCoincidence();
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Adds a feature to constraint and create its analogue in SolveSpace
+ virtual void addFeature(FeaturePtr theFeature);
+
+ /// \brief Update SketchPlugin attributes using the data obtained from SolveSpace entities
+ virtual void refresh()
+ {
+ myAdjusted = false;
+ SketchSolver_Constraint::refresh();
+ }
+
+ /// \brief Verifies, the coincidence between points of copied entities appears or disappears,
+ /// and removes or adds fixing of corresponding points.
+ void checkCoincidence();
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
{ /* do nothing here */ }
/// \brief Collect entities and their copies, like circles and arcs
- void getEntitiesAndCopies(std::list< std::list<EntityWrapperPtr> >& theEntAndCopies);
+ void processEntities(const std::vector< std::vector<Slvs_hEntity> >& theEntAndCopies);
/// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
{ /* do nothing here */ }
/// \brief This method is used in derived objects to check consistence of constraint.
/// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
virtual const std::string& nameNbObjects() = 0;
-
-////protected:
-//// /// \brief Convert absolute coordinates to relative coordinates
-//// virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY) = 0;
-//// /// \brief Convert relative coordinates to absolute coordinates
-//// virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY) = 0;
-//// /// \brief Apply transformation for relative coordinates
-//// virtual void transformRelative(double& theX, double& theY) = 0;
+
+protected:
+ /// \brief Convert absolute coordinates to relative coordinates
+ virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY) = 0;
+ /// \brief Convert relative coordinates to absolute coordinates
+ virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY) = 0;
+ /// \brief Apply transformation for relative coordinates
+ virtual void transformRelative(double& theX, double& theY) = 0;
protected:
- int myNumberOfObjects; ///< number of previous initial objects
- int myNumberOfCopies; ///< number of previous copies of initial objects
-
-//// std::vector< std::vector<Slvs_hEntity> > myPointsAndCopies; ///< list of initial points and their copies
-//// std::vector< std::vector<Slvs_hEntity> > myCircsAndCopies; ///< list of circles and their copies (to change their radii together)
-////
-//// std::set<Slvs_hEntity> myPointsJustUpdated; ///< list of points touched by user
-//// std::set<Slvs_hEntity> myInitialPoints; ///< list of points containing initial objects
+ size_t myNumberOfObjects; ///< number of previous initial objects
+ size_t myNumberOfCopies; ///< number of previous copies of initial objects
+
+ std::vector< std::vector<Slvs_hEntity> > myPointsAndCopies; ///< list of initial points and their copies
+ std::vector< std::vector<Slvs_hEntity> > myCircsAndCopies; ///< list of circles and their copies (to change their radii together)
+
+ std::set<Slvs_hEntity> myPointsJustUpdated; ///< list of points touched by user
+ std::set<Slvs_hEntity> myInitialPoints; ///< list of points containing initial objects
bool myAdjusted; ///< the constraint is already adjusted (to not do it several times)
};
#include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-////#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Arc.h>
#include <SketchPlugin_MultiRotation.h>
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeInteger.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
#include <math.h>
void SketchSolver_ConstraintMultiRotation::getAttributes(
- EntityWrapperPtr& theCenter, double& theAngle,
- std::list< std::list<EntityWrapperPtr> >& theEntities)
+ Slvs_hEntity& theCenter, double& theAngle,
+ std::vector< std::vector<Slvs_hEntity> >& thePoints,
+ std::vector< std::vector<Slvs_hEntity> >& theEntities)
{
DataPtr aData = myBaseConstraint->data();
theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
}
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aCenterAttr, aType);
+ theCenter = anEntityID;
+
+ // Lists of objects and number of copies
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ myNumberOfObjects = anInitialRefList->size();
+ myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
+ if (myNumberOfCopies <= 0)
+ return;
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (!aRefList) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
- myType = CONSTRAINT_MULTI_ROTATION;
-
- myStorage->update(aCenterAttr, GID_OUTOFGROUP);
- theCenter = myStorage->entity(aCenterAttr);
-
- getEntitiesAndCopies(theEntities);
-
-//// // Lists of objects and number of copies
-//// AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-//// aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
-//// myNumberOfObjects = anInitialRefList->size();
-//// myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-//// if (myNumberOfCopies <= 0)
-//// return;
-//// AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-//// myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-//// if (!aRefList) {
-//// myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-//// return;
-//// }
-////
-//// // Obtain all points of initial features and store them into separate lists
-//// // containing their translated copies.
-//// // Also all circles and arc collected too, because they will be constrained by equal radii.
-//// FeaturePtr aFeature;
-//// ResultConstructionPtr aRC;
-//// static const size_t MAX_POINTS = 3;
-//// std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
-//// std::vector<Slvs_hEntity> anEntities;
-//// std::list<ObjectPtr> anObjectList = aRefList->list();
-//// std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
-//// while (anObjectIter != anObjectList.end()) {
-//// for (size_t i = 0; i < MAX_POINTS; ++i)
-//// aPoints[i].clear();
-//// anEntities.clear();
-////
-//// for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
-//// aFeature = ModelAPI_Feature::feature(*anObjectIter);
-//// if (!aFeature)
-//// continue;
-//// anEntityID = changeEntity(aFeature, aType);
-//// anEntities.push_back(anEntityID);
-//// Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
-//// switch (aType) {
-//// case SLVS_E_POINT_IN_2D:
-//// case SLVS_E_POINT_IN_3D:
-//// aPoints[0].push_back(anEntityID);
-//// break;
-//// case SLVS_E_LINE_SEGMENT:
-//// aPoints[0].push_back(anEntity.point[0]); // start point of line
-//// aPoints[1].push_back(anEntity.point[1]); // end point of line
-//// break;
-//// case SLVS_E_CIRCLE:
-//// aPoints[0].push_back(anEntity.point[0]); // center of circle
-//// break;
-//// case SLVS_E_ARC_OF_CIRCLE:
-//// aPoints[0].push_back(anEntity.point[0]); // center of arc
-//// aPoints[1].push_back(anEntity.point[1]); // start point of arc
-//// aPoints[2].push_back(anEntity.point[2]); // end point of arc
-//// break;
-//// default:
-//// myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-//// return;
-//// }
-//// }
-////
-//// for (size_t i = 0; i < MAX_POINTS; ++i)
-//// if (!aPoints[i].empty())
-//// thePoints.push_back(aPoints[i]);
-//// if (!anEntities.empty())
-//// theEntities.push_back(anEntities);
-//// }
+ // Obtain all points of initial features and store them into separate lists
+ // containing their translated copies.
+ // Also all circles and arc collected too, because they will be constrained by equal radii.
+ FeaturePtr aFeature;
+ ResultConstructionPtr aRC;
+ static const size_t MAX_POINTS = 3;
+ std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
+ std::vector<Slvs_hEntity> anEntities;
+ std::list<ObjectPtr> anObjectList = aRefList->list();
+ std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+ while (anObjectIter != anObjectList.end()) {
+ for (size_t i = 0; i < MAX_POINTS; ++i)
+ aPoints[i].clear();
+ anEntities.clear();
+
+ for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+ aFeature = ModelAPI_Feature::feature(*anObjectIter);
+ if (!aFeature)
+ continue;
+ anEntityID = changeEntity(aFeature, aType);
+ anEntities.push_back(anEntityID);
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ switch (aType) {
+ case SLVS_E_POINT_IN_2D:
+ case SLVS_E_POINT_IN_3D:
+ aPoints[0].push_back(anEntityID);
+ break;
+ case SLVS_E_LINE_SEGMENT:
+ aPoints[0].push_back(anEntity.point[0]); // start point of line
+ aPoints[1].push_back(anEntity.point[1]); // end point of line
+ break;
+ case SLVS_E_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of circle
+ break;
+ case SLVS_E_ARC_OF_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of arc
+ aPoints[1].push_back(anEntity.point[1]); // start point of arc
+ aPoints[2].push_back(anEntity.point[2]); // end point of arc
+ break;
+ default:
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ }
+
+ for (size_t i = 0; i < MAX_POINTS; ++i)
+ if (!aPoints[i].empty())
+ thePoints.push_back(aPoints[i]);
+ if (!anEntities.empty())
+ theEntities.push_back(anEntities);
+ }
}
void SketchSolver_ConstraintMultiRotation::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
/// TODO: Put error message here
return;
}
-//// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-//// update(myBaseConstraint);
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- EntityWrapperPtr aRotationCenter;
- std::list<std::list<EntityWrapperPtr> > anEntitiesAndCopies;
- getAttributes(aRotationCenter, myAngle, anEntitiesAndCopies);
+ std::vector<std::vector<Slvs_hEntity> > anEntitiesAndCopies;
+ getAttributes(myRotationCenter, myAngle, myPointsAndCopies, anEntitiesAndCopies);
if (!myErrorMsg.empty())
return;
-//// // Set the rotation center unchanged during constraint recalculation
-//// Slvs_Constraint aConstraint;
-//// if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
-//// aConstraint = Slvs_MakeConstraint(
-//// SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-//// myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aConstraint.h = myStorage->addConstraint(aConstraint);
-//// mySlvsConstraints.push_back(aConstraint.h);
-//// }
-
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aRotConstraints;
-
- std::list< std::list<EntityWrapperPtr> >::iterator anEntIt = anEntitiesAndCopies.begin();
- for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) {
- std::list<ConstraintWrapperPtr> aNewConstraints =
- aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
- myAngle, aRotationCenter, EntityWrapperPtr(), *anEntIt);
- aRotConstraints.insert(aRotConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
+ // Set the rotation center unchanged during constraint recalculation
+ Slvs_Constraint aConstraint;
+ if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
+ aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
}
- myStorage->addConstraint(myBaseConstraint, aRotConstraints);
myAdjusted = false;
-//// processEntities(anEntitiesAndCopies);
+ processEntities(anEntitiesAndCopies);
adjustConstraint();
}
myAdjusted = false;
// update angle value
myAngle = aValue;
-
- // update center
- AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID());
- if (myStorage->update(aCenterAttr, myGroupID)) {
- myStorage->update(aCenterAttr, GID_UNKNOWN);
- myAdjusted = false;
- }
}
void SketchSolver_ConstraintMultiRotation::adjustConstraint()
myStorage->setNeedToResolve(false);
return;
}
-//// if (myAdjusted)
-//// return;
-////
-//// std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
-//// std::list<Slvs_Constraint>::const_iterator aCoIt;
-////
-//// // Check overconstrained on rotation center (if it is coincident with other fixed point)
-//// Slvs_hConstraint aFixedCenter;
-//// if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) {
-//// Slvs_hConstraint aFixed;
-//// for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt)
-//// if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) ||
-//// (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) {
-//// // Un-fix the center
-//// myStorage->removeConstraint(aFixedCenter);
-//// std::vector<Slvs_hConstraint>::iterator aSCIt = mySlvsConstraints.begin();
-//// for (; aSCIt != mySlvsConstraints.end(); ++aSCIt)
-//// if (*aSCIt == aFixedCenter) {
-//// mySlvsConstraints.erase(aSCIt);
-//// break;
-//// }
-//// }
-//// }
-////
-//// // Obtain coordinates of rotation center
-//// Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
-//// myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val;
-//// myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val;
-////
-//// myRotationVal[0] = sin(myAngle * PI / 180.0);
-//// myRotationVal[1] = cos(myAngle * PI / 180.0);
-////
-
- const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
- for (; aCIt != aConstraints.end(); ++aCIt)
- (*aCIt)->setValue(myAngle);
+ if (myAdjusted)
+ return;
+
+ std::list<Slvs_Constraint> aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+ std::list<Slvs_Constraint>::const_iterator aCoIt;
+
+ // Check overconstrained on rotation center (if it is coincident with other fixed point)
+ Slvs_hConstraint aFixedCenter;
+ if (myStorage->isPointFixed(myRotationCenter, aFixedCenter, false)) {
+ Slvs_hConstraint aFixed;
+ for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt)
+ if ((aCoIt->ptA == myRotationCenter && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) ||
+ (aCoIt->ptB == myRotationCenter && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) {
+ // Un-fix the center
+ myStorage->removeConstraint(aFixedCenter);
+ std::vector<Slvs_hConstraint>::iterator aSCIt = mySlvsConstraints.begin();
+ for (; aSCIt != mySlvsConstraints.end(); ++aSCIt)
+ if (*aSCIt == aFixedCenter) {
+ mySlvsConstraints.erase(aSCIt);
+ break;
+ }
+ }
+ }
+
+ // Obtain coordinates of rotation center
+ Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
+ myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val;
+ myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val;
+
+ myRotationVal[0] = sin(myAngle * PI / 180.0);
+ myRotationVal[1] = cos(myAngle * PI / 180.0);
SketchSolver_ConstraintMulti::adjustConstraint();
}
-////void SketchSolver_ConstraintMultiRotation::getRelative(
-//// double theAbsX, double theAbsY, double& theRelX, double& theRelY)
-////{
-//// theRelX = theAbsX - myCenterCoord[0];
-//// theRelY = theAbsY - myCenterCoord[1];
-////}
-////
-////void SketchSolver_ConstraintMultiRotation::getAbsolute(
-//// double theRelX, double theRelY, double& theAbsX, double& theAbsY)
-////{
-//// theAbsX = theRelX + myCenterCoord[0];
-//// theAbsY = theRelY + myCenterCoord[1];
-////}
-////
-////void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
-////{
-//// // rotate direction
-//// // myRotationVal[0] = sinA, myRotationVal[1] = cosA
-//// double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
-//// theY = theX * myRotationVal[0] + theY * myRotationVal[1];
-//// theX = aTemp;
-////}
+void SketchSolver_ConstraintMultiRotation::getRelative(
+ double theAbsX, double theAbsY, double& theRelX, double& theRelY)
+{
+ theRelX = theAbsX - myCenterCoord[0];
+ theRelY = theAbsY - myCenterCoord[1];
+}
+
+void SketchSolver_ConstraintMultiRotation::getAbsolute(
+ double theRelX, double theRelY, double& theAbsX, double& theAbsY)
+{
+ theAbsX = theRelX + myCenterCoord[0];
+ theAbsY = theRelY + myCenterCoord[1];
+}
+
+void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY)
+{
+ // rotate direction
+ // myRotationVal[0] = sinA, myRotationVal[1] = cosA
+ double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0];
+ theY = theX * myRotationVal[0] + theY * myRotationVal[1];
+ theX = aTemp;
+}
const std::string& SketchSolver_ConstraintMultiRotation::nameNbObjects()
{
SketchSolver_ConstraintMulti(theConstraint)
{}
-//// virtual int getType() const
-//// { return SLVS_C_MULTI_ROTATION; }
+ virtual int getType() const
+ { return SLVS_C_MULTI_ROTATION; }
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
/// \brief Generate list of rotated entities
- /// \param[out] theCenter central point of rotation
+ /// \param[out] theCenter ID of central point of rotation
/// \param[out] theAngle rotation angle
- /// \param[out] theEntities list of entities and their rotated copies
- void getAttributes(EntityWrapperPtr& theCenter, double& theAngle,
- std::list< std::list<EntityWrapperPtr> >& theEntities);
+ /// \param[out] thePoints list of IDs of initial points and their rotated copies
+ /// \param[out] theEntities list of IDs of entities and their rotated copies
+ void getAttributes(Slvs_hEntity& theCenter, double& theAngle,
+ std::vector< std::vector<Slvs_hEntity> >& thePoints,
+ std::vector< std::vector<Slvs_hEntity> >& theEntities);
/// \brief This method is used in derived objects to check consistence of constraint.
virtual void adjustConstraint();
/// \brief Update parameters (called from base class)
virtual void updateLocal();
-////private:
-//// /// \brief Convert absolute coordinates to relative coordinates
-//// virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
-//// /// \brief Convert relative coordinates to absolute coordinates
-//// virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
-//// /// \brief Apply transformation for relative coordinates
-//// virtual void transformRelative(double& theX, double& theY);
+private:
+ /// \brief Convert absolute coordinates to relative coordinates
+ virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+ /// \brief Convert relative coordinates to absolute coordinates
+ virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+ /// \brief Apply transformation for relative coordinates
+ virtual void transformRelative(double& theX, double& theY);
private:
/// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
virtual const std::string& nameNbObjects();
-////private:
-//// Slvs_hEntity myRotationCenter; ///< ID of center of rotation
+private:
+ Slvs_hEntity myRotationCenter; ///< ID of center of rotation
double myAngle; ///< angle of rotation
-////
-//// double myCenterCoord[2]; ///< coordinates of rotation center
-//// double myRotationVal[2]; ///< sinus and cosine of rotation angle
+
+ double myCenterCoord[2]; ///< coordinates of rotation center
+ double myRotationVal[2]; ///< sinus and cosinus of rotation angle
};
#endif
#include <SketchSolver_ConstraintMultiTranslation.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-////#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Arc.h>
#include <SketchPlugin_MultiTranslation.h>
-////
-////#include <ModelAPI_AttributeDouble.h>
-////#include <ModelAPI_AttributeInteger.h>
-////#include <ModelAPI_AttributeRefAttr.h>
-////#include <ModelAPI_AttributeRefList.h>
-////#include <ModelAPI_ResultConstruction.h>
-////#include <ModelAPI_Data.h>
-////
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_XY.h>
-////
-////#include <math.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Data.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
void SketchSolver_ConstraintMultiTranslation::getAttributes(
- EntityWrapperPtr& theStartPoint, EntityWrapperPtr& theEndPoint,
- std::list< std::list<EntityWrapperPtr> >& theEntities)
+ Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+ std::vector< std::vector<Slvs_hEntity> >& thePoints,
+ std::vector< std::vector<Slvs_hEntity> >& theEntities)
{
DataPtr aData = myBaseConstraint->data();
AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
return;
}
- myType = CONSTRAINT_MULTI_TRANSLATION;
-
- myStorage->update(aStartPointAttr);
- theStartPoint = myStorage->entity(aStartPointAttr);
- myStorage->update(aEndPointAttr);
- theEndPoint = myStorage->entity(aEndPointAttr);
-
- getEntitiesAndCopies(theEntities);
-
-//// int aType = SLVS_E_UNKNOWN; // type of created entity
-//// Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
-//// if (anEntityID == SLVS_E_UNKNOWN)
-//// anEntityID = changeEntity(aStartPointAttr, aType);
-//// theStartPoint = anEntityID;
-//// anEntityID = myGroup->getAttributeId(aEndPointAttr);
-//// if (anEntityID == SLVS_E_UNKNOWN)
-//// anEntityID = changeEntity(aEndPointAttr, aType);
-//// theEndPoint = anEntityID;
-////
-//// // Lists of objects and number of copies
-//// AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-//// aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
-//// myNumberOfObjects = anInitialRefList->size();
-//// myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
-//// if (myNumberOfCopies <= 0)
-//// return;
-////
-//// AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-//// myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
-//// if (!aRefList) {
-//// myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-//// return;
-//// }
-////
-//// // Obtain all points of initial features and store them into separate lists
-//// // containing their translated copies.
-//// // Also all circles and arc collected too, because they will be constrained by equal radii.
-//// FeaturePtr aFeature;
-//// ResultConstructionPtr aRC;
-//// static const size_t MAX_POINTS = 3;
-//// std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
-//// std::vector<Slvs_hEntity> anEntities; // list of translated entities
-//// std::list<ObjectPtr> anObjectList = aRefList->list();
-//// std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
-//// while (anObjectIter != anObjectList.end()) {
-//// for (size_t i = 0; i < MAX_POINTS; i++)
-//// aPoints[i].clear();
-//// anEntities.clear();
-////
-//// for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
-//// aFeature = ModelAPI_Feature::feature(*anObjectIter);
-//// if (!aFeature)
-//// continue;
-//// anEntityID = changeEntity(aFeature, aType);
-//// anEntities.push_back(anEntityID);
-//// Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
-//// switch (aType) {
-//// case SLVS_E_POINT_IN_2D:
-//// case SLVS_E_POINT_IN_3D:
-//// aPoints[0].push_back(anEntityID);
-//// break;
-//// case SLVS_E_LINE_SEGMENT:
-//// aPoints[0].push_back(anEntity.point[0]); // start point of line
-//// aPoints[1].push_back(anEntity.point[1]); // end point of line
-//// break;
-//// case SLVS_E_CIRCLE:
-//// aPoints[0].push_back(anEntity.point[0]); // center of circle
-//// break;
-//// case SLVS_E_ARC_OF_CIRCLE:
-//// aPoints[0].push_back(anEntity.point[0]); // center of arc
-//// aPoints[1].push_back(anEntity.point[1]); // start point of arc
-//// aPoints[2].push_back(anEntity.point[2]); // end point of arc
-//// break;
-//// default:
-//// myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-//// return;
-//// }
-//// }
-////
-//// for (size_t i = 0; i < MAX_POINTS; ++i)
-//// if (!aPoints[i].empty())
-//// thePoints.push_back(aPoints[i]);
-//// if (!anEntities.empty())
-//// theEntities.push_back(anEntities);
-//// }
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aStartPointAttr, aType);
+ theStartPoint = anEntityID;
+ anEntityID = myGroup->getAttributeId(aEndPointAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aEndPointAttr, aType);
+ theEndPoint = anEntityID;
+
+ // Lists of objects and number of copies
+ AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ myNumberOfObjects = anInitialRefList->size();
+ myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
+ if (myNumberOfCopies <= 0)
+ return;
+
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (!aRefList) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ // Obtain all points of initial features and store them into separate lists
+ // containing their translated copies.
+ // Also all circles and arc collected too, because they will be constrained by equal radii.
+ FeaturePtr aFeature;
+ ResultConstructionPtr aRC;
+ static const size_t MAX_POINTS = 3;
+ std::vector<Slvs_hEntity> aPoints[MAX_POINTS]; // lists of points of features
+ std::vector<Slvs_hEntity> anEntities; // list of translated entities
+ std::list<ObjectPtr> anObjectList = aRefList->list();
+ std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+ while (anObjectIter != anObjectList.end()) {
+ for (size_t i = 0; i < MAX_POINTS; i++)
+ aPoints[i].clear();
+ anEntities.clear();
+
+ for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+ aFeature = ModelAPI_Feature::feature(*anObjectIter);
+ if (!aFeature)
+ continue;
+ anEntityID = changeEntity(aFeature, aType);
+ anEntities.push_back(anEntityID);
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ switch (aType) {
+ case SLVS_E_POINT_IN_2D:
+ case SLVS_E_POINT_IN_3D:
+ aPoints[0].push_back(anEntityID);
+ break;
+ case SLVS_E_LINE_SEGMENT:
+ aPoints[0].push_back(anEntity.point[0]); // start point of line
+ aPoints[1].push_back(anEntity.point[1]); // end point of line
+ break;
+ case SLVS_E_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of circle
+ break;
+ case SLVS_E_ARC_OF_CIRCLE:
+ aPoints[0].push_back(anEntity.point[0]); // center of arc
+ aPoints[1].push_back(anEntity.point[1]); // start point of arc
+ aPoints[2].push_back(anEntity.point[2]); // end point of arc
+ break;
+ default:
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ }
+
+ for (size_t i = 0; i < MAX_POINTS; ++i)
+ if (!aPoints[i].empty())
+ thePoints.push_back(aPoints[i]);
+ if (!anEntities.empty())
+ theEntities.push_back(anEntities);
+ }
}
void SketchSolver_ConstraintMultiTranslation::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
/// TODO: Put error message here
return;
}
-//// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-//// update(myBaseConstraint);
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
- EntityWrapperPtr aStartPoint, aEndPoint;
- std::list<std::list<EntityWrapperPtr> > anEntitiesAndCopies;
- getAttributes(aStartPoint, aEndPoint, anEntitiesAndCopies);
+ Slvs_hEntity aStartPoint, aEndPoint;
+ std::vector<std::vector<Slvs_hEntity> > anEntitiesAndCopies;
+ getAttributes(aStartPoint, aEndPoint, myPointsAndCopies, anEntitiesAndCopies);
if (!myErrorMsg.empty())
return;
-//// // Create translation line
-//// if (myTranslationLine == SLVS_E_UNKNOWN) {
-//// Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-//// myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
-//// aTranslationLine.h = myStorage->addEntity(aTranslationLine);
-//// myTranslationLine = aTranslationLine.h;
-//// } else {
-//// Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
-//// if (aTranslationLine.point[0] != aStartPoint || aTranslationLine.point[1] != aEndPoint) {
-//// aTranslationLine.point[0] = aStartPoint;
-//// aTranslationLine.point[1] = aEndPoint;
-//// myStorage->updateEntity(aTranslationLine);
-//// }
-//// }
-
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aTransConstraints;
-
- std::list< std::list<EntityWrapperPtr> >::iterator anEntIt = anEntitiesAndCopies.begin();
- for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) {
- std::list<ConstraintWrapperPtr> aNewConstraints =
- aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
- 0.0, aStartPoint, aEndPoint, *anEntIt);
- aTransConstraints.insert(aTransConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
+ // Create translation line
+ if (myTranslationLine == SLVS_E_UNKNOWN) {
+ Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
+ aTranslationLine.h = myStorage->addEntity(aTranslationLine);
+ myTranslationLine = aTranslationLine.h;
+ } else {
+ Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+ if (aTranslationLine.point[0] != aStartPoint || aTranslationLine.point[1] != aEndPoint) {
+ aTranslationLine.point[0] = aStartPoint;
+ aTranslationLine.point[1] = aEndPoint;
+ myStorage->updateEntity(aTranslationLine);
+ }
}
- myStorage->addConstraint(myBaseConstraint, aTransConstraints);
myAdjusted = false;
-//// processEntities(anEntitiesAndCopies);
+ processEntities(anEntitiesAndCopies);
adjustConstraint();
}
-////void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
-////{
-//// if (myAdjusted)
-//// return;
-////
-//// Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
-//// Slvs_hConstraint aFixed; // temporary variable
-//// // Set the translation line unchanged during constraint recalculation
-//// for (int i = 0; i < 2; i++) {
-//// if (myStorage->isPointFixed(aTranslationLine.point[i], aFixed, true))
-//// continue;
-//// Slvs_Constraint aConstraint = Slvs_MakeConstraint(
-//// SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-//// aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-//// aConstraint.h = myStorage->addConstraint(aConstraint);
-//// myStorage->addTemporaryConstraint(aConstraint.h);
-//// }
-////
-//// // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
-//// double aXY[4];
-//// for (int i = 0; i < 2; i++) {
-//// Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
-//// aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
-//// aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
-//// }
-//// myDelta[0] = aXY[2] - aXY[0];
-//// myDelta[1] = aXY[3] - aXY[1];
-//// if (fabs(myDelta[0]) + fabs(myDelta[1]) < tolerance) {
-//// myStorage->setNeedToResolve(false);
-//// return;
-//// }
-////
-//// SketchSolver_ConstraintMulti::adjustConstraint();
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::getRelative(
-//// double theAbsX, double theAbsY, double& theRelX, double& theRelY)
-////{
-//// theRelX = theAbsX;
-//// theRelY = theAbsY;
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::getAbsolute(
-//// double theRelX, double theRelY, double& theAbsX, double& theAbsY)
-////{
-//// theAbsX = theRelX;
-//// theAbsY = theRelY;
-////}
-////
-////void SketchSolver_ConstraintMultiTranslation::transformRelative(double& theX, double& theY)
-////{
-//// // translate coordinates
-//// theX += myDelta[0];
-//// theY += myDelta[1];
-////}
+void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
+{
+ if (myAdjusted)
+ return;
+
+ Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+ Slvs_hConstraint aFixed; // temporary variable
+ // Set the translation line unchanged during constraint recalculation
+ for (int i = 0; i < 2; i++) {
+ if (myStorage->isPointFixed(aTranslationLine.point[i], aFixed, true))
+ continue;
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ myStorage->addTemporaryConstraint(aConstraint.h);
+ }
+
+ // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
+ double aXY[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
+ aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
+ aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
+ }
+ myDelta[0] = aXY[2] - aXY[0];
+ myDelta[1] = aXY[3] - aXY[1];
+ if (fabs(myDelta[0]) + fabs(myDelta[1]) < tolerance) {
+ myStorage->setNeedToResolve(false);
+ return;
+ }
+
+ SketchSolver_ConstraintMulti::adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiTranslation::getRelative(
+ double theAbsX, double theAbsY, double& theRelX, double& theRelY)
+{
+ theRelX = theAbsX;
+ theRelY = theAbsY;
+}
+
+void SketchSolver_ConstraintMultiTranslation::getAbsolute(
+ double theRelX, double theRelY, double& theAbsX, double& theAbsY)
+{
+ theAbsX = theRelX;
+ theAbsY = theRelY;
+}
+
+void SketchSolver_ConstraintMultiTranslation::transformRelative(double& theX, double& theY)
+{
+ // translate coordinates
+ theX += myDelta[0];
+ theY += myDelta[1];
+}
const std::string& SketchSolver_ConstraintMultiTranslation::nameNbObjects()
{
public:
/// Constructor based on SketchPlugin constraint
SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) :
- SketchSolver_ConstraintMulti(theConstraint)////,
-//// myTranslationLine(SLVS_E_UNKNOWN)
+ SketchSolver_ConstraintMulti(theConstraint),
+ myTranslationLine(SLVS_E_UNKNOWN)
{}
-//// virtual int getType() const
-//// { return SLVS_C_MULTI_TRANSLATION; }
+ virtual int getType() const
+ { return SLVS_C_MULTI_TRANSLATION; }
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
/// \brief Generate list of translated entities
- /// \param[out] theStartPoint start point of translation
- /// \param[out] theEndPoint final point of translation
- /// \param[out] theEntities list of entities and their translated copies
- void getAttributes(EntityWrapperPtr& theStartPoint, EntityWrapperPtr& theEndPoint,
- std::list< std::list<EntityWrapperPtr> >& theEntities);
+ /// \param[out] theStartPoint ID of start point of translation
+ /// \param[out] theEndPoint ID of final point of translation
+ /// \param[out] thePoints list of IDs of initial points and their translated copies
+ /// \param[out] theEntities list of IDs of entities and their translated copies
+ void getAttributes(Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+ std::vector< std::vector<Slvs_hEntity> >& thePoints,
+ std::vector< std::vector<Slvs_hEntity> >& theEntities);
-//// /// \brief This method is used in derived objects to check consistence of constraint.
-//// virtual void adjustConstraint();
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ virtual void adjustConstraint();
/// \brief Update parameters (called from base class)
virtual void updateLocal()
{}
-////private:
-//// /// \brief Convert absolute coordinates to relative coordinates
-//// virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
-//// /// \brief Convert relative coordinates to absolute coordinates
-//// virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
-//// /// \brief Apply transformation for relative coordinates
-//// virtual void transformRelative(double& theX, double& theY);
+private:
+ /// \brief Convert absolute coordinates to relative coordinates
+ virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+ /// \brief Convert relative coordinates to absolute coordinates
+ virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+ /// \brief Apply transformation for relative coordinates
+ virtual void transformRelative(double& theX, double& theY);
private:
/// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
virtual const std::string& nameNbObjects();
-////private:
-//// Slvs_hEntity myTranslationLine; ///< ID of translation line
-////
-//// double myDelta[2]; ///< increment of translation
+private:
+ Slvs_hEntity myTranslationLine; ///< ID of translation line
+
+ double myDelta[2]; ///< increment of translation
};
#endif
--- /dev/null
+#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Group.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+SketchSolver_ConstraintParametric::SketchSolver_ConstraintParametric(AttributePtr theAttribute)
+ : SketchSolver_ConstraintRigid(ConstraintPtr()),
+ myBaseAttribute(theAttribute)
+{
+ process();
+}
+
+void SketchSolver_ConstraintParametric::process()
+{
+ cleanErrorMsg();
+ if (!myBaseAttribute || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ Slvs_hEntity anAttrID;
+ getAttributes(anAttrID);
+ if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
+ return;
+
+ myHorizLineID = SLVS_E_UNKNOWN;
+ myVertLineID = SLVS_E_UNKNOWN;
+
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (!aPoint)
+ return;
+ if (!aPoint->textX().empty()) {
+ // Create vertical line with fixed boundary point
+ Slvs_Entity aLine = createLine(aPoint->x(), -100.0, aPoint->x(), 100.0);
+ // Place point on line
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
+ aLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ myVertLineID = aLine.h;
+ myX = aPoint->x();
+ }
+ if (!aPoint->textY().empty()) {
+ // Create horizontal line with fixed boundary points
+ Slvs_Entity aLine = createLine(-100.0, aPoint->y(), 100.0, aPoint->y());
+ // Place point on line
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
+ aLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ myHorizLineID = aLine.h;
+ myY = aPoint->y();
+ }
+}
+
+
+void SketchSolver_ConstraintParametric::getAttributes(Slvs_hEntity& theAttributeID)
+{
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ theAttributeID = SLVS_E_UNKNOWN;
+ theAttributeID = myGroup->getAttributeId(myBaseAttribute);
+ if (theAttributeID == SLVS_E_UNKNOWN) {
+ theAttributeID = changeEntity(myBaseAttribute, aType);
+ if (theAttributeID == SLVS_E_UNKNOWN) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ }
+ else
+ myAttributeMap[myBaseAttribute] = theAttributeID;
+}
+
+
+void SketchSolver_ConstraintParametric::update(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (aPoint && ((!aPoint->textX().empty() && myVertLineID == SLVS_E_UNKNOWN) ||
+ (!aPoint->textY().empty() && myHorizLineID == SLVS_E_UNKNOWN))) {
+ remove();
+ process();
+ return;
+ }
+ }
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintParametric::refresh()
+{
+ Slvs_hEntity aBasePointID = myAttributeMap[myBaseAttribute];
+ const Slvs_Entity& aBasePoint = myStorage->getEntity(aBasePointID);
+ double aXY[2];
+ aXY[0] = myVertLineID != SLVS_E_UNKNOWN ? myX : myStorage->getParameter(aBasePoint.param[0]).val;
+ aXY[1] = myHorizLineID != SLVS_E_UNKNOWN ? myY : myStorage->getParameter(aBasePoint.param[1]).val;
+
+ std::list<Slvs_Constraint> aCoincidence = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+ std::list<Slvs_Constraint>::const_iterator aCIt = aCoincidence.begin();
+ for (; aCIt != aCoincidence.end(); ++aCIt) {
+ if (aCIt->ptA != aBasePointID && aCIt->ptB != aBasePointID)
+ continue;
+ Slvs_hEntity anOtherPointID = aCIt->ptA == aBasePointID ? aCIt->ptB : aCIt->ptA;
+ const Slvs_Entity& aPoint = myStorage->getEntity(anOtherPointID);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = myStorage->getParameter(aPoint.param[i]);
+ aParam.val = aXY[i];
+ myStorage->updateParameter(aParam);
+ }
+ }
+}
+
+void SketchSolver_ConstraintParametric::adjustConstraint()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (!aPoint)
+ return;
+
+ if (!aPoint->textX().empty()) {
+ const Slvs_Entity& aLine = myStorage->getEntity(myVertLineID);
+ const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+ Slvs_Param aParX = myStorage->getParameter(aStartPoint.param[0]);
+ aParX.val = aPoint->x();
+ myStorage->updateParameter(aParX);
+ myX = aParX.val;
+ }
+ if (!aPoint->textY().empty()) {
+ const Slvs_Entity& aLine = myStorage->getEntity(myHorizLineID);
+ const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+ Slvs_Param aParY = myStorage->getParameter(aStartPoint.param[1]);
+ aParY.val = aPoint->y();
+ myStorage->updateParameter(aParY);
+ myY = aParY.val;
+ }
+}
+
+
+Slvs_Entity SketchSolver_ConstraintParametric::createLine(
+ double theStartX, double theStartY, double theEndX, double theEndY)
+{
+ // Start point
+ Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theStartX);
+ Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theStartY);
+ aParX.h = myStorage->addParameter(aParX);
+ aParY.h = myStorage->addParameter(aParY);
+ Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+ myGroup->getWorkplaneId(), aParX.h, aParY.h);
+ aStartPoint.h = myStorage->addEntity(aStartPoint);
+
+ // End point
+ aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theEndX);
+ aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP, theEndY);
+ aParX.h = myStorage->addParameter(aParX);
+ aParY.h = myStorage->addParameter(aParY);
+ Slvs_Entity aEndPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+ myGroup->getWorkplaneId(), aParX.h, aParY.h);
+ aEndPoint.h = myStorage->addEntity(aEndPoint);
+
+ // Line
+ Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, SLVS_G_OUTOFGROUP,
+ myGroup->getWorkplaneId(), aStartPoint.h, aEndPoint.h);
+ aLine.h = myStorage->addEntity(aLine);
+ return aLine;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintParametric.h
+// Created: 15 Jun 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintParametric_H_
+#define SketchSolver_ConstraintParametric_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_ConstraintRigid.h>
+
+/** \class SketchSolver_ConstraintParametric
+ * \ingroup Plugins
+ * \brief Stores data of Rigid (Fixed) constraint for the attribute
+ * which coordinates are given by parametric expression
+ */
+class SketchSolver_ConstraintParametric : public SketchSolver_ConstraintRigid
+{
+private:
+ /// Creates constraint to manage the given constraint from plugin
+ SketchSolver_ConstraintParametric()
+ : SketchSolver_ConstraintRigid(ConstraintPtr())
+ {}
+
+public:
+ /// Creates temporary constraint based on feature
+ SketchSolver_ConstraintParametric(AttributePtr theAttribute);
+
+ /// \brief Update constraint
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Update points coincident with parametric one
+ virtual void refresh();
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Convert attribute to the entity
+ /// \param[out] theAttributeID identifier of the entity related to the attribute
+ virtual void getAttributes(Slvs_hEntity& theAttributeID);
+
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ virtual void adjustConstraint();
+
+private:
+ /// \brief Create SolveSpace line with given coordinates
+ /// \return created line
+ Slvs_Entity createLine(double theStartX, double theStartY, double theEndX, double theEndY);
+
+private:
+ AttributePtr myBaseAttribute; ///< attribute given by expression
+ Slvs_hEntity myHorizLineID; ///< identifier of horizontal line, containing the point
+ Slvs_hEntity myVertLineID; ///< identifier of vertical line, containing the point
+ double myX, myY;
+};
+
+#endif
--- /dev/null
+#include <SketchSolver_ConstraintRigid.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Group.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <math.h>
+
+SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature)
+ : SketchSolver_Constraint(),
+ myBaseFeature(theFeature)
+{
+ process();
+}
+
+void SketchSolver_ConstraintRigid::process()
+{
+ cleanErrorMsg();
+ if ((!myBaseConstraint && !myBaseFeature) || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
+ return;
+ fixFeature();
+}
+
+void SketchSolver_ConstraintRigid::update(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint == myBaseConstraint &&
+ theConstraint->getKind() == myBaseConstraint->getKind() &&
+ checkAttributesChanged(theConstraint)) {
+ // remove previous constraint and set the given one
+ remove(myBaseConstraint);
+ myBaseConstraint = theConstraint;
+ process();
+ }
+}
+
+static void fixEntity(StoragePtr theStorage, const Slvs_hEntity& theEntID)
+{
+ Slvs_Entity anEntity = theStorage->getEntity(theEntID);
+ anEntity.group = SLVS_G_OUTOFGROUP;
+ theStorage->updateEntity(anEntity);
+ // move out of group all sub-entities
+ for (int i = 0; i < 4; ++i)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN)
+ fixEntity(theStorage, anEntity.point[i]);
+ // move out of group the radius of circle
+ if (anEntity.distance != SLVS_E_UNKNOWN)
+ fixEntity(theStorage, anEntity.distance);
+ // move out of group parameters
+ for (int i = 0; i < 4; ++i)
+ if (anEntity.param[i] != SLVS_E_UNKNOWN) {
+ Slvs_Param aParam = theStorage->getParameter(anEntity.param[i]);
+ aParam.group = SLVS_G_OUTOFGROUP;
+ theStorage->updateParameter(aParam);
+ }
+}
+
+void SketchSolver_ConstraintRigid::fixFeature()
+{
+ Slvs_hEntity anEntID = fixedEntity();
+ if (anEntID != SLVS_E_UNKNOWN)
+ fixEntity(myStorage, anEntID);
+}
+
+Slvs_hEntity SketchSolver_ConstraintRigid::fixedEntity() const
+{
+ Slvs_hEntity anEntID = SLVS_E_UNKNOWN;
+ if (myBaseConstraint) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(aFeature);
+ if (aFound != myFeatureMap.end())
+ anEntID = aFound->second;
+ } else {
+ std::map<AttributePtr, Slvs_hEntity>::const_iterator aFound = myAttributeMap.find(aRefAttr->attr());
+ if (aFound != myAttributeMap.end())
+ anEntID = aFound->second;
+ }
+ }
+ else if (myBaseFeature) {
+ std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFound = myFeatureMap.find(myBaseFeature);
+ if (aFound != myFeatureMap.end())
+ anEntID = aFound->second;
+ }
+ return anEntID;
+}
+
+void SketchSolver_ConstraintRigid::getAttributes(
+ double& theValue,
+ std::vector<Slvs_hEntity>& theAttributes)
+{
+ theValue = 0.0;
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ Slvs_hEntity anEntityID = SLVS_E_UNKNOWN;
+ if (myBaseConstraint) {
+ // Get the attribute of constraint
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
+ if (!aRefAttr || !aRefAttr->isInitialized()) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ anEntityID = myGroup->getAttributeId(aRefAttr);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(aRefAttr, aType);
+ } else {
+ anEntityID = myGroup->getFeatureId(myBaseFeature);
+ if (anEntityID == SLVS_E_UNKNOWN)
+ anEntityID = changeEntity(myBaseFeature, aType);
+ else
+ myFeatureMap[myBaseFeature] = anEntityID;
+ }
+
+ if (anEntityID == SLVS_E_UNKNOWN) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+
+ // Check the entity is complex
+ Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+ if (anEntity.point[0] != SLVS_E_UNKNOWN) {
+ for (int i = 0; i < 4 && anEntity.point[i]; i++)
+ theAttributes.push_back(anEntity.point[i]);
+ } else // simple entity
+ theAttributes.push_back(anEntityID);
+}
+
+
+bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (theConstraint && theConstraint != myBaseConstraint)
+ return false;
+ bool isFullyRemoved = true;
+
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); ++aCIter)
+ isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+
+ std::map<FeaturePtr, Slvs_hEntity>::iterator aFIter = myFeatureMap.begin();
+ for (; aFIter != myFeatureMap.end(); ++aFIter)
+ isFullyRemoved = myStorage->removeEntity(aFIter->second) && isFullyRemoved;
+
+ std::map<AttributePtr, Slvs_hEntity>::iterator anAtIter = myAttributeMap.begin();
+ for (; anAtIter != myAttributeMap.end(); ++anAtIter)
+ isFullyRemoved = myStorage->removeEntity(anAtIter->second) && isFullyRemoved;
+
+ if (isFullyRemoved) {
+ myFeatureMap.clear();
+ myAttributeMap.clear();
+ myValueMap.clear();
+ mySlvsConstraints.clear();
+ } else
+ cleanRemovedEntities();
+ return true;
+}
+
+Slvs_hConstraint SketchSolver_ConstraintRigid::fixPoint(const Slvs_hEntity& thePointID)
+{
+ if (thePointID == SLVS_E_UNKNOWN)
+ return SLVS_C_UNKNOWN;
+
+ Slvs_Constraint aConstraint;
+ Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
+ bool isFixed = myStorage->isPointFixed(thePointID, aConstrID, true);
+ bool isForceUpdate = (isFixed && !myBaseConstraint &&
+ myStorage->isTemporary(aConstrID));
+ if (!isForceUpdate) { // create new constraint
+ if (isFixed) return aConstrID;
+ aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
+ 0.0, thePointID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ if (!myBaseConstraint)
+ myStorage->addConstraintWhereDragged(aConstraint.h);
+ } else { // update already existent constraint
+ if (!isFixed || aConstrID == SLVS_C_UNKNOWN || myBaseConstraint)
+ return SLVS_C_UNKNOWN;
+ aConstraint = myStorage->getConstraint(aConstrID);
+ aConstraint.ptA = thePointID;
+ myStorage->addConstraint(aConstraint);
+ if (!myBaseConstraint)
+ myStorage->addConstraintWhereDragged(aConstraint.h);
+ }
+ return aConstraint.h;
+}
+
+void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
+{
+ Slvs_Constraint anEqual;
+ if (myStorage->isAxisParallel(theLine.h)) {
+ // Fix one point and a line length
+ Slvs_hConstraint aFixed;
+ if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) &&
+ !myStorage->isPointFixed(theLine.point[1], aFixed, true))
+ fixPoint(theLine.point[0]);
+ if (!myStorage->isUsedInEqual(theLine.h, anEqual)) {
+ // Check the distance is not set yet
+ std::list<Slvs_Constraint> aDistConstr = myStorage->getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+ std::list<Slvs_Constraint>::const_iterator aDIt = aDistConstr.begin();
+ for (; aDIt != aDistConstr.end(); aDIt++)
+ if ((aDIt->ptA == theLine.point[0] && aDIt->ptB == theLine.point[1]) ||
+ (aDIt->ptA == theLine.point[1] && aDIt->ptB == theLine.point[0]))
+ return;
+ // Calculate distance between points on the line
+ double aCoords[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]);
+ for (int j = 0; j < 2; j++) {
+ Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]);
+ aCoords[2*i+j] = aParam.val;
+ }
+ }
+ double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
+ (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
+ // fix line length
+ Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength,
+ theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aDistance.h = myStorage->addConstraint(aDistance);
+ mySlvsConstraints.push_back(aDistance.h);
+ }
+ return;
+ }
+ else if (myStorage->isUsedInEqual(theLine.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
+ if (myStorage->isEntityFixed(anOtherEntID, true)) {
+ // Fix start point of the line (if end point is not fixed yet) ...
+ Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
+ bool isFixed = myStorage->isPointFixed(theLine.point[1], anEndFixedID, true);
+ if (isFixed == SLVS_E_UNKNOWN)
+ fixPoint(theLine.point[0]);
+ // ... and create fixed point lying on this line
+ Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
+ // Firstly, search already fixed point on line
+ bool isPonLineFixed = false;
+ Slvs_hEntity aFixedPoint;
+ std::list<Slvs_Constraint> aPonLineList = myStorage->getConstraintsByType(SLVS_C_PT_ON_LINE);
+ std::list<Slvs_Constraint>::const_iterator aPLIter = aPonLineList.begin();
+ for (; aPLIter != aPonLineList.end() && !isPonLineFixed; aPLIter++)
+ if (aPLIter->entityA == theLine.h) {
+ isPonLineFixed = myStorage->isPointFixed(aPLIter->ptA, anEndFixedID);
+ aFixedPoint = aPLIter->ptA;
+ }
+
+ if (isPonLineFixed) { // update existent constraint
+ myStorage->copyEntity(aPointToCopy, aFixedPoint);
+ } else { // create new constraint
+ Slvs_hEntity aCopied = myStorage->copyEntity(aPointToCopy);
+ Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE,
+ myGroup->getWorkplaneId(), 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
+ aPonLine.h = myStorage->addConstraint(aPonLine);
+ mySlvsConstraints.push_back(aPonLine.h);
+ fixPoint(aCopied);
+ }
+ return;
+ }
+ }
+
+ for (int i = 0; i < 2; i++)
+ fixPoint(theLine.point[i]);
+}
+
+void SketchSolver_ConstraintRigid::fixCircle(const Slvs_Entity& theCircle)
+{
+ bool isFixRadius = true;
+ // Verify the arc is under Equal constraint
+ Slvs_Constraint anEqual;
+ if (myStorage->isUsedInEqual(theCircle.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
+ if (myStorage->isEntityFixed(anOtherEntID, true))
+ isFixRadius = false;
+ }
+
+ fixPoint(theCircle.point[0]);
+
+ if (isFixRadius) {
+ // Search the radius is already fixed
+ std::list<Slvs_Constraint> aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+ std::list<Slvs_Constraint>::const_iterator aDiamIter = aDiamConstr.begin();
+ for (; aDiamIter != aDiamConstr.end(); aDiamIter++)
+ if (aDiamIter->entityA == theCircle.h)
+ return;
+
+ // Fix radius of a circle
+ AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
+ Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
+ myGroup->getWorkplaneId(), aRadiusAttr->value() * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+ aFixedR.h = myStorage->addConstraint(aFixedR);
+ mySlvsConstraints.push_back(aFixedR.h);
+ }
+}
+
+void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc)
+{
+ bool isFixRadius = true;
+ std::list<Slvs_hEntity> aPointsToFix;
+ aPointsToFix.push_back(theArc.point[1]);
+ aPointsToFix.push_back(theArc.point[2]);
+
+ // Verify the arc is under Equal constraint
+ Slvs_Constraint anEqual;
+ if (myStorage->isUsedInEqual(theArc.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
+ if (myStorage->isEntityFixed(anOtherEntID, true)) {
+ isFixRadius = false;
+ Slvs_Entity anOtherEntity = myStorage->getEntity(anOtherEntID);
+ if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
+ aPointsToFix.pop_back();
+ aPointsToFix.push_back(theArc.point[0]);
+ }
+ }
+ }
+
+ Slvs_hConstraint aConstrID;
+ int aNbPointsToFix = 2; // number of fixed points for the arc
+ if (myStorage->isPointFixed(theArc.point[0], aConstrID, true))
+ aNbPointsToFix--;
+
+ // Radius of the arc
+ FeaturePtr aFeature = myFeatureMap.begin()->first;
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+ double aRadius = aCenter->distance(aStart);
+
+ // Update end point of the arc to be on a curve
+ std::shared_ptr<GeomAPI_Pnt2d> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
+ double aDistance = anEnd->distance(aCenter);
+ std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
+ if (aDistance < tolerance)
+ aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
+ else
+ aDir = aDir->multiplied(aRadius / aDistance);
+ double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
+ Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]);
+ aParam.val = xy[i];
+ myStorage->updateParameter(aParam);
+ }
+
+ std::list<Slvs_hEntity>::iterator aPtIt = aPointsToFix.begin();
+ for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
+ fixPoint(*aPtIt);
+
+ if (isFixRadius) {
+ // Fix radius of the arc
+ bool isExists = false;
+ std::list<Slvs_Constraint> aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+ std::list<Slvs_Constraint>::iterator anIt = aDiamConstraints.begin();
+ for (; anIt != aDiamConstraints.end() && !isExists; anIt++)
+ if (anIt->entityA == theArc.h)
+ isExists = true;
+ if (!isExists) {
+ Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
+ myGroup->getWorkplaneId(), aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ myFeatureMap.begin()->second, SLVS_E_UNKNOWN);
+ aFixedR.h = myStorage->addConstraint(aFixedR);
+ mySlvsConstraints.push_back(aFixedR.h);
+ if (!myBaseConstraint)
+ myStorage->addConstraintWhereDragged(aFixedR.h);
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintRigid.h
+// Created: 30 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintRigid_H_
+#define SketchSolver_ConstraintRigid_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintRigid
+ * \ingroup Plugins
+ * \brief Stores data of Rigid (Fixed) constraint
+ *
+ * Rigid constraint may have NULL basic SketchPlugin constraint,
+ * because the Rigid constraint may be temporary for correct moving of objects.
+ *
+ * Rigid constraint does not create a constraint, but builds the entities in separate group,
+ * so they will not be moved while resolving the set of constraints.
+ */
+class SketchSolver_ConstraintRigid : public SketchSolver_Constraint
+{
+public:
+ /// Creates constraint to manage the given constraint from plugin
+ SketchSolver_ConstraintRigid(ConstraintPtr theConstraint)
+ : SketchSolver_Constraint(theConstraint)
+ {}
+ /// Creates temporary constraint based on feature
+ SketchSolver_ConstraintRigid(FeaturePtr theFeature);
+
+ /// \brief Update constraint
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Returns the type of constraint
+ virtual int getType() const
+ { return SLVS_C_WHERE_DRAGGED; }
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
+ /// \brief Fixed feature basing on its type
+ virtual void fixFeature();
+
+ /// \brief Fix given point
+ /// \return ID of the Fixed constraint
+ Slvs_hConstraint fixPoint(const Slvs_hEntity& thePointID);
+
+ /// \brief Returns ID of fixed entity
+ Slvs_hEntity fixedEntity() const;
+
+ /// \brief Fixing line position (start and end points)
+ void fixLine(const Slvs_Entity& theLine);
+ /// \brief Fixing circle (center and radius)
+ void fixCircle(const Slvs_Entity& theCircle);
+ /// \brief The arc is fixed differently to avoid SolveSpace problems (overconstraint)
+ ///
+ /// There will be fixed start and end points and the radius of the arc.
+ void fixArc(const Slvs_Entity& theArc);
+
+protected:
+ FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
+};
+
+#endif
#include <SketchSolver_ConstraintTangent.h>
+#include <SketchSolver_Group.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-#include <GeomAPI_Pnt2d.h>
-
-/// \brief Check whether the entities has only one shared point
-static bool hasSingleCoincidence(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2)
+void SketchSolver_ConstraintTangent::process()
{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
-
- std::list<EntityWrapperPtr>::const_iterator aStartIt1 = aPoints1.begin();
- if (theEntity1->type() == ENTITY_ARC) ++aStartIt1; // skip center of arc
- std::list<EntityWrapperPtr>::const_iterator aStartIt2 = aPoints2.begin();
- if (theEntity2->type() == ENTITY_ARC) ++aStartIt2; // skip center of arc
-
- int aNbCoinc = 0;
- std::list<EntityWrapperPtr>::const_iterator anIt1, anIt2;
- for (anIt1 = aStartIt1; anIt1 != aPoints1.end(); ++anIt1) {
- std::shared_ptr<GeomAPI_Pnt2d> aPt1 = aBuilder->point(*anIt1);
- for (anIt2 = aStartIt2; anIt2 != aPoints2.end(); ++anIt2) {
- std::shared_ptr<GeomAPI_Pnt2d> aPt2 = aBuilder->point(*anIt2);
- if (aPt1->distance(aPt2) < tolerance)
- ++aNbCoinc;
- }
- }
- return aNbCoinc == 1;
-}
-
-
-void SketchSolver_ConstraintTangent::getAttributes(
- double& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
-{
- SketchSolver_Constraint::getAttributes(theValue, theAttributes);
- if (!myErrorMsg.empty() || !theAttributes[2] || !theAttributes[3]) {
- theAttributes.clear();
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
return;
}
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+ double aValue;
+ std::vector<Slvs_hEntity> anEntID;
+ getAttributes(aValue, anEntID);
+ if (!myErrorMsg.empty())
+ return;
// Check the quantity of entities of each type and their order (arcs first)
int aNbLines = 0;
int aNbArcs = 0;
- bool isSwap = false; // whether need to swap arguments (arc goes before line)
- std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
- for (; anEntIt != theAttributes.end(); ++anEntIt) {
- if ((*anEntIt)->type() == ENTITY_LINE)
- ++aNbLines;
- else if ((*anEntIt)->type() == ENTITY_ARC) {
- ++aNbArcs;
- isSwap = aNbLines > 0;
+ Slvs_Entity anEntities[2];
+ myType = SLVS_C_CURVE_CURVE_TANGENT;
+ std::vector<Slvs_hEntity>::iterator anEntIter = anEntID.begin();
+ for (; anEntIter != anEntID.end(); anEntIter++) {
+ Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+ if (anEnt.type == SLVS_E_LINE_SEGMENT) {
+ if (aNbLines == 0)
+ anEntities[1 + aNbLines] = anEnt;
+ aNbLines++;
+ myType = SLVS_C_ARC_LINE_TANGENT;
+ }
+ else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
+ if (aNbArcs < 2)
+ anEntities[aNbArcs] = anEnt;
+ aNbArcs++;
}
}
- if (aNbArcs < 1) {
+ if (aNbLines + aNbArcs != 2) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ } else if (aNbArcs < 1) {
myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
return;
}
- if (aNbLines == 1 && aNbArcs == 1)
- myType = CONSTRAINT_TANGENT_ARC_LINE;
- else if (aNbArcs == 2)
- myType = CONSTRAINT_TANGENT_ARC_ARC;
- else {
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+
+ // It is necessary to identify which points of entities are coincident
+ int aSlvsOtherFlag = 0;
+ int aSlvsOther2Flag = 0;
+ // Obtain start and end points of entities
+ Slvs_hEntity aPointsToFind[4];
+ for (int i = 0; i < 2; i++) {
+ int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
+ aPointsToFind[2*i] = anEntities[i].point[aShift];
+ aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
+ }
+ // Search coincident points
+ bool isPointFound = false;
+ for (int i = 0; i < 2 && !isPointFound; i++)
+ for (int j = 2; j < 4 && !isPointFound; j++)
+ if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
+ aSlvsOtherFlag = i;
+ aSlvsOther2Flag = j - 2;
+ isPointFound = true;
+ }
+ if (!isPointFound) {
+ // There is no coincident points between tangential objects. Generate error message
+ myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
return;
}
- if (!hasSingleCoincidence(theAttributes[2], theAttributes[3]))
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-
- if (isSwap) {
- EntityWrapperPtr aTemp = theAttributes[2];
- theAttributes[2] = theAttributes[3];
- theAttributes[3] = aTemp;
- }
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h);
+ aConstraint.other = aSlvsOtherFlag;
+ aConstraint.other2 = aSlvsOther2Flag;
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ adjustConstraint();
}
-
-////void SketchSolver_ConstraintTangent::process()
-////{
-//// cleanErrorMsg();
-//// if (!myBaseConstraint || !myStorage || myGroup == 0) {
-//// /// TODO: Put error message here
-//// return;
-//// }
-//// if (!mySlvsConstraints.empty()) // some data is changed, update constraint
-//// update(myBaseConstraint);
-////
-//// double aValue;
-//// std::vector<Slvs_hEntity> anEntID;
-//// getAttributes(aValue, anEntID);
-//// if (!myErrorMsg.empty())
-//// return;
-//// // Check the quantity of entities of each type and their order (arcs first)
-//// int aNbLines = 0;
-//// int aNbArcs = 0;
-//// Slvs_Entity anEntities[2];
-//// myType = SLVS_C_CURVE_CURVE_TANGENT;
-//// std::vector<Slvs_hEntity>::iterator anEntIter = anEntID.begin();
-//// for (; anEntIter != anEntID.end(); anEntIter++) {
-//// Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
-//// if (anEnt.type == SLVS_E_LINE_SEGMENT) {
-//// if (aNbLines == 0)
-//// anEntities[1 + aNbLines] = anEnt;
-//// aNbLines++;
-//// myType = SLVS_C_ARC_LINE_TANGENT;
-//// }
-//// else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) {
-//// if (aNbArcs < 2)
-//// anEntities[aNbArcs] = anEnt;
-//// aNbArcs++;
-//// }
-//// }
-////
-//// if (aNbLines + aNbArcs != 2) {
-//// myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-//// return;
-//// } else if (aNbArcs < 1) {
-//// myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
-//// return;
-//// }
-////
-//// // It is necessary to identify which points of entities are coincident
-//// int aSlvsOtherFlag = 0;
-//// int aSlvsOther2Flag = 0;
-//// // Obtain start and end points of entities
-//// Slvs_hEntity aPointsToFind[4];
-//// for (int i = 0; i < 2; i++) {
-//// int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0;
-//// aPointsToFind[2*i] = anEntities[i].point[aShift];
-//// aPointsToFind[2*i+1]= anEntities[i].point[aShift+1];
-//// }
-//// // Search coincident points
-//// bool isPointFound = false;
-//// for (int i = 0; i < 2 && !isPointFound; i++)
-//// for (int j = 2; j < 4 && !isPointFound; j++)
-//// if (myStorage->isEqual(aPointsToFind[i], aPointsToFind[j])) {
-//// aSlvsOtherFlag = i;
-//// aSlvsOther2Flag = j - 2;
-//// isPointFound = true;
-//// }
-//// if (!isPointFound) {
-//// // There is no coincident points between tangential objects. Generate error message
-//// myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS();
-//// return;
-//// }
-////
-//// Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
-//// getType(), myGroup->getWorkplaneId(), aValue,
-//// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h);
-//// aConstraint.other = aSlvsOtherFlag;
-//// aConstraint.other2 = aSlvsOther2Flag;
-//// aConstraint.h = myStorage->addConstraint(aConstraint);
-//// mySlvsConstraints.push_back(aConstraint.h);
-//// adjustConstraint();
-////}
-
SketchSolver_Constraint(theConstraint)
{}
+ virtual int getType() const
+ { return myType; }
+
protected:
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+private:
+ int myType; ///< type of constraint (applicable: SLVS_C_ARC_LINE_TANGENT, SLVS_C_CURVE_CURVE_TANGENT)
};
#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_FeatureStorage.cpp
+// Created: 23 Mar 2015
+// Author: Artem ZHIDKOV
+
+#include <SketchSolver_FeatureStorage.h>
+
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <GeomDataAPI_Point2D.h>
+
+void SketchSolver_FeatureStorage::changeConstraint(ConstraintPtr theConstraint)
+{
+ std::list<AttributePtr> anAttributes = theConstraint->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject()) {
+ changeAttribute(aRefAttr->attr(), theConstraint);
+ continue;
+ }
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ aRefAttr->object());
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+ if (aFeature)
+ changeFeature(aFeature, theConstraint);
+ continue;
+ }
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+ if (aRefList) {
+ std::list<ObjectPtr> aList = aRefList->list();
+ std::list<ObjectPtr>::iterator aListIter = aList.begin();
+ for (; aListIter != aList.end(); aListIter++) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ *aListIter);
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+ if (aFeature)
+ changeFeature(aFeature, theConstraint);
+ }
+ continue;
+ }
+ changeAttribute(*anIter, theConstraint);
+ }
+ myConstraints.insert(theConstraint);
+}
+
+void SketchSolver_FeatureStorage::removeConstraint(ConstraintPtr theConstraint)
+{
+ DataPtr aData = theConstraint->data();
+ if (aData) { // Constraint has data. Iterate through its attributes and remove them
+ std::list<AttributePtr> anAttributes = aData->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject()) {
+ removeAttribute(aRefAttr->attr(), theConstraint);
+ continue;
+ }
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ aRefAttr->object());
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+ if (aFeature)
+ removeFeature(aFeature, theConstraint);
+ continue;
+ }
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+ if (aRefList) {
+ std::list<ObjectPtr> aList = aRefList->list();
+ std::list<ObjectPtr>::iterator aListIter = aList.begin();
+ for (; aListIter != aList.end(); aListIter++) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ *aListIter);
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+ if (aFeature)
+ removeFeature(aFeature, theConstraint);
+ }
+ continue;
+ }
+ removeAttribute(*anIter, theConstraint);
+ }
+ } else { // Constraint has no data. Search the links on it in the lists of back references for features and attributes
+ std::set<ConstraintPtr>::iterator aCIter;
+ MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
+ while (aFeatIter != myFeatures.end()) {
+ aCIter = aFeatIter->second.find(theConstraint);
+ if (aCIter != aFeatIter->second.end()) {
+ FeaturePtr aFeature = aFeatIter->first;
+ aFeatIter++;
+ removeFeature(aFeature, theConstraint);
+ continue;
+ }
+ aFeatIter++;
+ }
+ std::set<FeaturePtr>::iterator aFIter;
+ MapAttributeFeature::iterator anAttrIter = myAttributes.begin();
+ while (anAttrIter != myAttributes.end()) {
+ aFIter = anAttrIter->second.find(theConstraint);
+ if (aFIter != anAttrIter->second.end()) {
+ anAttrIter->second.erase(aFIter);
+ if (anAttrIter->second.empty()) {
+ MapAttributeFeature::iterator aTmpIter = anAttrIter; // stores iterator for the next element, while the current is deleting
+ aTmpIter++;
+ myAttributes.erase(anAttrIter);
+ anAttrIter = aTmpIter;
+ continue;
+ }
+ }
+ anAttrIter++;
+ }
+ }
+ myConstraints.erase(theConstraint);
+}
+
+bool SketchSolver_FeatureStorage::isInteract(ConstraintPtr theConstraint) const
+{
+ if (myConstraints.empty() || myConstraints.find(theConstraint) != myConstraints.end())
+ return true;
+
+ DataPtr aData = theConstraint->data();
+ if (!aData)
+ return false;
+
+ std::list<AttributePtr> anAttributes = aData->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject()) {
+ if (isInteract(aRefAttr->attr()))
+ return true;
+ continue;
+ }
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ aRefAttr->object());
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aRefAttr->object());
+ if (aFeature)
+ if (isInteract(aFeature))
+ return true;
+ continue;
+ }
+ AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anIter);
+ if (aRefList) {
+ std::list<ObjectPtr> aList = aRefList->list();
+ std::list<ObjectPtr>::iterator aListIter = aList.begin();
+ for (; aListIter != aList.end(); aListIter++) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ *aListIter);
+ FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<ModelAPI_Feature>(*aListIter);
+ if (aFeature)
+ if (isInteract(aFeature))
+ return true;
+ }
+ continue;
+ }
+ if (isInteract(*anIter))
+ return true;
+ }
+ return false;
+}
+
+
+void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature)
+{
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject())
+ changeAttribute(aRefAttr->attr(), theFeature);
+ continue;
+ }
+ changeAttribute(*anIter, theFeature);
+ }
+ if (myFeatures.find(theFeature) == myFeatures.end())
+ myFeatures[theFeature] = std::set<ConstraintPtr>();
+}
+
+void SketchSolver_FeatureStorage::changeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
+{
+ // Change all attributes of the feature
+ changeFeature(theFeature);
+ // Add back reference feature to constraint
+ myFeatures[theFeature].insert(theConstraint);
+}
+
+void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature)
+{
+ MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
+ if (aFeatIter == myFeatures.end())
+ return; // no such feature
+
+ std::set<ConstraintPtr> aConstraints = aFeatIter->second;
+ std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+ for (; aCIter != aConstraints.end(); aCIter++)
+ removeFeature(theFeature, *aCIter);
+}
+
+void SketchSolver_FeatureStorage::removeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint)
+{
+ MapFeatureConstraint::iterator aFeatIter = myFeatures.find(theFeature);
+ if (aFeatIter == myFeatures.end())
+ return; // no such feature
+
+ if (theFeature->data()) {
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject())
+ removeAttribute(aRefAttr->attr(), theFeature);
+ continue;
+ }
+ removeAttribute(*anIter, theFeature);
+ }
+ } else {
+ // iterate on attributes to find items refered to theFeature
+ MapAttributeFeature::iterator anIter = myAttributes.begin();
+ while (anIter != myAttributes.end()) {
+ if (anIter->second.find(theFeature) != anIter->second.end()) {
+ anIter->second.erase(theFeature);
+ if (anIter->second.empty()) {
+ MapAttributeFeature::iterator aDeadIter = anIter++;
+ myAttributes.erase(aDeadIter);
+ continue;
+ }
+ }
+ anIter++;
+ }
+ }
+
+ aFeatIter->second.erase(theConstraint);
+ if (aFeatIter->second.empty())
+ myFeatures.erase(aFeatIter);
+}
+
+bool SketchSolver_FeatureStorage::isInteract(FeaturePtr theFeature) const
+{
+ if (myFeatures.find(theFeature) != myFeatures.end())
+ return true;
+ if (!theFeature->data() || !theFeature->data()->isValid())
+ return false;
+
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ for (; anIter != anAttributes.end(); anIter++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttr) {
+ if (!aRefAttr->isObject())
+ if (isInteract(aRefAttr->attr()))
+ return true;
+ continue;
+ }
+ if (isInteract(*anIter))
+ return true;
+ }
+ return false;
+}
+
+
+void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute)
+{
+ if (myAttributes.find(theAttribute) == myAttributes.end())
+ myAttributes[theAttribute] = std::set<FeaturePtr>();
+}
+
+void SketchSolver_FeatureStorage::changeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
+{
+ MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+ if (anAttrIter == myAttributes.end()) {
+ std::set<FeaturePtr> aFeatures;
+ aFeatures.insert(theFeature);
+ myAttributes[theAttribute] = aFeatures;
+ return;
+ }
+ anAttrIter->second.insert(theFeature);
+}
+
+void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute)
+{
+ MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+ if (anAttrIter == myAttributes.end())
+ return;
+
+ std::set<FeaturePtr> aFeatures = anAttrIter->second;
+ std::set<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+ for (; aFeatIter != aFeatures.end(); aFeatIter++)
+ removeAttribute(theAttribute, *aFeatIter);
+}
+
+void SketchSolver_FeatureStorage::removeAttribute(AttributePtr theAttribute, FeaturePtr theFeature)
+{
+ MapAttributeFeature::iterator anAttrIter = myAttributes.find(theAttribute);
+ if (anAttrIter == myAttributes.end())
+ return; // no such attribute
+
+ anAttrIter->second.erase(theFeature);
+ if (!anAttrIter->second.empty())
+ return;
+
+ // Check there is no features containing such attribute
+ MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
+ for (; aFeatIter != myFeatures.end(); aFeatIter++) {
+ DataPtr aData = aFeatIter->first->data();
+ if (!aData || !aData->isValid())
+ continue;
+ std::list<AttributePtr> anAttrList = aData->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anAtIt = anAttrList.begin();
+ for (; anAtIt != anAttrList.end(); anAtIt++) {
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAtIt);
+ if (aPoint == theAttribute)
+ anAttrIter->second.insert(aFeatIter->first);
+ }
+ }
+ if (anAttrIter->second.empty())
+ myAttributes.erase(anAttrIter);
+}
+
+bool SketchSolver_FeatureStorage::isInteract(AttributePtr theAttribute) const
+{
+ return myAttributes.find(theAttribute) != myAttributes.end();
+}
+
+
+bool SketchSolver_FeatureStorage::isConsistent() const
+{
+ // Check the constraints are valid
+ std::set<ConstraintPtr>::const_iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); aCIter++)
+ if (!(*aCIter)->data() || !(*aCIter)->data()->isValid())
+ return false;
+ // Check the features are valid
+ MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
+ for (; aFIter != myFeatures.end(); aFIter++)
+ if (!aFIter->first->data() || !aFIter->first->data()->isValid())
+ return false;
+ return true;
+}
+
+std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(FeaturePtr theFeature) const
+{
+ std::set<ConstraintPtr> aResult;
+ MapFeatureConstraint::const_iterator aFeatIter = myFeatures.find(theFeature);
+ if (aFeatIter != myFeatures.end())
+ aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::const_iterator anAttrIter = anAttributes.begin();
+ for (; anAttrIter != anAttributes.end(); anAttrIter++) {
+ MapAttributeFeature::const_iterator anIt = myAttributes.find(*anAttrIter);
+ if (anIt == myAttributes.end())
+ continue;
+ std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
+ for (; aFIter != anIt->second.end(); aFIter++) {
+ aFeatIter = myFeatures.find(*aFIter);
+ if (aFeatIter != myFeatures.end())
+ aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+ else {
+ ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
+ if (aConstraint)
+ aResult.insert(aConstraint);
+ }
+ }
+ }
+ return aResult;
+}
+
+std::set<ConstraintPtr> SketchSolver_FeatureStorage::getConstraints(AttributePtr theAttribute) const
+{
+ std::set<ConstraintPtr> aResult;
+ MapAttributeFeature::const_iterator anIt = myAttributes.find(theAttribute);
+ if (anIt == myAttributes.end())
+ return aResult;
+ std::set<FeaturePtr>::const_iterator aFIter = anIt->second.begin();
+ MapFeatureConstraint::const_iterator aFeatIter;
+ for (; aFIter != anIt->second.end(); aFIter++) {
+ aFeatIter = myFeatures.find(*aFIter);
+ if (aFeatIter != myFeatures.end())
+ aResult.insert(aFeatIter->second.begin(), aFeatIter->second.end());
+ else {
+ ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aFIter);
+ if (aConstraint)
+ aResult.insert(aConstraint);
+ }
+ }
+ return aResult;
+}
+
+void SketchSolver_FeatureStorage::blockEvents(bool isBlocked) const
+{
+ std::set<ConstraintPtr>::iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); aCIter++)
+ if ((*aCIter)->data() && (*aCIter)->data()->isValid())
+ (*aCIter)->data()->blockSendAttributeUpdated(isBlocked);
+
+ MapFeatureConstraint::const_iterator aFIter = myFeatures.begin();
+ for (; aFIter != myFeatures.end(); aFIter++)
+ if (aFIter->first->data() && aFIter->first->data()->isValid())
+ aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
+
+ MapAttributeFeature::const_iterator anAtIter = myAttributes.begin();
+ for (; anAtIter != myAttributes.end(); anAtIter++)
+ if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
+ anAtIter->first->owner()->data()->isValid())
+ anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_FeatureStorage.h
+// Created: 23 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_FeatureStorage_H_
+#define SketchSolver_FeatureStorage_H_
+
+#include <SketchSolver.h>
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Constraint.h>
+
+#include <set>
+#include <map>
+
+typedef std::map<FeaturePtr, std::set<ConstraintPtr> > MapFeatureConstraint;
+typedef std::map<AttributePtr, std::set<FeaturePtr> > MapAttributeFeature;
+
+/** \class SketchSolver_FeatureStorage
+ * \ingroup Plugins
+ * \brief Collects information about SketchPlugin constraints used in specific group
+ */
+class SketchSolver_FeatureStorage
+{
+public:
+ SketchSolver_FeatureStorage() {}
+
+ /// \brief Adds or changes a constraint and all features it uses in the storage
+ void changeConstraint(ConstraintPtr theConstraint);
+ /// \brief Removes a constraint and all its features not used by other constraints
+ void removeConstraint(ConstraintPtr theConstraint);
+ /// \brief Verifies a constraint is used in the current storage
+ bool isInteract(ConstraintPtr theConstraint) const;
+
+ /// \brief Adds or changes a feature in the storage
+ void changeFeature(FeaturePtr theFeature);
+ /// \brief Adds or changes a feature in the storage. The feature is used in specified constraint
+ void changeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint);
+ /// \brief Removes a feature
+ void removeFeature(FeaturePtr theFeature);
+ /// \brief Removes a feature according to a given constraint
+ void removeFeature(FeaturePtr theFeature, ConstraintPtr theConstraint);
+ /// \brief Verifies a feature is used in the current storage
+ bool isInteract(FeaturePtr theFeature) const;
+
+ /// \brief Adds or changes an attribute in the storage
+ void changeAttribute(AttributePtr theAttribute);
+ /// \brief Adds or changes a attribute in the storage.
+ /// The attribute is used in specified feature or constraint (theFeature)
+ void changeAttribute(AttributePtr theAttribute, FeaturePtr theFeature);
+ /// \brief Removes an attribute
+ void removeAttribute(AttributePtr theAttribute);
+ /// \brief Removes an attribute according to a given feature
+ void removeAttribute(AttributePtr theAttribute, FeaturePtr theFeature);
+ /// \brief Verifies an attribute is used in the current storage
+ bool isInteract(AttributePtr theAttribute) const;
+
+ /// \brief Check the features is not removed
+ bool isConsistent() const;
+
+ /// \brief Prepares list of constraints, which using specified feature or its attributes
+ std::set<ConstraintPtr> getConstraints(FeaturePtr theFeature) const;
+ /// \brief Prepares list of constraints, which using specified attribute
+ std::set<ConstraintPtr> getConstraints(AttributePtr theAttribute) const;
+
+ /// \brief Block/unblock events of changing attributes of the features
+ void blockEvents(bool isBlocked) const;
+
+private:
+ std::set<ConstraintPtr> myConstraints; ///< list of SketchPlugin constraints used in the current group
+ MapFeatureConstraint myFeatures; ///< list of features used in the group and corresponding constraints which use the feature
+ MapAttributeFeature myAttributes; ///< list of attributes used in the group and corresponding features which are based on the attribute
+};
+
+typedef std::shared_ptr<SketchSolver_FeatureStorage> FeatureStoragePtr;
+
+#endif // SketchSolver_FeatureStorage_H_
#include "SketchSolver_Group.h"
+#include <SketchSolver_Builder.h>
#include <SketchSolver_Constraint.h>
#include <SketchSolver_ConstraintCoincidence.h>
#include <SketchSolver_ConstraintMulti.h>
#include <SketchSolver_Error.h>
-////#include <SketchSolver_Builder.h>
-#include <SketchSolver_Manager.h>
#include <Events_Error.h>
#include <Events_Loop.h>
-////#include <GeomAPI_XY.h>
-////#include <GeomAPI_Dir2d.h>
-////#include <GeomAPI_Pnt2d.h>
-////#include <GeomDataAPI_Dir.h>
-////#include <GeomDataAPI_Point.h>
-////#include <GeomDataAPI_Point2D.h>
-////#include <ModelAPI_AttributeDouble.h>
+#include <GeomAPI_XY.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomDataAPI_Dir.h>
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeString.h>
-////#include <ModelAPI_Document.h>
+#include <ModelAPI_Document.h>
#include <ModelAPI_Events.h>
-////#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
-////
-////#include <SketchPlugin_Constraint.h>
+
+#include <SketchPlugin_Constraint.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintRigid.h>
#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_ConstraintVertical.h>
-////#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Feature.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
-////#include <SketchPlugin_Sketch.h>
-////
-////#include <SketchPlugin_Arc.h>
-////#include <SketchPlugin_Circle.h>
-////#include <SketchPlugin_Line.h>
-////#include <SketchPlugin_Point.h>
-////#include <SketchPlugin_Sketch.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Sketch.h>
#include <math.h>
#include <assert.h>
{
public:
/// \brief Return vacant index
- static GroupID NEW_GROUP() { return ++myGroupIndex; }
+ static Slvs_hGroup NEW_GROUP() { return ++myGroupIndex; }
/// \brief Removes the index
- static void REMOVE_GROUP(const GroupID& theIndex) {
+ static void REMOVE_GROUP(const Slvs_hGroup& theIndex) {
if (myGroupIndex == theIndex)
myGroupIndex--;
}
private:
GroupIndexer() {};
- static GroupID myGroupIndex; ///< index of the group
+ static Slvs_hGroup myGroupIndex; ///< index of the group
};
-GroupID GroupIndexer::myGroupIndex = GID_OUTOFGROUP;
+Slvs_hGroup GroupIndexer::myGroupIndex = SLVS_G_OUTOFGROUP;
static void sendMessage(const char* theMessageName)
myPrevSolved(true)
{
// Initialize workplane
- myWorkplaneID = EID_UNKNOWN;
+ myWorkplaneID = SLVS_E_UNKNOWN;
+#ifndef NDEBUG
+ assert(addWorkplane(theWorkplane));
+#else
addWorkplane(theWorkplane);
+#endif
}
SketchSolver_Group::~SketchSolver_Group()
// Class: SketchSolver_Group
// Purpose: verify are there any entities in the group used by given constraint
// ============================================================================
-bool SketchSolver_Group::isInteract(FeaturePtr theFeature) const
+bool SketchSolver_Group::isInteract(
+ std::shared_ptr<SketchPlugin_Feature> theFeature) const
{
// Empty group interacts with everything
- if (isEmpty())
- return true;
- // Check interaction with the storage
- return myStorage->isInteract(theFeature);
+ if (isEmpty()) return true;
+ ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
+ if (aConstraint)
+ return myFeatureStorage->isInteract(aConstraint);
+ return myFeatureStorage->isInteract(std::dynamic_pointer_cast<ModelAPI_Feature>(theFeature));
+}
+
+// check the entity is really exists
+static void checkEntity(StoragePtr theStorage, Slvs_hEntity& theEntity)
+{
+ if (theEntity == SLVS_E_UNKNOWN)
+ return;
+ Slvs_Entity anEnt = theStorage->getEntity(theEntity);
+ theEntity = anEnt.h;
+}
+
+// ============================================================================
+// Function: getFeatureId
+// Class: SketchSolver_Group
+// Purpose: Find the identifier of the feature, if it already exists in the group
+// ============================================================================
+Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const
+{
+ Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+ if (!myFeatureStorage)
+ return aResult;
+ // Obtain regular constraints interacting with the feature and find its ID
+ ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); ++aCIter) {
+ aResult = aCIter->second->getId(theFeature);
+ checkEntity(myStorage, aResult);
+ if (aResult != SLVS_E_UNKNOWN)
+ return aResult;
+ }
+ // The feature is not found, check it in the temporary constraints
+ std::set<SolverConstraintPtr>::iterator aTmpCIter = myTempConstraints.begin();
+ for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) {
+ aResult = (*aTmpCIter)->getId(theFeature);
+ checkEntity(myStorage, aResult);
+ }
+ return aResult;
+}
+
+// ============================================================================
+// Function: getAttributeId
+// Class: SketchSolver_Group
+// Purpose: Find the identifier of the attribute, if it already exists in the group
+// ============================================================================
+Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const
+{
+ Slvs_hEntity aResult = SLVS_E_UNKNOWN;
+ if (!myFeatureStorage)
+ return aResult;
+ // Obtain regular constraints interacting with the attribute and find its ID
+ ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); ++aCIter) {
+ aResult = aCIter->second->getId(theAttribute);
+ checkEntity(myStorage, aResult);
+ if (aResult != SLVS_E_UNKNOWN)
+ return aResult;
+ }
+ // The attribute is not found, check it in the temporary constraints
+ std::set<SolverConstraintPtr>::const_iterator aTmpCIter = myTempConstraints.begin();
+ for (; aTmpCIter != myTempConstraints.end() && aResult == SLVS_E_UNKNOWN; ++aTmpCIter) {
+ aResult = (*aTmpCIter)->getId(theAttribute);
+ checkEntity(myStorage, aResult);
+ }
+ // Last chance to find attribute in parametric constraints
+ std::map<AttributePtr, SolverConstraintPtr>::const_iterator aParIter =
+ myParametricConstraints.find(theAttribute);
+ if (aParIter != myParametricConstraints.end()) {
+ aResult = aParIter->second->getId(theAttribute);
+ checkEntity(myStorage, aResult);
+ }
+ return aResult;
}
// ============================================================================
std::shared_ptr<SketchPlugin_Constraint> theConstraint)
{
// There is no workplane yet, something wrong
- if (myWorkplaneID == EID_UNKNOWN)
+ if (myWorkplaneID == SLVS_E_UNKNOWN)
return false;
if (!theConstraint || !theConstraint->data())
if (!checkFeatureValidity(theConstraint))
return false;
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
if (isNewConstraint) {
// Add constraint to the current group
- SolverConstraintPtr aConstraint = aBuilder->createConstraint(theConstraint);
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
if (!aConstraint)
return false;
- aConstraint->process(myStorage, getId(), getWorkplaneId());
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
if (!aConstraint->error().empty()) {
if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
return false; // some attribute are not initialized yet, don't show message
Events_Error::send(aConstraint->error(), this);
}
-//// // Additional verification of coincidence of several points
-//// if (aConstraint->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
-//// bool hasMultiCoincidence = false;
-//// std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
-//// std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
-////
-//// ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
-//// for (; aCIter != myConstraints.end(); ++aCIter) {
-//// if (aCIter->second->getType() != CONSTRAINT_PT_PT_COINCIDENT)
-//// continue;
-////
-//// std::shared_ptr<SketchSolver_ConstraintCoincidence> aCurCoinc =
-//// std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
-//// if (aCoincidence != aCurCoinc && aCurCoinc->isCoincide(aCoincidence)) {
-//// aCoincidence->attach(aCurCoinc);
-//////// // update other coincidences
-//////// ConstraintConstraintMap::iterator anIt = aCIter;
-//////// for (++anIt; anIt != myConstraints.end(); ++anIt)
-//////// if (anIt->second == aCIter->second)
-//////// anIt->second = aCoincidence;
-//// aCIter->second = aCoincidence;
-//// hasMultiCoincidence = true;
-//// }
-//// }
-////
-//// if (hasMultiCoincidence)
-//// notifyMultiConstraints();
-//// }
+ // Additional verification of coincidence of several points
+ if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ bool hasMultiCoincidence = false;
+ ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); ++aCIter) {
+ std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
+ std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
+ if (!aCoincidence)
+ continue;
+ std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoinc2 =
+ std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aConstraint);
+ if (aCoincidence != aCoinc2 && aCoincidence->isCoincide(aCoinc2)) {
+ aCoinc2->attach(aCoincidence);
+ // update other coincidences
+ ConstraintConstraintMap::iterator anIt = aCIter;
+ for (++anIt; anIt != myConstraints.end(); ++anIt)
+ if (anIt->second == aCIter->second)
+ anIt->second = aCoinc2;
+ aCIter->second = aCoinc2;
+ hasMultiCoincidence = true;
+ }
+ }
+
+ if (hasMultiCoincidence)
+ notifyMultiConstraints();
+ }
myConstraints[theConstraint] = aConstraint;
}
else
myConstraints[theConstraint]->update();
-//// // Fix base features for fillet
-//// if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
-//// std::list<AttributePtr> anAttrList =
-//// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-//// std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
-//// for (; anAttrIter != anAttrList.end(); anAttrIter++) {
-//// AttributeRefAttrPtr aRefAttr =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
-//// if (!aRefAttr || !aRefAttr->isObject())
-//// continue;
-//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
-//// SolverConstraintPtr aConstraint = aBuilder->createRigidConstraint(aFeature);
-//// if (!aConstraint)
-//// continue;
-//// aConstraint->setGroup(this);
-//// aConstraint->setStorage(myStorage);
-//// setTemporary(aConstraint);
-//// }
-//// }
-
+ // Fix base features for fillet
+ if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+ std::list<AttributePtr> anAttrList =
+ theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
+ for (; anAttrIter != anAttrList.end(); anAttrIter++) {
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
+ if (!aRefAttr || !aRefAttr->isObject())
+ continue;
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+ if (!aConstraint)
+ continue;
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ setTemporary(aConstraint);
+ }
+ }
// Fix mirror line
if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
if (aRefAttr && aRefAttr->isObject()) {
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(
- ModelAPI_Feature::feature(aRefAttr->object()));
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
if (aFeature) {
- SolverConstraintPtr aConstraint = aBuilder->createFixedConstraint(aFeature);
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
if (aConstraint) {
- aConstraint->process(myStorage, getId(), getWorkplaneId());
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
setTemporary(aConstraint);
}
}
}
}
-//// // Check the attributes of constraint are given by parametric expression
-//// std::list<AttributePtr> anAttributes =
-//// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
-//// std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
-//// for (; anAttrIt != anAttributes.end(); ++anAttrIt) {
-//// AttributeRefAttrPtr aRefAttr =
-//// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
-//// if (!aRefAttr)
-//// continue;
-////
-//// std::shared_ptr<GeomDataAPI_Point2D> aPoint;
-//// if (aRefAttr->isObject()) {
-//// FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
-//// if (aFeat->getKind() != SketchPlugin_Point::ID())
-//// continue;
-//// aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-//// aFeat->attribute(SketchPlugin_Point::COORD_ID()));
-//// } else
-//// aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
-////
-//// if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty()))
-//// continue;
-////
-//// std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
-//// myParametricConstraints.find(aPoint);
-//// if (aFound == myParametricConstraints.end()) {
-//// SolverConstraintPtr aConstraint = aBuilder->createParametricConstraint(aPoint);
-//// if (!aConstraint)
-//// continue;
-//// aConstraint->setGroup(this);
-//// aConstraint->setStorage(myStorage);
-//// myParametricConstraints[aPoint] = aConstraint;
-//// } else
-//// aFound->second->update();
-//// }
+ if (!myFeatureStorage)
+ myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
+ myFeatureStorage->changeConstraint(theConstraint);
+
+ // Check the attributes of constraint are given by parametric expression
+ std::list<AttributePtr> anAttributes =
+ theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+ for (; anAttrIt != anAttributes.end(); ++anAttrIt) {
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+ if (!aRefAttr)
+ continue;
+
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint;
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
+ if (aFeat->getKind() != SketchPlugin_Point::ID())
+ continue;
+ aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeat->attribute(SketchPlugin_Point::COORD_ID()));
+ } else
+ aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+
+ if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty()))
+ continue;
+
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+ myParametricConstraints.find(aPoint);
+ if (aFound == myParametricConstraints.end()) {
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createParametricConstraint(aPoint);
+ if (!aConstraint)
+ continue;
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ myParametricConstraints[aPoint] = aConstraint;
+ } else
+ aFound->second->update();
+ }
return true;
}
myChangedConstraints.clear();
}
-bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
+bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
if (!checkFeatureValidity(theFeature))
return false;
- bool isUpdated = myStorage->update(theFeature);
-
-//// // Search attributes of the feature in the set of parametric constraints and update them
-//// std::list<AttributePtr> anAttrList =
-//// theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
-//// std::list<AttributePtr>::iterator anAttrIt = anAttrList.begin();
-//// for (; anAttrIt != anAttrList.end(); ++anAttrIt) {
-//// std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
-//// myParametricConstraints.find(*anAttrIt);
-//// if (aFound != myParametricConstraints.end())
-//// aFound->second->update();
-//// else {
-//// std::shared_ptr<GeomDataAPI_Point2D> aPoint =
-//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAttrIt);
-//// if (aPoint && (!aPoint->textX().empty() || !aPoint->textY().empty())) {
-//// // Create new parametric constraint
-//// SolverConstraintPtr aConstraint =
-//// SketchSolver_Builder::getInstance()->createParametricConstraint(*anAttrIt);
-//// if (!aConstraint)
-//// continue;
-//// aConstraint->setGroup(this);
-//// aConstraint->setStorage(myStorage);
-//// myParametricConstraints[*anAttrIt] = aConstraint;
-//// }
-//// }
-//// }
- return isUpdated;
-}
+ std::set<ConstraintPtr> aConstraints =
+ myFeatureStorage->getConstraints(std::dynamic_pointer_cast<ModelAPI_Feature>(theFeature));
+ if (aConstraints.empty())
+ return false;
+ std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+ for (; aCIter != aConstraints.end(); aCIter++) {
+ ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
+ if (aSolConIter == myConstraints.end() || !aSolConIter->first->data() ||
+ !aSolConIter->first->data()->isValid())
+ continue;
+ myFeatureStorage->changeFeature(theFeature, aSolConIter->first);
-void SketchSolver_Group::moveFeature(FeaturePtr theFeature)
-{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- // Firstly, revert changes in the fixed entities
- myStorage->refresh(true);
-
- // Secondly, search attributes of the feature in the list of the Multi constraints and update them
- ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
- for (; aCIt != myConstraints.end(); ++aCIt) {
- if ((aCIt->second->getType() == CONSTRAINT_MULTI_ROTATION ||
- aCIt->second->getType() == CONSTRAINT_MULTI_TRANSLATION)
- && aCIt->second->isUsed(theFeature))
- std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
+ aSolConIter->second->addFeature(theFeature);
+ myChangedConstraints.insert(aSolConIter->first);
+ }
+
+ // Search attributes of the feature in the set of parametric constraints and update them
+ std::list<AttributePtr> anAttrList =
+ theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anAttrIt = anAttrList.begin();
+ for (; anAttrIt != anAttrList.end(); ++anAttrIt) {
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+ myParametricConstraints.find(*anAttrIt);
+ if (aFound != myParametricConstraints.end())
+ aFound->second->update();
+ else {
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAttrIt);
+ if (aPoint && (!aPoint->textX().empty() || !aPoint->textY().empty())) {
+ // Create new parametric constraint
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createParametricConstraint(*anAttrIt);
+ if (!aConstraint)
+ continue;
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ myParametricConstraints[*anAttrIt] = aConstraint;
+ }
+ }
}
+ return true;
+}
- // Then, create temporary rigid constraint
- SolverConstraintPtr aConstraint = aBuilder->createMovementConstraint(theFeature);
+void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+ // Firstly, create temporary rigid constraint
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createMovementConstraint(theFeature);
if (!aConstraint)
return;
- aConstraint->process(myStorage, getId(), getWorkplaneId());
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
if (aConstraint->error().empty())
setTemporary(aConstraint);
+ // Secondly, update the feature
+ updateFeature(theFeature);
+}
+
+// ============================================================================
+// Function: fixFeaturesList
+// Class: SketchSolver_Group
+// Purpose: Apply temporary rigid constraints for the list of features
+// ============================================================================
+void SketchSolver_Group::fixFeaturesList(AttributeRefListPtr theList)
+{
+ std::list<ObjectPtr> aList = theList->list();
+ std::list<ObjectPtr>::iterator anIt = aList.begin();
+ std::list<FeaturePtr> aFeatures;
+ // Sort features, at begining there are features used by Equal constraint
+ for (; anIt != aList.end(); anIt++) {
+ if (!(*anIt))
+ continue;
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(aFeature);
+ std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+ for (; aCIter != aConstraints.end(); aCIter++)
+ if ((*aCIter)->getKind() == SketchPlugin_ConstraintEqual::ID())
+ break;
+ if (aCIter != aConstraints.end())
+ aFeatures.push_front(aFeature);
+ else
+ aFeatures.push_back(aFeature);
+ }
+
+ std::list<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+ for (; aFeatIter != aFeatures.end(); aFeatIter++) {
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createRigidConstraint(*aFeatIter);
+ if (!aConstraint)
+ continue;
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ setTemporary(aConstraint);
+ }
}
// ============================================================================
// ============================================================================
bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
{
- if (myWorkplaneID != EID_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
+ if (myWorkplaneID != SLVS_E_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
return false; // the workplane already exists or the function parameter is not Sketch
mySketch = theSketch;
- if (!updateWorkplane()) {
- mySketch = CompositeFeaturePtr();
- return false;
- }
+ updateWorkplane();
return true;
}
// ============================================================================
bool SketchSolver_Group::updateWorkplane()
{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
if (!myStorage) // Create storage if not exists
- myStorage = aBuilder->createStorage(getId());
+ myStorage = StoragePtr(new SketchSolver_Storage);
+ SketchSolver_Builder* aBuilder = SketchSolver_Builder::getInstance();
- // sketch should be unchanged, set it out of current group
- bool isUpdated = myStorage->update(FeaturePtr(mySketch), GID_OUTOFGROUP);
- if (isUpdated) {
- EntityWrapperPtr anEntity = myStorage->entity(FeaturePtr(mySketch));
- myWorkplaneID = anEntity->id();
+ std::vector<Slvs_Entity> anEntities;
+ std::vector<Slvs_Param> aParams;
+ if (!aBuilder->createWorkplane(mySketch, anEntities, aParams))
+ return false;
+
+ if (myWorkplaneID == SLVS_E_UNKNOWN) {
+ myWorkplaneID = anEntities.back().h;
+ // Add new workplane elements
+ std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
+ for (; aParIter != aParams.end(); aParIter++) {
+ aParIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
+ aParIter->group = SLVS_G_OUTOFGROUP;
+ aParIter->h = myStorage->addParameter(*aParIter);
+ }
+ std::vector<Slvs_Entity>::iterator anEntIter = anEntities.begin();
+ for (; anEntIter != anEntities.end(); anEntIter++) {
+ anEntIter->h = SLVS_E_UNKNOWN; // the ID should be generated by storage
+ anEntIter->group = SLVS_G_OUTOFGROUP;
+ anEntIter->wrkpl = myWorkplaneID;
+ for (int i = 0; i < 4; i++)
+ if (anEntIter->param[i] != SLVS_E_UNKNOWN)
+ anEntIter->param[i] = aParams[anEntIter->param[i]-1].h;
+ for (int i = 0; i < 4; i++)
+ if (anEntIter->point[i] != SLVS_E_UNKNOWN)
+ anEntIter->point[i] = anEntities[anEntIter->point[i]-1].h;
+ anEntIter->h = myStorage->addEntity(*anEntIter);
+ }
+ } else {
+ // Update existent workplane
+ const Slvs_Entity& aWP = myStorage->getEntity(myWorkplaneID);
+ const Slvs_Entity& anOrigin = myStorage->getEntity(aWP.point[0]);
+ const Slvs_Entity& aNormal = myStorage->getEntity(aWP.normal);
+ // Get parameters and update them
+ Slvs_hParam aWPParams[7] = {
+ anOrigin.param[0], anOrigin.param[1], anOrigin.param[2],
+ aNormal.param[0], aNormal.param[1], aNormal.param[2], aNormal.param[3]
+ };
+ std::vector<Slvs_Param>::iterator aParIter = aParams.begin();
+ for (int i = 0; aParIter != aParams.end(); aParIter++, i++) {
+ Slvs_Param aParam = myStorage->getParameter(aWPParams[i]);
+ aParam.val = aParIter->val;
+ myStorage->updateParameter(aParam);
+ }
}
- return isUpdated;
+ return myWorkplaneID > 0;
}
// ============================================================================
bool aResolved = false;
bool isGroupEmpty = isEmpty();
if (myStorage->isNeedToResolve() && !isGroupEmpty) {
- if (!mySketchSolver)
- mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
-
- mySketchSolver->setGroup(myID);
- mySketchSolver->calculateFailedConstraints(false);
- myStorage->initializeSolver(mySketchSolver);
+ myConstrSolver.setGroupID(myID);
+ myConstrSolver.calculateFailedConstraints(false);
+ myStorage->initializeSolver(myConstrSolver);
- SketchSolver_SolveStatus aResult = STATUS_OK;
+ int aResult = SLVS_RESULT_OKAY;
try {
if (myStorage->hasDuplicatedConstraint())
- aResult = STATUS_INCONSISTENT;
+ aResult = SLVS_RESULT_INCONSISTENT;
else {
// To avoid overconstraint situation, we will remove temporary constraints one-by-one
// and try to find the case without overconstraint
bool isLastChance = false;
- size_t aNbTemp = myStorage->nbTemporary();
+ int aNbTemp = myStorage->numberTemporary();
while (true) {
- aResult = mySketchSolver->solve();
- if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET || isLastChance)
+ aResult = myConstrSolver.solve();
+ if (aResult == SLVS_RESULT_OKAY || isLastChance)
break;
- if (aNbTemp == 0) {
+ if (aNbTemp <= 0) {
// try to update parameters and resolve once again
ConstraintConstraintMap::iterator aConstrIt = myConstraints.begin();
for (; aConstrIt != myConstraints.end(); ++aConstrIt)
aConstrIt->second->update();
isLastChance = true;
} else
- aNbTemp = myStorage->removeTemporary();
- mySketchSolver->calculateFailedConstraints(true); // something failed => need to find it
- myStorage->initializeSolver(mySketchSolver);
+ aNbTemp = myStorage->deleteTemporaryConstraint();
+ myConstrSolver.calculateFailedConstraints(true); // something failed => need to find it
+ myStorage->initializeSolver(myConstrSolver);
}
}
} catch (...) {
}
return false;
}
- if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) { // solution succeeded, store results into correspondent attributes
- myStorage->refresh();
-//// myFeatureStorage->blockEvents(true);
-//// // First refresh parametric constraints to satisfy parameters
-//// std::map<AttributePtr, SolverConstraintPtr>::iterator aParIter = myParametricConstraints.begin();
-//// for (; aParIter != myParametricConstraints.end(); ++aParIter)
-//// aParIter->second->refresh();
-//// // Update all other constraints
-//// ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
-//// for (; aConstrIter != myConstraints.end(); ++aConstrIter)
-//// aConstrIter->second->refresh();
-//// myFeatureStorage->blockEvents(false);
+ if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
+ myFeatureStorage->blockEvents(true);
+ // First refresh parametric constraints to satisfy parameters
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aParIter = myParametricConstraints.begin();
+ for (; aParIter != myParametricConstraints.end(); ++aParIter)
+ aParIter->second->refresh();
+ // Update all other constraints
+ ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); ++aConstrIter)
+ aConstrIter->second->refresh();
+ myFeatureStorage->blockEvents(false);
if (!myPrevSolved) {
getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
// the error message should be changed before sending the message
aResolved = true;
} else if (!isGroupEmpty) {
-//// myFeatureStorage->blockEvents(true);
+ myFeatureStorage->blockEvents(true);
// Check there are constraints Fixed. If they exist, update parameters by stored values
ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
for (; aCIt != myConstraints.end(); ++aCIt)
if (aCIt->first->getKind() == SketchPlugin_ConstraintRigid::ID()) {
-//// aCIt->second->refresh();
+ aCIt->second->refresh();
aResolved = true;
- break;
}
-//// myFeatureStorage->blockEvents(false);
- if (aCIt != myConstraints.end())
- myStorage->refresh();
+ myFeatureStorage->blockEvents(false);
}
removeTemporaryConstraints();
myStorage->setNeedToResolve(false);
// If specified group is empty, no need to merge
if (theGroup.isEmpty())
return;
+ if (!myFeatureStorage)
+ myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
std::set<ObjectPtr> aConstraints;
ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
// Class: SketchSolver_Group
// Purpose: divide the group into several subgroups
// ============================================================================
-void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
+void SketchSolver_Group::splitGroup(std::vector<SketchSolver_Group*>& theCuts)
{
- // New storage will be used in trimmed way to store the list of constraint interacted together.
- StoragePtr aNewStorage = SketchSolver_Manager::instance()->builder()->createStorage(getId());
- std::list<ConstraintWrapperPtr> aDummyVec; // empty vector to avoid creation of solver's constraints
-
// Obtain constraints, which should be separated
- std::list<ConstraintPtr> anUnusedConstraints;
+ FeatureStoragePtr aNewFeatStorage(new SketchSolver_FeatureStorage);
+ std::vector<ConstraintPtr> anUnusedConstraints;
ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
for ( ; aCIter != myConstraints.end(); aCIter++) {
- if (aNewStorage->isInteract(FeaturePtr(aCIter->first)))
- aNewStorage->addConstraint(aCIter->first, aDummyVec);
- else
- anUnusedConstraints.push_back(aCIter->first);
+ std::list<ConstraintPtr> aBaseConstraints = aCIter->second->constraints();
+ std::list<ConstraintPtr>::iterator anIter = aBaseConstraints.begin();
+ for (; anIter != aBaseConstraints.end(); anIter++)
+ if (aNewFeatStorage->isInteract(*anIter)) {
+ aNewFeatStorage->changeConstraint(*anIter);
+ } else
+ anUnusedConstraints.push_back(*anIter);
}
// Check the unused constraints once again, because they may become interacted with new storage since adding constraints
- std::list<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
+ std::vector<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
while (aUnuseIt != anUnusedConstraints.end()) {
- if (aNewStorage->isInteract(FeaturePtr(*aUnuseIt))) {
- aNewStorage->addConstraint(*aUnuseIt, aDummyVec);
+ if (aNewFeatStorage->isInteract(*aUnuseIt)) {
+ aNewFeatStorage->changeConstraint(*aUnuseIt);
anUnusedConstraints.erase(aUnuseIt);
aUnuseIt = anUnusedConstraints.begin();
continue;
aUnuseIt++;
}
- std::list<SketchSolver_Group*>::iterator aCutsIter;
+ std::vector<SketchSolver_Group*>::iterator aCutsIter;
aUnuseIt = anUnusedConstraints.begin();
- for ( ; aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt) {
+ for ( ; aUnuseIt != anUnusedConstraints.end(); aUnuseIt++) {
// Remove unused constraints
removeConstraint(*aUnuseIt);
// Try to append constraint to already existent group
- for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); ++aCutsIter)
+ for (aCutsIter = theCuts.begin(); aCutsIter != theCuts.end(); aCutsIter++)
if ((*aCutsIter)->isInteract(*aUnuseIt)) {
(*aCutsIter)->changeConstraint(*aUnuseIt);
break;
SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
aGroup->changeConstraint(*aUnuseIt);
theCuts.push_back(aGroup);
- } else {
- // Find other groups interacting with constraint
- std::list<SketchSolver_Group*>::iterator aBaseGroupIt = aCutsIter;
- for (++aCutsIter; aCutsIter != theCuts.end(); ++aCutsIter)
- if ((*aCutsIter)->isInteract(*aUnuseIt)) {
- (*aBaseGroupIt)->mergeGroups(**aCutsIter);
- std::list<SketchSolver_Group*>::iterator aRemoveIt = aCutsIter--;
- theCuts.erase(aRemoveIt);
- }
}
}
+
+ // Update feature storage
+ myFeatureStorage = aNewFeatStorage;
}
// ============================================================================
// ============================================================================
bool SketchSolver_Group::isConsistent()
{
- if (isEmpty()) // no one constraint is initialized yet
+ if (!myFeatureStorage) // no one constraint is initialized yet
return true;
- // Check the features and constraint is the storage are valid
- bool aResult = myStorage->isConsistent();
- if (aResult) {
- // additional check of consistency of the Fixed constraint,
- // because they are not added to the storage
- ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
- for (; aCIter != myConstraints.end(); ++aCIter)
- if (aCIter->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
- (!aCIter->first->data() || !aCIter->first->data()->isValid())) {
- aResult = false;
- break;
- }
- }
+ bool aResult = myFeatureStorage->isConsistent();
if (!aResult) {
- // remove invalid constraints
+ // remove invalid entities
std::set<ConstraintPtr> anInvalidConstraints;
ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
for (; aCIter != myConstraints.end(); ++aCIter) {
std::set<ConstraintPtr>::const_iterator aRemoveIt = anInvalidConstraints.begin();
for (; aRemoveIt != anInvalidConstraints.end(); ++aRemoveIt)
removeConstraint(*aRemoveIt);
- // remove invalid features
- myStorage->removeInvalidEntities();
}
return aResult;
}
std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
(*aTmpIt)->remove();
+ myTempConstraints.clear();
- size_t aNbTemp = myStorage->nbTemporary();
- if (aNbTemp > 0)
- myStorage->removeTemporary(aNbTemp);
-//// // Clean lists of removed entities in the storage
-//// std::set<Slvs_hParam> aRemPar;
-//// std::set<Slvs_hEntity> aRemEnt;
-//// std::set<Slvs_hConstraint> aRemCon;
-//// myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
-
- if (!myTempConstraints.empty())
- myStorage->verifyFixed();
+ while (myStorage->numberTemporary())
+ myStorage->deleteTemporaryConstraint();
+ // Clean lists of removed entities in the storage
+ std::set<Slvs_hParam> aRemPar;
+ std::set<Slvs_hEntity> aRemEnt;
+ std::set<Slvs_hConstraint> aRemCon;
+ myStorage->getRemoved(aRemPar, aRemEnt, aRemCon);
myStorage->setNeedToResolve(false);
- myTempConstraints.clear();
}
// ============================================================================
void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint)
{
bool isFullyRemoved = true;
+ myFeatureStorage->removeConstraint(theConstraint);
ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
for (; aCIter != myConstraints.end(); aCIter++)
- if (aCIter->first == theConstraint) {
- if (!aCIter->second->remove()) // the constraint is not fully removed
+ if (aCIter->second->hasConstraint(theConstraint)) {
+ if (!aCIter->second->remove(theConstraint)) // the constraint is not fully removed
isFullyRemoved = false;
break;
}
if (aCIter == myConstraints.end())
return;
-//// // Remove entities not used by constraints
-//// myStorage->removeUnusedEntities();
+ // Remove entities not used by constraints
+ myStorage->removeUnusedEntities();
if (isFullyRemoved)
myConstraints.erase(aCIter);
}
if (aCIter->first != theConstraint)
aMultiCoinc.push_back(aCIter->first);
- aCIter->second->remove();
+ aCIter->second->remove(aCIter->first);
ConstraintConstraintMap::iterator aRemoveIt = aCIter++;
myConstraints.erase(aRemoveIt);
}
// ============================================================================
// Function: setTemporary
// Class: SketchSolver_Group
-// Purpose: append given constraint to the group of temporary constraints
+// Purpose: append given constraint to th group of temporary constraints
// ============================================================================
void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint)
{
// ============================================================================
void SketchSolver_Group::notifyMultiConstraints()
{
-//// ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
-//// for (; aCIter != myConstraints.end(); ++aCIter) {
-//// if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() ||
-//// aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
-//// std::shared_ptr<SketchSolver_ConstraintMulti> aMulti =
-//// std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIter->second);
-//// aMulti->checkCoincidence();
-//// }
-//// }
+ ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); ++aCIter) {
+ if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() ||
+ aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
+ std::shared_ptr<SketchSolver_ConstraintMulti> aMulti =
+ std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIter->second);
+ aMulti->checkCoincidence();
+ }
+ }
}
#include "SketchSolver.h"
#include <SketchSolver_Constraint.h>
#include <SketchSolver_Storage.h>
-#include <SketchSolver_ISolver.h>
+#include <SketchSolver_FeatureStorage.h>
+#include <SketchSolver_Solver.h>
#include <SketchPlugin_Constraint.h>
-////#include <ModelAPI_Data.h>
+#include <ModelAPI_Data.h>
#include <ModelAPI_Feature.h>
-////#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeRefList.h>
#include <memory>
#include <list>
#include <map>
+#include <vector>
#include <set>
typedef std::map<ConstraintPtr, SolverConstraintPtr> ConstraintConstraintMap;
~SketchSolver_Group();
/// \brief Returns group's unique identifier
- inline const GroupID& getId() const
+ inline const Slvs_hGroup& getId() const
{
return myID;
}
/// \brief Returns identifier of the workplane
- inline const EntityID& getWorkplaneId() const
+ inline const Slvs_hEntity& getWorkplaneId() const
{
return myWorkplaneID;
}
+ /// \brief Find the identifier of the feature, if it already exists in the group
+ Slvs_hEntity getFeatureId(FeaturePtr theFeature) const;
+ /// \brief Find the identifier of the attribute, if it already exists in the group
+ Slvs_hEntity getAttributeId(AttributePtr theAttribute) const;
+
/// \brief Returns true if the group has no constraints yet
inline bool isEmpty() const
{
/** \brief Updates the data corresponding the specified feature
* \param[in] theFeature the feature to be updated
*/
- bool updateFeature(FeaturePtr theFeature);
+ bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
/** \brief Updates the data corresponding the specified feature moved in GUI.
* Additional Fixed constraints are created.
* \param[in] theFeature the feature to be updated
*/
- void moveFeature(FeaturePtr theFeature);
+ void moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
/** \brief Verifies the feature attributes are used in this group
* \param[in] theFeature constraint or any other object for verification of interaction
* \return \c true if some of attributes are used in current group
*/
- bool isInteract(FeaturePtr theFeature) const;
+ bool isInteract(std::shared_ptr<SketchPlugin_Feature> theFeature) const;
/** \brief Verifies the specified feature is equal to the base workplane for this group
* \param[in] theWorkplane the feature to be compared with base workplane
/** \brief Cut from the group several subgroups, which are not connected to the current one by any constraint
* \param[out] theCuts enlarge this list by newly created groups
*/
- void splitGroup(std::list<SketchSolver_Group*>& theCuts);
+ void splitGroup(std::vector<SketchSolver_Group*>& theCuts);
/** \brief Start solution procedure if necessary and update attributes of features
* \return \c false when no need to solve constraints
*/
bool addWorkplane(CompositeFeaturePtr theSketch);
- /// \brief Append given constraint to the group of temporary constraints
+ /// \brief Apply temporary rigid constraints for the list of features
+ void fixFeaturesList(AttributeRefListPtr theList);
+
+ /// \brief Append given constraint to th group of temporary constraints
void setTemporary(SolverConstraintPtr theConstraint);
/// \brief Verifies is the feature valid
void notifyMultiConstraints();
private:
- GroupID myID; ///< Index of the group
- EntityID myWorkplaneID; ///< Index of workplane, the group is based on
+ Slvs_hGroup myID; ///< Index of the group
+ Slvs_hEntity myWorkplaneID; ///< Index of workplane, the group is based on
CompositeFeaturePtr mySketch; ///< Sketch is equivalent to workplane
ConstraintConstraintMap myConstraints; ///< List of constraints
std::set<SolverConstraintPtr> myTempConstraints; ///< List of temporary constraints
std::set<ConstraintPtr> myChangedConstraints; ///< List of just updated constraints
StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities
+ FeatureStoragePtr myFeatureStorage; ///< Container for the set of SketchPlugin features and their dependencies
- SolverPtr mySketchSolver; ///< Solver for set of equations obtained by constraints
+ SketchSolver_Solver myConstrSolver; ///< Solver for set of equations obtained by constraints
bool myPrevSolved; ///< Indicates that previous solving was done correctly
};
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_IConstraintWrapper.h
-// Created: 30 Nov 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_IConstraintWrapper_H_
-#define SketchSolver_IConstraintWrapper_H_
-
-#include <SketchSolver_IEntityWrapper.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <list>
-#include <memory>
-
-/// Types of constraints
-enum SketchSolver_ConstraintType {
- CONSTRAINT_UNKNOWN = 0,
- CONSTRAINT_COINCIDENCE, // base coincidence if we don't know exact type yet
- CONSTRAINT_PT_PT_COINCIDENT,
- CONSTRAINT_PT_ON_LINE,
- CONSTRAINT_PT_ON_CIRCLE,
- CONSTRAINT_DISTANCE, // base distance if we don't know the measured objects yet
- CONSTRAINT_PT_PT_DISTANCE,
- CONSTRAINT_PT_LINE_DISTANCE,
- CONSTRAINT_RADIUS,
- CONSTRAINT_ANGLE,
- CONSTRAINT_FIXED,
- CONSTRAINT_HORIZONTAL,
- CONSTRAINT_VERTICAL,
- CONSTRAINT_PARALLEL,
- CONSTRAINT_PERPENDICULAR,
- CONSTRAINT_SYMMETRIC,
- CONSTRAINT_EQUAL, // base equality if we don't know the measured objects yet
- CONSTRAINT_EQUAL_LINES,
- CONSTRAINT_EQUAL_LINE_ARC,
- CONSTRAINT_EQUAL_RADIUS,
- CONSTRAINT_TANGENT, // base tangency if we don't know the measured objects yet
- CONSTRAINT_TANGENT_ARC_LINE,
- CONSTRAINT_TANGENT_ARC_ARC,
- CONSTRAINT_MULTI_TRANSLATION,
- CONSTRAINT_MULTI_ROTATION
-};
-
-/**
- * Wrapper providing operations with constraints regardless the solver.
- */
-class SketchSolver_IConstraintWrapper
-{
-public:
- virtual ~SketchSolver_IConstraintWrapper() {}
-
- /// \brief Return base feature
- const ConstraintPtr& baseConstraint() const
- { return myBaseConstraint; }
-
- /// \brief Return ID of current entity
- virtual ConstraintID id() const = 0;
-
- /// \brief Change group for the constraint
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the constraint belongs to
- virtual const GroupID& group() const = 0;
-
- /// \brief Return type of current entity
- virtual SketchSolver_ConstraintType type() const = 0;
-
- /// \brief Assign list of constrained objects
- void setEntities(const std::list<EntityWrapperPtr>& theEntities)
- { myConstrained = theEntities; }
- /// \brief Return list of constrained objects
- const std::list<EntityWrapperPtr>& entities() const
- { return myConstrained; }
-
- /// \brief Assign numeric parameter of constraint
- virtual void setValue(const double& theValue)
- { myValue = theValue; }
- /// \brief Return numeric parameter of constraint
- const double& value() const
- { return myValue; }
-
- /// \brief Verify the feature is used in the constraint
- virtual bool isUsed(FeaturePtr theFeature) const = 0;
- /// \brief Verify the attribute is used in the constraint
- virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
- /// \brief Compare current constraint with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
- /// \brief Update values of parameters of this constraint by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
-protected:
- ConstraintPtr myBaseConstraint;
- std::list<EntityWrapperPtr> myConstrained;
- double myValue;
-};
-
-typedef std::shared_ptr<SketchSolver_IConstraintWrapper> ConstraintWrapperPtr;
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_IEntityWrapper.h
-// Created: 30 Nov 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_IEntityWrapper_H_
-#define SketchSolver_IEntityWrapper_H_
-
-#include <SketchSolver.h>
-#include <SketchSolver_IParameterWrapper.h>
-
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_Feature.h>
-
-#include <list>
-#include <memory>
-
-/// Types of entities
-enum SketchSolver_EntityType {
- ENTITY_UNKNOWN = 0,
- ENTITY_SCALAR,
- ENTITY_POINT,
- ENTITY_NORMAL,
- ENTITY_LINE,
- ENTITY_CIRCLE,
- ENTITY_ARC,
- ENTITY_SKETCH
-};
-
-/**
- * Wrapper providing operations with entities regardless the solver.
- */
-class SketchSolver_IEntityWrapper
-{
-public:
- virtual ~SketchSolver_IEntityWrapper() {}
-
- /// \brief Return base feature
- const FeaturePtr& baseFeature() const
- { return myBaseFeature; }
- /// \brief Return base attribute
- const AttributePtr& baseAttribute() const
- { return myBaseAttribute; }
-
- /// \brief Check the feature is basis for this wrapper
- bool isBase(FeaturePtr theFeature) const
- { return myBaseFeature && myBaseFeature == theFeature; }
- /// \brief Check the attribute is basis for this wrapper
- bool isBase(AttributePtr theAttribute) const
- { return myBaseAttribute && myBaseAttribute == theAttribute; }
-
- /// \brief Assign list of parameters for this entity
- void setParameters(const std::list<ParameterWrapperPtr>& theParams)
- { myParameters = theParams; }
- /// \brief Return list of parameters
- const std::list<ParameterWrapperPtr>& parameters() const
- { return myParameters; }
-
- /// \brief Assign list of sub-entities
- void setSubEntities(const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& theEntities)
- { mySubEntities = theEntities; }
- /// \brief Return list of sub-entities
- const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& subEntities() const
- { return mySubEntities; }
-
- /// \brief Return ID of current entity
- virtual EntityID id() const = 0;
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the entity belongs to
- virtual const GroupID& group() const = 0;
-
- /// \brief Return type of current entity
- virtual SketchSolver_EntityType type() const = 0;
-
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const = 0;
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
-protected:
- FeaturePtr myBaseFeature;
- AttributePtr myBaseAttribute;
-
- std::list<ParameterWrapperPtr> myParameters;
- std::list<std::shared_ptr<SketchSolver_IEntityWrapper> > mySubEntities;
-};
-
-typedef std::shared_ptr<SketchSolver_IEntityWrapper> EntityWrapperPtr;
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_IParameterWrapper.h
-// Created: 1 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_IParameterWrapper_H_
-#define SketchSolver_IParameterWrapper_H_
-
-#include <SketchSolver.h>
-
-#include <memory>
-
-/**
- * Wrapper providing operations with parameters regardless the solver.
- */
-class SketchSolver_IParameterWrapper
-{
-public:
- virtual ~SketchSolver_IParameterWrapper() {}
-
- /// \brief Return ID of current parameter
- virtual ParameterID id() const = 0;
-
- /// \brief Change group for the parameter
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the parameter belongs to
- virtual const GroupID& group() const = 0;
-
- /// \brief Change value of parameter
- virtual void setValue(double theValue) = 0;
- /// \brief Return value of parameter
- virtual double value() const = 0;
-
- /// \brief Set or unset flag the parameter is given by expression
- void setIsParametric(bool isParametric)
- { myIsParametric = isParametric; }
- /// \brief Show the parameter is an expression
- bool isParametric() const
- { return myIsParametric; }
-
- /// \brief Compare current parameter with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
- /// \brief Update value of parameter by the given one
- /// \return \c true if the value of parameter is changed
- virtual bool update(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
-protected:
- bool myIsParametric; ///< indicate the parameter is given by parametric expression
-};
-
-typedef std::shared_ptr<SketchSolver_IParameterWrapper> ParameterWrapperPtr;
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_ISolver.h
-// Created: 30 Nov 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_ISolver_H_
-#define SketchSolver_ISolver_H_
-
-#include <SketchSolver.h>
-
-#include <memory>
-
-/// The result of constraints solution
-enum SketchSolver_SolveStatus {
- STATUS_OK,
- STATUS_INCONSISTENT,
- STATUS_EMPTYSET,
- STATUS_FAILED // set if no one other status is applicable
-};
-
-
-/**
- * Interface providing operations to solve sketches.
- */
-class SketchSolver_ISolver
-{
-public:
- virtual ~SketchSolver_ISolver() {}
-
- /// \brief Changes the ID of the group to solve
- void setGroup(const GroupID& theGroupID)
- { myGroup = theGroupID; }
-
- /// \brief Set or unset the flag which allows to find all failed constraints
- void calculateFailedConstraints(bool theSic)
- { myFindFaileds = theSic; }
-
- /// \brief Solve the set of equations
- /// \return identifier whether solution succeeded
- virtual SketchSolver_SolveStatus solve() = 0;
-
-protected:
- GroupID myGroup; ///< ID of the group to be solved
- bool myFindFaileds; ///< flag to find conflicting or inappropriate constraints
-};
-
-typedef std::shared_ptr<SketchSolver_ISolver> SolverPtr;
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_Manager.cpp
-// Created: 08 May 2014
-// Author: Artem ZHIDKOV
-
-#include "SketchSolver_Manager.h"
-
-#include <Events_Loop.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeRefList.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_Attribute.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Feature.h>
-
-#include <list>
-#include <set>
-#include <memory>
-
-// Initialization of constraint manager self pointer
-SketchSolver_Manager* SketchSolver_Manager::mySelf = 0;
-
-/// Global constraint manager object
-SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
-
-
-// ========================================================
-// ========= SketchSolver_Manager ===============
-// ========================================================
-SketchSolver_Manager* SketchSolver_Manager::instance()
-{
- if (!mySelf)
- mySelf = new SketchSolver_Manager();
- return mySelf;
-}
-
-SketchSolver_Manager::SketchSolver_Manager()
-{
- myGroups.clear();
- myIsComputed = false;
-
- // Register in event loop
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
-}
-
-SketchSolver_Manager::~SketchSolver_Manager()
-{
- myGroups.clear();
-}
-
-void SketchSolver_Manager::setBuilder(BuilderPtr theBuilder)
-{
- myBuilder = theBuilder;
-}
-
-BuilderPtr SketchSolver_Manager::builder()
-{
- return myBuilder;
-}
-
-// ============================================================================
-// Function: processEvent
-// Purpose: listen the event loop and process the message
-// ============================================================================
-void SketchSolver_Manager::processEvent(
- const std::shared_ptr<Events_Message>& theMessage)
-{
- if (myIsComputed)
- return;
- if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
- || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)
- || theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
- std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
- std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
-
- // Shows the message has at least one feature applicable for solver
- bool hasProperFeature = false;
-
- bool isMovedEvt = theMessage->eventID()
- == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
- if (isMovedEvt) {
- std::set<ObjectPtr>::iterator aFeatIter;
- for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
- std::shared_ptr<SketchPlugin_Feature> aSFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (aSFeature) {
- moveEntity(aSFeature);
- hasProperFeature = true;
- }
- }
- } else {
- std::list<FeaturePtr> aSketchFeatures = SketchSolver_Group::selectApplicableFeatures(aFeatures);
- std::list<FeaturePtr>::iterator aFeatIter = aSketchFeatures.begin();
- for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) {
- if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) {
- std::shared_ptr<ModelAPI_CompositeFeature> aSketch =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIter);
- hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
- continue;
- }
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (!aFeature)
- continue;
- hasProperFeature = changeFeature(aFeature) || hasProperFeature;
- }
- }
-
- // Solve the set of constraints
- if (hasProperFeature)
- resolveConstraints(isMovedEvt); // send update for movement in any case
- } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
- std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
- const std::set<std::string>& aFeatureGroups = aDeleteMsg->groups();
-
- // Find SketchPlugin_Sketch::ID() in groups. The constraint groups should be updated when an object removed from Sketch
- std::set<std::string>::const_iterator aFGrIter;
- for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
- if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
- aFGrIter->compare(ModelAPI_Feature::group()) == 0)
- break;
-
- if (aFGrIter != aFeatureGroups.end()) {
- std::vector<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
- std::list<SketchSolver_Group*> aSeparatedGroups;
- while (aGroupIter != myGroups.end()) {
- if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed
- delete *aGroupIter;
- int aShift = aGroupIter - myGroups.begin();
- myGroups.erase(aGroupIter);
- aGroupIter = myGroups.begin() + aShift;
- continue;
- }
- if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group
- (*aGroupIter)->splitGroup(aSeparatedGroups);
- }
- aGroupIter++;
- }
- if (aSeparatedGroups.size() > 0)
- myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
- }
- }
-}
-
-// ============================================================================
-// Function: changeWorkplane
-// Purpose: update workplane by given parameters of the sketch
-// ============================================================================
-bool SketchSolver_Manager::changeWorkplane(CompositeFeaturePtr theSketch)
-{
- bool aResult = true; // changed when a workplane wrongly updated
- bool isUpdated = false;
- // Try to update specified workplane in all groups
- std::vector<SketchSolver_Group*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
- isUpdated = true;
- aResult = false;
- }
- // If the workplane is not updated, so this is a new workplane
- if (!isUpdated) {
- SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch);
- // Verify that the group is created successfully
- if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) {
- delete aNewGroup;
- return false;
- }
- myGroups.push_back(aNewGroup);
- }
- return aResult;
-}
-
-// ============================================================================
-// Function: changeConstraintOrEntity
-// Purpose: create/update the constraint or the feature and place it into appropriate group
-// ============================================================================
-bool SketchSolver_Manager::changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
- // Search the groups which this feature touches
- std::set<GroupID> aGroups;
- findGroups(theFeature, aGroups);
-
- std::shared_ptr<SketchPlugin_Constraint> aConstraint =
- std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
-
- // Process the groups list
- if (aGroups.size() == 0) {
- // There are no groups applicable for this constraint => create new one
- // The group will be created only for constraints, not for features
- if (!aConstraint) return false;
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(aConstraint);
- if (!aWP)
- return false;
- SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
- if (!aGroup->changeConstraint(aConstraint)) {
- delete aGroup;
- return false;
- }
- myGroups.push_back(aGroup);
- return true;
- } else if (aGroups.size() == 1) { // Only one group => add feature into it
- GroupID aGroupId = *(aGroups.begin());
- std::vector<SketchSolver_Group*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if ((*aGroupIter)->getId() == aGroupId) {
- // If the group is empty, the feature is not added (the constraint only)
- if (!aConstraint && !(*aGroupIter)->isEmpty())
- return (*aGroupIter)->updateFeature(theFeature);
- return (*aGroupIter)->changeConstraint(aConstraint);
- }
- } else if (aGroups.size() > 1) { // Several groups applicable for this feature => need to merge them
- std::set<GroupID>::const_iterator aGroupsIter = aGroups.begin();
-
- // Search first group
- std::vector<SketchSolver_Group*>::iterator aFirstGroupIter;
- for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++)
- if ((*aFirstGroupIter)->getId() == *aGroupsIter)
- break;
- if (aFirstGroupIter == myGroups.end())
- return false;
-
- // Append other groups to the first one
- std::vector<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter + 1;
- for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
- for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
- if ((*anOtherGroupIter)->getId() == *aGroupsIter)
- break;
- if (anOtherGroupIter == myGroups.end()) { // Group disappears
- anOtherGroupIter = aFirstGroupIter + 1;
- continue;
- }
-
- (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
- int aShiftFirst = aFirstGroupIter - myGroups.begin();
- int aShiftOther = anOtherGroupIter - myGroups.begin();
- delete *anOtherGroupIter;
- myGroups.erase(anOtherGroupIter);
- aFirstGroupIter = myGroups.begin() + aShiftFirst;
- anOtherGroupIter = myGroups.begin() + aShiftOther;
- }
-
- if (aConstraint)
- return (*aFirstGroupIter)->changeConstraint(aConstraint);
- return (*aFirstGroupIter)->updateFeature(theFeature);
- }
-
- // Something goes wrong
- return false;
-}
-
-// ============================================================================
-// Function: moveEntity
-// Purpose: update element moved on the sketch, which is used by constraints
-// ============================================================================
-void SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
- std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
- for (; aGroupIt != myGroups.end(); aGroupIt++)
- if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
- (*aGroupIt)->moveFeature(theFeature);
-}
-
-// ============================================================================
-// Function: findGroups
-// Purpose: search groups of entities interacting with given feature
-// ============================================================================
-void SketchSolver_Manager::findGroups(
- std::shared_ptr<SketchPlugin_Feature> theFeature,
- std::set<GroupID>& theGroupIDs) const
-{
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
-
- SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint
- std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) {
- if (!(*aGroupIter)->isEmpty())
- theGroupIDs.insert((*aGroupIter)->getId());
- else if (!anEmptyGroup)
- anEmptyGroup = *aGroupIter;
- }
-
- // When only empty group is found, use it
- if (anEmptyGroup && theGroupIDs.empty())
- theGroupIDs.insert(anEmptyGroup->getId());
-}
-
-// ============================================================================
-// Function: findWorkplane
-// Purpose: search workplane containing given feature
-// ============================================================================
-std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_Manager
-::findWorkplane(std::shared_ptr<SketchPlugin_Feature> theFeature) const
-{
- // Already verified workplanes
- std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
-
- std::vector<SketchSolver_Group*>::const_iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
- if (aVerified.find(aWP) != aVerified.end())
- continue;
-
- DataPtr aData = aWP->data();
- if (aData->isValid()) {
- std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
- ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
- std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
- std::list<ObjectPtr>::const_iterator anIter;
- for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
- if (*anIter == theFeature)
- return aWP; // workplane is found
- }
- aVerified.insert(aWP);
- }
-
- return std::shared_ptr<ModelAPI_CompositeFeature>();
-}
-
-// ============================================================================
-// Function: resolveConstraints
-// Purpose: change entities according to available constraints
-// ============================================================================
-void SketchSolver_Manager::resolveConstraints(const bool theForceUpdate)
-{
- myIsComputed = true;
- bool needToUpdate = false;
- static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- // to avoid redisplay of each segment on update by solver one by one in the viewer
- bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
- if (isUpdateFlushed) {
- Events_Loop::loop()->setFlushed(anUpdateEvent, false);
- }
-
- std::vector<SketchSolver_Group*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if ((*aGroupIter)->resolveConstraints())
- needToUpdate = true;
-
- // Features may be updated => now send events, but for all changed at once
- if (isUpdateFlushed) {
- Events_Loop::loop()->setFlushed(anUpdateEvent, true);
- }
- // Must be before flush because on "Updated" flush the results may be produced
- // and the creation event is appeared with many new objects. If myIsComputed these
- // events are missed in processEvents and some elements are not added.
- myIsComputed = false;
- if (needToUpdate || theForceUpdate)
- Events_Loop::loop()->flush(anUpdateEvent);
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_Manager.h
-// Created: 08 May 2014
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_Manager_H_
-#define SketchSolver_Manager_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_Group.h>
-#include <SketchSolver_Builder.h>
-
-#include <Events_Listener.h>
-#include <SketchPlugin_Constraint.h>
-
-#include <vector>
-#include <set>
-
-/** \class SketchSolver_Manager
- * \ingroup Plugins
- * \brief Listens the changes of SketchPlugin features and transforms the Constraint
- * feature into the format understandable by SolveSpace library.
- *
- * Constraints created for SolveSpace library are divided into the groups.
- * The division order based on connectedness of the features by the constraints.
- * The groups may be fused or separated according to the new constraints.
- *
- * \remark This is a singleton.
- */
-class SketchSolver_Manager : public Events_Listener
-{
-public:
- /** \brief Main method to create constraint manager
- * \return pointer to the singleton
- */
- SKETCHSOLVER_EXPORT static SketchSolver_Manager* instance();
-
- /** \brief Implementation of Event Listener method
- * \param[in] theMessage the data of the event
- */
- virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
- /// \brief Initialize builder for solver's data structure entities
- /// \param theBuilder [in] solver's specific builder
- SKETCHSOLVER_EXPORT void setBuilder(BuilderPtr theBuilder);
- /// \brief Returns the builder specific for the solver
- BuilderPtr builder();
-
-protected:
- SketchSolver_Manager();
- ~SketchSolver_Manager();
-
- /** \brief Adds or updates a constraint or an entity in the suitable group
- * \param[in] theFeature sketch feature to be changed
- * \return \c true if the feature changed successfully
- */
- bool changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
- /** \brief Removes a constraint from the manager
- * \param[in] theConstraint constraint to be removed
- * \return \c true if the constraint removed successfully
- */
- bool removeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
-
- /** \brief Adds or updates a workplane in the manager
- * \param[in] theSketch the feature to create or update workplane
- * \return \c true if the workplane changed successfully
- * \remark Type of theSketch is not verified inside
- */
- bool changeWorkplane(CompositeFeaturePtr theSketch);
-
- /** \brief Removes a workplane from the manager.
- * All groups based on such workplane will be removed too.
- * \param[in] theSketch the feature to be removed
- * \return \c true if the workplane removed successfully
- */
- bool removeWorkplane(std::shared_ptr<SketchPlugin_Sketch> theSketch);
-
- /** \brief Updates entity which is moved in GUI
- * \param[in] theFeature entity to be updated
- */
- void moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
- /** \brief Goes through the list of groups and solve the constraints
- * \param theForceUpdate flushes the update event in any case: something changed or not
- */
- void resolveConstraints(const bool theForceUpdate);
-
-private:
- /** \brief Searches list of groups which interact with specified feature
- * \param[in] theFeature object to be found
- * \param[out] theGroups list of group indexes interacted with the feature
- */
- void findGroups(std::shared_ptr<SketchPlugin_Feature> theFeature,
- std::set<GroupID>& theGroupIDs) const;
-
- /** \brief Searches in the list of groups the workplane which contains specified feature
- * \param[in] theFeature object to be found
- * \return workplane containing the feature
- */
- std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
- std::shared_ptr<SketchPlugin_Feature> theFeature) const;
-
-private:
- static SketchSolver_Manager* mySelf; ///< Self pointer to implement singleton functionality
- std::vector<SketchSolver_Group*> myGroups; ///< Groups of constraints
- BuilderPtr myBuilder; ///< Builder for solver's entities
- /// true if computation is performed and all "updates" are generated by this algo
- /// and needs no recomputation
- bool myIsComputed;
-};
-
-#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_Solver.cpp
+// Created: 07 May 2014
+// Author: Artem ZHIDKOV
+
+#include "SketchSolver_Solver.h"
+#include <Events_LongOp.h>
+
+SketchSolver_Solver::SketchSolver_Solver()
+{
+ myGroupID = 0;
+ // Nullify all elements of the set of equations
+ myEquationsSystem.param = 0;
+ myEquationsSystem.params = 0;
+ myEquationsSystem.entity = 0;
+ myEquationsSystem.entities = 0;
+ myEquationsSystem.constraint = 0;
+ myEquationsSystem.constraints = 0;
+ myEquationsSystem.failed = 0;
+ myEquationsSystem.faileds = 0;
+
+ myEquationsSystem.dragged[0] = 0;
+ myEquationsSystem.dragged[1] = 0;
+ myEquationsSystem.dragged[2] = 0;
+ myEquationsSystem.dragged[3] = 0;
+
+ // If the set of constraints is inconsistent,
+ // the failed field will contain wrong constraints
+ myEquationsSystem.calculateFaileds = 0;
+}
+
+SketchSolver_Solver::~SketchSolver_Solver()
+{
+ if (myEquationsSystem.constraint)
+ delete[] myEquationsSystem.constraint;
+ myEquationsSystem.constraint = 0;
+ if (myEquationsSystem.failed)
+ delete[] myEquationsSystem.failed;
+ myEquationsSystem.failed = 0;
+}
+
+void SketchSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
+{
+ myEquationsSystem.param = theParameters;
+ myEquationsSystem.params = theSize;
+}
+
+
+void SketchSolver_Solver::setDraggedParameters(const Slvs_hParam* theDragged)
+{
+ for (unsigned int i = 0; i < 4; i++)
+ myEquationsSystem.dragged[i] = theDragged[i];
+}
+
+void SketchSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
+{
+ myEquationsSystem.entity = theEntities;
+ myEquationsSystem.entities = theSize;
+}
+
+void SketchSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
+{
+ if (!myEquationsSystem.constraint) {
+ myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ myEquationsSystem.constraints = theSize;
+ myEquationsSystem.failed = new Slvs_hConstraint[theSize];
+ }
+ else if (myEquationsSystem.constraints != theSize) {
+ if (theSize > myEquationsSystem.constraints) {
+ delete[] myEquationsSystem.constraint;
+ myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ if (myEquationsSystem.failed)
+ delete[] myEquationsSystem.failed;
+ myEquationsSystem.failed = new Slvs_hConstraint[theSize];
+ }
+ myEquationsSystem.constraints = theSize;
+ }
+ memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
+ memset(myEquationsSystem.failed, SLVS_C_UNKNOWN, theSize * sizeof(Slvs_hConstraint));
+}
+
+
+int SketchSolver_Solver::solve()
+{
+ if (myEquationsSystem.constraints <= 0)
+ return SLVS_RESULT_EMPTY_SET;
+
+ Events_LongOp::start(this);
+ Slvs_Solve(&myEquationsSystem, myGroupID);
+ Events_LongOp::end(this);
+
+ return myEquationsSystem.result;
+}
+
+bool SketchSolver_Solver::getResult(std::vector<Slvs_Param>& theParameters)
+{
+ if (myEquationsSystem.result != SLVS_RESULT_OKAY)
+ return false;
+
+ if (theParameters.size() != myEquationsSystem.params)
+ return false; // number of parameters is not the same
+
+ std::vector<Slvs_Param>::iterator aParamIter = theParameters.begin();
+ for (int i = 0; i < myEquationsSystem.params; i++, aParamIter++) {
+ if (myEquationsSystem.param[i].h != aParamIter->h)
+ return false; // sequence of parameters was changed
+ aParamIter->val = myEquationsSystem.param[i].val;
+ }
+
+ return true;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_Solver.h
+// Created: 07 May 2014
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_Solver_H_
+#define SketchSolver_Solver_H_
+
+#include "SketchSolver.h"
+
+// Need to be defined before including SolveSpace to avoid additional dependances on Windows platform
+#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES)
+typedef unsigned int UINT32;
+#else
+#include <stdint.h>
+#endif
+#include <string.h>
+#include <slvs.h>
+
+#include <vector>
+
+#define SLVS_RESULT_EMPTY_SET -1
+
+// Unknown constraint (for error reporting)
+#define SLVS_C_UNKNOWN 0
+// Fillet constraint identifier
+#define SLVS_C_FILLET 100100
+// Multi-rotation constraint identifier
+#define SLVS_C_MULTI_ROTATION 100101
+// Multi-translation constraint identifier
+#define SLVS_C_MULTI_TRANSLATION 100102
+// Unknown entity
+#define SLVS_E_UNKNOWN 0
+// Unknown group
+#define SLVS_G_UNKNOWN 0
+// Group ID to store external objects
+#define SLVS_G_OUTOFGROUP 1
+
+/**
+ * The main class that performs the high-level operations for connection to the SolveSpace.
+ */
+class SketchSolver_Solver
+{
+ public:
+ SketchSolver_Solver();
+ ~SketchSolver_Solver();
+
+ /** \brief Initialize the ID of the group
+ */
+ inline void setGroupID(Slvs_hGroup theGroupID)
+ {
+ myGroupID = theGroupID;
+ }
+
+ /** \brief Change array of parameters
+ * \param[in] theParameters pointer to the array of parameters
+ * \param[in] theSize size of this array
+ */
+ void setParameters(Slvs_Param* theParameters, int theSize);
+
+ /** \brief Change array of entities
+ * \param[in] theEntities pointer to the array of entities
+ * \param[in] theSize size of this array
+ */
+ void setEntities(Slvs_Entity* theEntities, int theSize);
+
+ /** \brief Change array of constraints
+ * \param[in] theConstraints pointer to the array of constraints
+ * \param[in] theSize size of this array
+ */
+ void setConstraints(Slvs_Constraint* theConstraints, int theSize);
+
+ /** \brief Store the parameters of the point which was moved by user.
+ * The solver will watch this items to be constant
+ * \param[in] theDragged list of parameters (not more than 4) which should not be changed during solving
+ */
+ void setDraggedParameters(const Slvs_hParam* theDragged);
+
+ /** \brief Set or unset the flag which allows to find all failed constraints
+ */
+ void calculateFailedConstraints(bool theSic)
+ { myEquationsSystem.calculateFaileds = theSic ? 1 : 0; }
+
+ /** \brief Solve the set of equations
+ * \return identifier whether solution succeeded
+ */
+ int solve();
+
+ /** \brief Updates the list of parameters by calculated values
+ * \param[in,out] theParameters parameters to be updated
+ * \return \c true if parameters are updated correctly
+ */
+ bool getResult(std::vector<Slvs_Param>& theParameters);
+
+ private:
+ Slvs_hGroup myGroupID; ///< identifier of the group to be solved
+ Slvs_System myEquationsSystem; ///< set of equations for solving in SolveSpace
+};
+
+#endif
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
// File: SketchSolver_Storage.cpp
-// Created: 30 Nov 2015
+// Created: 18 Mar 2015
// Author: Artem ZHIDKOV
#include <SketchSolver_Storage.h>
-#include <SketchSolver_Manager.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeRefAttr.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <math.h>
+/** \brief Search the entity/parameter with specified ID in the list of elements
+ * \param[in] theEntityID unique ID of the element
+ * \param[in] theEntities list of elements
+ * \return position of the found element or -1 if the element is not found
+ */
+template<typename T>
+static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
-/// \brief Verify two vectors of constraints are equal.
-/// Vectors differ by the order of elements are equal.
-static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
- const std::list<ConstraintWrapperPtr>& theCVec2);
+/// \brief Compare two parameters to be different
+static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
+/// \brief Compare two entities to be different
+static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
+/// \brief Compare two constriants to be different
+static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
-void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
- ConstraintWrapperPtr theSolverConstraint)
+SketchSolver_Storage::SketchSolver_Storage()
+ : myParamMaxID(SLVS_E_UNKNOWN),
+ myEntityMaxID(SLVS_E_UNKNOWN),
+ myConstrMaxID(SLVS_C_UNKNOWN),
+ myFixed(SLVS_E_UNKNOWN),
+ myNeedToResolve(false),
+ myDuplicatedConstraint(false)
{
- std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
- addConstraint(theConstraint, aConstrList);
}
-void SketchSolver_Storage::addConstraint(
- ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints)
+Slvs_hParam SketchSolver_Storage::addParameter(const Slvs_Param& theParam)
{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aFound = myConstraintMap.find(theConstraint);
- if (!isEqual(aFound->second, theSolverConstraints))
- setNeedToResolve(true);
+ if (theParam.h > 0 && theParam.h <= myParamMaxID) {
+ // parameter is already used, rewrite it
+ return updateParameter(theParam);
+ }
+
+ Slvs_Param aParam = theParam;
+ if (aParam.h > myParamMaxID)
+ myParamMaxID = aParam.h;
+ else
+ aParam.h = ++myParamMaxID;
+ myParameters.push_back(aParam);
+ myNeedToResolve = true;
+ return aParam.h;
+}
+
+Slvs_hParam SketchSolver_Storage::updateParameter(const Slvs_Param& theParam)
+{
+ if (theParam.h > 0 && theParam.h <= myParamMaxID) {
+ // parameter already used, rewrite it
+ int aPos = Search(theParam.h, myParameters);
+ if (aPos >= 0 && aPos < (int)myParameters.size()) {
+ if (IsNotEqual(myParameters[aPos], theParam))
+ myUpdatedParameters.insert(theParam.h);
+ myParameters[aPos] = theParam;
+ return theParam.h;
+ }
+ }
+
+ // Parameter is not found, add new one
+ Slvs_Param aParam = theParam;
+ aParam.h = 0;
+ return addParameter(aParam);
+}
- // Do not add point-point coincidence, because it is already made by setting
- // the same parameters for both points
- if (!theSolverConstraints.empty() &&
- theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
- std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
- for (; aCIt != theSolverConstraints.end(); ++aCIt)
- update(*aCIt);
+bool SketchSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
+{
+ int aPos = Search(theParamID, myParameters);
+ if (aPos >= 0 && aPos < (int)myParameters.size()) {
+ // Firstly, search the parametes is not used elsewhere
+ std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+ for (; anEntIter != myEntities.end(); anEntIter++) {
+ for (int i = 0; i < 4; i++)
+ if (anEntIter->param[i] == theParamID)
+ return false;
+ }
+ // Remove parameter
+ myParameters.erase(myParameters.begin() + aPos);
+ myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
+ myNeedToResolve = true;
+ myRemovedParameters.insert(theParamID);
+ return true;
}
- myConstraintMap[theConstraint] = theSolverConstraints;
+ return false;
}
-void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
- EntityWrapperPtr theSolverEntity)
+const Slvs_Param& SketchSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
{
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
- if (aFound == myFeatureMap.end() || !aFound->second->isEqual(theSolverEntity))
- setNeedToResolve(true); // the entity is new or modified
+ int aPos = Search(theParamID, myParameters);
+ if (aPos >= 0 && aPos < (int)myParameters.size())
+ return myParameters[aPos];
- myFeatureMap[theFeature] = theSolverEntity;
+ // Parameter is not found, return empty object
+ static Slvs_Param aDummy;
+ aDummy.h = 0;
+ return aDummy;
}
-void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
- EntityWrapperPtr theSolverEntity)
+
+Slvs_hEntity SketchSolver_Storage::addEntity(const Slvs_Entity& theEntity)
{
- std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
- if (aFound == myAttributeMap.end() || !aFound->second->isEqual(theSolverEntity))
- setNeedToResolve(true); // the entity is new or modified
+ if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
+ // Entity is already used, rewrite it
+ return updateEntity(theEntity);
+ }
- myAttributeMap[theAttribute] = theSolverEntity;
+ Slvs_Entity aEntity = theEntity;
+ if (aEntity.h > myEntityMaxID)
+ myEntityMaxID = aEntity.h;
+ else
+ aEntity.h = ++myEntityMaxID;
+ myEntities.push_back(aEntity);
+ myNeedToResolve = true;
+ return aEntity.h;
}
+Slvs_hEntity SketchSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
+{
+ if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
+ // Entity already used, rewrite it
+ int aPos = Search(theEntity.h, myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
+ myEntities[aPos] = theEntity;
+ return theEntity.h;
+ }
+ }
+
+ // Entity is not found, add new one
+ Slvs_Entity aEntity = theEntity;
+ aEntity.h = 0;
+ return addEntity(aEntity);
+}
-bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
+bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
{
- bool isUpdated = false;
- EntityWrapperPtr aRelated = entity(theFeature);
- if (!aRelated) { // Feature is not exist, create it
- std::list<EntityWrapperPtr> aSubs;
- // Firstly, create/update its attributes
- std::list<AttributePtr> anAttrs =
- theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
- for (; anIt != anAttrs.end(); ++anIt) {
- isUpdated = update(*anIt, theGroup) || isUpdated;
- aSubs.push_back(entity(*anIt));
+ bool aResult = true;
+ int aPos = Search(theEntityID, myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ // Firstly, check the entity and its attributes is not used elsewhere
+ std::set<Slvs_hEntity> anEntAndSubs;
+ anEntAndSubs.insert(theEntityID);
+ for (int i = 0; i < 4; i++)
+ if (myEntities[aPos].point[i] != SLVS_E_UNKNOWN)
+ anEntAndSubs.insert(myEntities[aPos].point[i]);
+
+ std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+ for (; anEntIter != myEntities.end(); anEntIter++) {
+ for (int i = 0; i < 4; i++)
+ if (anEntAndSubs.find(anEntIter->point[i]) != anEntAndSubs.end())
+ return false;
+ if (anEntAndSubs.find(anEntIter->distance) != anEntAndSubs.end())
+ return false;
}
- // If the feature is a circle, add its radius as a sub
- if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
- AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
- isUpdated = update(aRadius, theGroup) || isUpdated;
- aSubs.push_back(entity(aRadius));
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++) {
+ Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
+ aConstrIter->entityA, aConstrIter->entityB,
+ aConstrIter->entityC, aConstrIter->entityD};
+ for (int i = 0; i < 6; i++)
+ if (anEntAndSubs.find(anEntIDs[i]) != anEntAndSubs.end())
+ return false;
+ }
+ // The entity is not used, remove it and its parameters
+ Slvs_Entity anEntity = myEntities[aPos];
+ myEntities.erase(myEntities.begin() + aPos);
+ myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
+ if (anEntity.distance != SLVS_E_UNKNOWN)
+ aResult = aResult && removeParameter(anEntity.distance);
+ for (int i = 0; i < 4; i++)
+ if (anEntity.param[i] != SLVS_E_UNKNOWN)
+ aResult = removeParameter(anEntity.param[i]) && aResult;
+ for (int i = 0; i < 4; i++)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN)
+ aResult = removeEntity(anEntity.point[i]) && aResult;
+ myNeedToResolve = true;
+ myRemovedEntities.insert(theEntityID);
+ if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
+ removeCoincidentPoint(theEntityID);
+ }
+ return aResult;
+}
+
+void SketchSolver_Storage::removeUnusedEntities()
+{
+ std::set<Slvs_hEntity> anUnusedEntities;
+ std::vector<Slvs_Entity>::const_iterator aEIt = myEntities.begin();
+ for (; aEIt != myEntities.end(); ++aEIt) {
+ if (aEIt->h == aEIt->wrkpl) {
+ // don't remove workplane
+ anUnusedEntities.erase(aEIt->point[0]);
+ anUnusedEntities.erase(aEIt->normal);
+ continue;
}
- // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
- if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
- theFeature->getKind() == SketchPlugin_Circle::ID()) {
- EntityWrapperPtr aNormal = getNormal();
- if (aNormal) aSubs.push_back(aNormal);
+ anUnusedEntities.insert(aEIt->h);
+ }
+
+ std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end(); ++aCIt) {
+ Slvs_hEntity aSubs[6] = {
+ aCIt->entityA, aCIt->entityB,
+ aCIt->entityC, aCIt->entityD,
+ aCIt->ptA, aCIt->ptB};
+ for (int i = 0; i < 6; i++) {
+ if (aSubs[i] != SLVS_E_UNKNOWN) {
+ anUnusedEntities.erase(aSubs[i]);
+ int aPos = Search(aSubs[i], myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ for (int j = 0; j < 4; j++)
+ if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN)
+ anUnusedEntities.erase(myEntities[aPos].point[j]);
+ if (myEntities[aPos].distance != SLVS_E_UNKNOWN)
+ anUnusedEntities.erase(myEntities[aPos].distance);
+ }
+ }
}
- // Secondly, convert feature
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- aRelated = aBuilder->createFeature(theFeature, aSubs, theGroup);
- if (!aRelated)
- return false;
- addEntity(theFeature, aRelated);
- } else if (theGroup != GID_UNKNOWN)
- changeGroup(aRelated, theGroup);
- return update(aRelated) || isUpdated;
+ }
+
+ std::set<Slvs_hEntity>::const_iterator anEntIt = anUnusedEntities.begin();
+ while (anEntIt != anUnusedEntities.end()) {
+ int aPos = Search(*anEntIt, myEntities);
+ if (aPos < 0 && aPos >= (int)myEntities.size())
+ continue;
+ Slvs_Entity anEntity = myEntities[aPos];
+ // Remove entity if and only if all its parameters unused
+ bool isUsed = false;
+ if (anEntity.distance != SLVS_E_UNKNOWN &&
+ anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end())
+ isUsed = true;
+ for (int i = 0; i < 4 && !isUsed; i++)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN &&
+ anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end())
+ isUsed = true;
+ if (isUsed) {
+ anUnusedEntities.erase(anEntity.distance);
+ for (int i = 0; i < 4; i++)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN)
+ anUnusedEntities.erase(anEntity.point[i]);
+ std::set<Slvs_hEntity>::iterator aRemoveIt = anEntIt++;
+ anUnusedEntities.erase(aRemoveIt);
+ continue;
+ }
+ ++anEntIt;
+ }
+
+ for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) {
+ int aPos = Search(*anEntIt, myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ // Remove entity and its parameters
+ Slvs_Entity anEntity = myEntities[aPos];
+ myEntities.erase(myEntities.begin() + aPos);
+ myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
+ if (anEntity.distance != SLVS_E_UNKNOWN)
+ removeParameter(anEntity.distance);
+ for (int i = 0; i < 4; i++)
+ if (anEntity.param[i] != SLVS_E_UNKNOWN)
+ removeParameter(anEntity.param[i]);
+ for (int i = 0; i < 4; i++)
+ if (anEntity.point[i] != SLVS_E_UNKNOWN)
+ removeEntity(anEntity.point[i]);
+ myRemovedEntities.insert(*anEntIt);
+ if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
+ removeCoincidentPoint(*anEntIt);
+ }
+ }
+
+ if (!anUnusedEntities.empty())
+ myNeedToResolve = true;
+}
+
+bool SketchSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const
+{
+ std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end(); ++aCIt) {
+ Slvs_hEntity aSubs[6] = {
+ aCIt->entityA, aCIt->entityB,
+ aCIt->entityC, aCIt->entityD,
+ aCIt->ptA, aCIt->ptB};
+ for (int i = 0; i < 6; i++)
+ if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID)
+ return true;
+ }
+ return false;
+}
+
+const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
+{
+ int aPos = Search(theEntityID, myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size())
+ return myEntities[aPos];
+
+ // Entity is not found, return empty object
+ static Slvs_Entity aDummy;
+ aDummy.h = SLVS_E_UNKNOWN;
+ return aDummy;
+}
+
+Slvs_hEntity SketchSolver_Storage::copyEntity(const Slvs_hEntity& theCopied)
+{
+ int aPos = Search(theCopied, myEntities);
+ if (aPos < 0 || aPos >= (int)myEntities.size())
+ return SLVS_E_UNKNOWN;
+
+ Slvs_Entity aCopy = myEntities[aPos];
+ aCopy.h = SLVS_E_UNKNOWN;
+ int i = 0;
+ while (aCopy.point[i] != SLVS_E_UNKNOWN) {
+ aCopy.point[i] = copyEntity(aCopy.point[i]);
+ i++;
+ }
+ if (aCopy.param[0] != SLVS_E_UNKNOWN) {
+ aPos = Search(aCopy.param[0], myParameters);
+ i = 0;
+ while (aCopy.param[i] != SLVS_E_UNKNOWN) {
+ Slvs_Param aNewParam = myParameters[aPos];
+ aNewParam.h = SLVS_E_UNKNOWN;
+ aCopy.param[i] = addParameter(aNewParam);
+ i++;
+ aPos++;
+ }
+ }
+ return addEntity(aCopy);
+}
+
+void SketchSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo)
+{
+ int aPosFrom = Search(theFrom, myEntities);
+ int aPosTo = Search(theTo, myEntities);
+ if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() ||
+ aPosTo < 0 || aPosTo >= (int)myEntities.size())
+ return;
+
+ Slvs_Entity aEntFrom = myEntities[aPosFrom];
+ Slvs_Entity aEntTo = myEntities[aPosTo];
+ int i = 0;
+ while (aEntFrom.point[i] != SLVS_E_UNKNOWN) {
+ copyEntity(aEntFrom.point[i], aEntTo.point[i]);
+ i++;
+ }
+ if (aEntFrom.param[0] != SLVS_E_UNKNOWN) {
+ aPosFrom = Search(aEntFrom.param[0], myParameters);
+ aPosTo = Search(aEntTo.param[0], myParameters);
+ i = 0;
+ while (aEntFrom.param[i] != SLVS_E_UNKNOWN) {
+ myParameters[aPosTo++].val = myParameters[aPosFrom++].val;
+ i++;
+ }
+ }
}
-bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
+
+bool SketchSolver_Storage::isPointFixed(
+ const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
+{
+ // Search the set of coincident points
+ std::set<Slvs_hEntity> aCoincident;
+ aCoincident.insert(thePointID);
+ std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+ for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+ if (aCPIter->find(thePointID) != aCPIter->end()) {
+ aCoincident = *aCPIter;
+ break;
+ }
+
+ // Check whether one of coincident points is out-of-group
+ std::set<Slvs_hEntity>::const_iterator aCoincIt = aCoincident.begin();
+ for (; aCoincIt != aCoincident.end(); ++aCoincIt) {
+ Slvs_Entity aPoint = getEntity(*aCoincIt);
+ if (aPoint.group == SLVS_G_OUTOFGROUP)
+ return true;
+ }
+
+ // Search the Rigid constraint
+ theFixed = SLVS_C_UNKNOWN;
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
+ theFixed = aConstrIter->h;
+ if (aConstrIter->ptA == thePointID)
+ return true;
+ }
+ if (theFixed != SLVS_C_UNKNOWN)
+ return true;
+
+ if (theAccurate) {
+ // Try to find the fixed entity which uses such point or its coincidence
+ std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
+ for (; anEntIter != myEntities.end(); anEntIter++) {
+ for (int i = 0; i < 4; i++) {
+ Slvs_hEntity aPt = anEntIter->point[i];
+ if (aPt != SLVS_E_UNKNOWN &&
+ (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
+ if (isEntityFixed(anEntIter->h, true))
+ return true;
+ }
+ }
+ }
+ }
+ return SLVS_E_UNKNOWN;
+}
+
+bool SketchSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- return update(aFeature, theGroup);
- } else
- anAttribute = aRefAttr->attr();
+ int aPos = Search(theEntityID, myEntities);
+ if (aPos < 0 || aPos >= (int)myEntities.size())
+ return false;
+
+ // Firstly, find how many points are under Rigid constraint
+ int aNbFixed = 0;
+ for (int i = 0; i < 4; i++) {
+ Slvs_hEntity aPoint = myEntities[aPos].point[i];
+ if (aPoint == SLVS_E_UNKNOWN)
+ continue;
+
+ std::set<Slvs_hEntity> aCoincident;
+ aCoincident.insert(aPoint);
+ std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+ for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+ if (aCPIter->find(aPoint) != aCPIter->end()) {
+ aCoincident = *aCPIter;
+ break;
+ }
+
+ // Search the Rigid constraint
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aCoincident.find(aConstrIter->ptA) != aCoincident.end())
+ aNbFixed++;
}
- EntityWrapperPtr aRelated = entity(anAttribute);
- if (!aRelated) { // Attribute is not exist, create it
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- aRelated = aBuilder->createAttribute(anAttribute, theGroup);
- if (!aRelated)
+ std::list<Slvs_Constraint> aList;
+ std::list<Slvs_Constraint>::iterator anIt;
+ Slvs_hConstraint aTempID; // used in isPointFixed() method
+
+ if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
+ if (aNbFixed == 2)
+ return true;
+ else if (aNbFixed == 0 || !theAccurate)
+ return false;
+ // Additional check (the line may be fixed if it is used by different constraints):
+ // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
+ aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
+ break;
+ if (anIt != aList.end()) {
+ aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ }
+ // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints
+ aList = getConstraintsByType(SLVS_C_PARALLEL);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ break;
+ }
+ if (anIt != aList.end()) {
+ aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
+ (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
+ return true;
+ }
+ // 3. Another verifiers ...
+ } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
+ if (aNbFixed == 0)
+ return false;
+ // Search for Diameter constraint
+ aList = getConstraintsByType(SLVS_C_DIAMETER);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID)
+ return true;
+ if (!theAccurate)
+ return false;
+ // Additional check (the circle may be fixed if it is used by different constraints):
+ // 1. The circle is used in Equal constraint and another entity is fixed
+ aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ // 2. Another verifiers ...
+ } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
+ if (aNbFixed > 2)
+ return true;
+ else if (aNbFixed <= 1)
+ return false;
+ // Search for Diameter constraint
+ aList = getConstraintsByType(SLVS_C_DIAMETER);
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID)
+ return true;
+ if (!theAccurate)
return false;
- addEntity(anAttribute, aRelated);
- } else if (theGroup != GID_UNKNOWN)
- changeGroup(aRelated, theGroup);
- return update(aRelated);
+ // Additional check (the arc may be fixed if it is used by different constraints):
+ // 1. The arc is used in Equal constraint and another entity is fixed
+ aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
+ for (anIt = aList.begin(); anIt != aList.end(); anIt++)
+ if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
+ Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
+ if (isEntityFixed(anOther, false))
+ return true;
+ }
+ // 2. Another verifiers ...
+ }
+ return false;
}
+Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
+{
+ if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
+ // Constraint is already used, rewrite it
+ return updateConstraint(theConstraint);
+ }
+
+ Slvs_Constraint aConstraint = theConstraint;
+
+ // Find a constraint with same type uses same arguments to show user overconstraint situation
+ std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end(); aCIt++) {
+ if (aConstraint.type != aCIt->type)
+ continue;
+ if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
+ aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
+ aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
+ myDuplicatedConstraint = true;
+ }
+
+ if (aConstraint.h > myConstrMaxID)
+ myConstrMaxID = aConstraint.h;
+ else
+ aConstraint.h = ++myConstrMaxID;
+ myConstraints.push_back(aConstraint);
+ myNeedToResolve = true;
+ if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
+ return aConstraint.h;
+}
-const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
- const ConstraintPtr& theConstraint) const
+Slvs_hConstraint SketchSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
{
- static std::list<ConstraintWrapperPtr> aDummy;
+ if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
+ // Constraint already used, rewrite it
+ int aPos = Search(theConstraint.h, myConstraints);
+ if (aPos >= 0 && aPos < (int)myConstraints.size()) {
+ myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
+ myConstraints[aPos] = theConstraint;
+ if (theConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ addCoincidentPoints(theConstraint.ptA, theConstraint.ptB);
+ return theConstraint.h;
+ }
+ }
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
- aFound = myConstraintMap.find(theConstraint);
- if (aFound != myConstraintMap.end())
- return aFound->second;
- return aDummy;
+ // Constraint is not found, add new one
+ Slvs_Constraint aConstraint = theConstraint;
+ aConstraint.h = 0;
+ return addConstraint(aConstraint);
+}
+
+bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
+{
+ bool aResult = true;
+ int aPos = Search(theConstraintID, myConstraints);
+ if (aPos >= 0 && aPos < (int)myConstraints.size()) {
+ Slvs_Constraint aConstraint = myConstraints[aPos];
+ myConstraints.erase(myConstraints.begin() + aPos);
+ myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
+ myNeedToResolve = true;
+ myRemovedConstraints.insert(theConstraintID);
+ if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ removeCoincidence(aConstraint);
+
+ // Remove all entities
+ Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
+ aConstraint.entityA, aConstraint.entityB,
+ aConstraint.entityC, aConstraint.entityD};
+ for (int i = 0; i < 6; i++)
+ if (anEntities[i] != SLVS_E_UNKNOWN)
+ aResult = removeEntity(anEntities[i]) && aResult;
+ // remove temporary fixed point, if available
+ if (myFixed == theConstraintID)
+ myFixed = SLVS_E_UNKNOWN;
+ if (myDuplicatedConstraint) {
+ // Check the duplicated constraints are still available
+ myDuplicatedConstraint = false;
+ std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
+ std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
+ for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
+ for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
+ if (anIt1->type != anIt2->type)
+ continue;
+ if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
+ anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
+ anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
+ myDuplicatedConstraint = true;
+ }
+ }
+ }
+ return aResult;
}
-const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
+const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
{
- static EntityWrapperPtr aDummy;
+ int aPos = Search(theConstraintID, myConstraints);
+ if (aPos >= 0 && aPos < (int)myConstraints.size())
+ return myConstraints[aPos];
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
- if (aFound != myFeatureMap.end())
- return aFound->second;
+ // Constraint is not found, return empty object
+ static Slvs_Constraint aDummy;
+ aDummy.h = 0;
return aDummy;
}
-const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
+std::list<Slvs_Constraint> SketchSolver_Storage::getConstraintsByType(int theConstraintType) const
+{
+ std::list<Slvs_Constraint> aResult;
+ std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); aCIter++)
+ if (aCIter->type == theConstraintType)
+ aResult.push_back(*aCIter);
+ return aResult;
+}
+
+
+void SketchSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
+{
+ if (myFixed != SLVS_E_UNKNOWN)
+ return; // the point is already fixed
+ int aPos = Search(theConstraintID, myConstraints);
+ if (aPos >= 0 && aPos < (int)myConstraints.size())
+ myFixed = theConstraintID;
+}
+
+void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
{
- static EntityWrapperPtr aDummy;
+ myTemporaryConstraints.insert(theConstraintID);
+}
- std::map<AttributePtr, EntityWrapperPtr>::const_iterator
- aFound = myAttributeMap.find(theAttribute);
- if (aFound != myAttributeMap.end())
- return aFound->second;
+void SketchSolver_Storage::removeTemporaryConstraints()
+{
+ myTemporaryConstraints.clear();
+}
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- return entity(aFeature);
- } else
- return entity(aRefAttr->attr());
+int SketchSolver_Storage::deleteTemporaryConstraint()
+{
+ if (myTemporaryConstraints.empty())
+ return 0;
+ // Search the point-on-line or a non-rigid constraint
+ std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
+ for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
+ int aPos = Search(*aCIt, myConstraints);
+ if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
+ break;
+ std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
+ for (; anIt != myConstraints.end(); anIt++)
+ if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
+ break;
+ if (anIt != myConstraints.end())
+ break;
}
- return aDummy;
+ if (aCIt == myTemporaryConstraints.end())
+ aCIt = myTemporaryConstraints.begin();
+ bool aNewFixed = (*aCIt == myFixed);
+ removeConstraint(*aCIt);
+ myTemporaryConstraints.erase(aCIt);
+ if (aNewFixed) {
+ for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
+ int aPos = Search(*aCIt, myConstraints);
+ if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
+ myFixed = *aCIt;
+ break;
+ }
+ }
+ }
+ return (int)myTemporaryConstraints.size();
}
-////const ParameterWrapperPtr& SketchSolver_Storage::parameter(const AttributeDoublePtr& theAttribute) const
-////{
-//// static ParameterWrapperPtr aDummy;
-////
-//// std::map<AttributeDoublePtr, ParameterWrapperPtr>::const_iterator
-//// aFound = myParametersMap.find(theAttribute);
-//// if (aFound != myParametersMap.end())
-//// return aFound->second;
-//// return aDummy;
-////}
+bool SketchSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
+{
+ return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
+}
-bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
+void SketchSolver_Storage::getRemoved(
+ std::set<Slvs_hParam>& theParameters,
+ std::set<Slvs_hEntity>& theEntities,
+ std::set<Slvs_hConstraint>& theConstraints)
{
- if (!theFeature)
- return false;
- if (myConstraintMap.empty())
- return true; // empty storage interacts with each feature
+ theParameters = myRemovedParameters;
+ theEntities = myRemovedEntities;
+ theConstraints = myRemovedConstraints;
+
+ myRemovedParameters.clear();
+ myRemovedEntities.clear();
+ myRemovedConstraints.clear();
+}
+
+void SketchSolver_Storage::initializeSolver(SketchSolver_Solver& theSolver)
+{
+ theSolver.setParameters(myParameters.data(), (int)myParameters.size());
+ theSolver.setEntities(myEntities.data(), (int)myEntities.size());
+
+ // Copy constraints excluding the fixed one
+ std::vector<Slvs_Constraint> aConstraints = myConstraints;
+ if (myFixed != SLVS_E_UNKNOWN) {
+ Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
+ std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
+ for (; anIt != aConstraints.end(); anIt++)
+ if (anIt->h == myFixed) {
+ aFixedPoint = anIt->ptA;
+ aConstraints.erase(anIt);
+ break;
+ }
+ // set dragged parameters
+ int aPos = Search(aFixedPoint, myEntities);
+ theSolver.setDraggedParameters(myEntities[aPos].param);
+ }
+ theSolver.setConstraints(aConstraints.data(), (int)aConstraints.size());
+}
+
+void SketchSolver_Storage::addCoincidentPoints(
+ const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
+{
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+ std::vector< std::set<Slvs_hEntity> >::iterator aFoundIter = myCoincidentPoints.end(); // already found coincidence
+ bool isFound = false;
+ for (; aCIter != myCoincidentPoints.end(); aCIter++) {
+ bool isFirstFound = aCIter->find(thePoint1) != aCIter->end();
+ bool isSecondFound = aCIter->find(thePoint2) != aCIter->end();
+ isFound = isFound || isFirstFound || isSecondFound;
+ if (isFirstFound && isSecondFound)
+ break; // already coincident
+ else if (isFirstFound || isSecondFound) {
+ if (aFoundIter != myCoincidentPoints.end()) {
+ // merge two sets
+ aFoundIter->insert(aCIter->begin(), aCIter->end());
+ myCoincidentPoints.erase(aCIter);
+ break;
+ } else
+ aFoundIter = aCIter;
+ aCIter->insert(thePoint1);
+ aCIter->insert(thePoint2);
+ }
+ }
+ // coincident points not found
+ if (!isFound) {
+ std::set<Slvs_hEntity> aNewSet;
+ aNewSet.insert(thePoint1);
+ aNewSet.insert(thePoint2);
+ myCoincidentPoints.push_back(aNewSet);
+ }
+}
+
+void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint)
+{
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+ for (; aCIter != myCoincidentPoints.end(); aCIter++)
+ if (aCIter->find(thePoint) != aCIter->end()) {
+ aCIter->erase(thePoint);
+ if (aCIter->size() <= 1)
+ myCoincidentPoints.erase(aCIter);
+ break;
+ }
+}
- ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
- if (aConstraint) {
- if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
+void SketchSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence)
+{
+ // Find set of coincident points
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIt = myCoincidentPoints.begin();
+ for (; aCIt != myCoincidentPoints.end(); ++aCIt)
+ if (aCIt->find(theCoincidence.ptA) != aCIt->end() ||
+ aCIt->find(theCoincidence.ptB) != aCIt->end())
+ break;
+ if (aCIt == myCoincidentPoints.end())
+ return;
+
+ // Leave only the points which are still coincident
+ std::set<Slvs_hEntity> aRemainCoincidence;
+ std::vector<Slvs_Constraint>::const_iterator aConstrIt = myConstraints.begin();
+ for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
+ if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT)
+ continue;
+ if (aCIt->find(aConstrIt->ptA) != aCIt->end() ||
+ aCIt->find(aConstrIt->ptB) != aCIt->end()) {
+ aRemainCoincidence.insert(aConstrIt->ptA);
+ aRemainCoincidence.insert(aConstrIt->ptB);
+ }
+ }
+ if (aRemainCoincidence.size() <= 1)
+ myCoincidentPoints.erase(aCIt);
+ else
+ aCIt->swap(aRemainCoincidence);
+}
+
+bool SketchSolver_Storage::isCoincident(
+ const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
+{
+ std::vector< std::set<Slvs_hEntity> >::const_iterator aCIter = myCoincidentPoints.begin();
+ for (; aCIter != myCoincidentPoints.end(); aCIter++)
+ if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end())
return true;
- } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
+ return false;
+}
+
+bool SketchSolver_Storage::isEqual(
+ const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
+{
+ if (isCoincident(thePoint1, thePoint2))
return true;
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt)
- if (isInteract(*anIt))
+ // Precise checking of coincidence: verify that points have equal coordinates
+ int aEnt1Pos = Search(thePoint1, myEntities);
+ int aEnt2Pos = Search(thePoint2, myEntities);
+ if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
+ aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
+ double aDist[2];
+ int aParamPos;
+ for (int i = 0; i < 2; i++) {
+ aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
+ aDist[i] = myParameters[aParamPos].val;
+ aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
+ aDist[i] -= myParameters[aParamPos].val;
+ }
+ if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
return true;
-
+ }
return false;
}
-bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
+
+std::vector<Slvs_hConstraint> SketchSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
{
- if (!theAttribute)
- return false;
+ std::vector<Slvs_hConstraint> aNewConstraints;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (!aRefAttr)
- return myAttributeMap.find(theAttribute) != myAttributeMap.end();
- if (!aRefAttr->isObject())
- return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
+ int aPos = Search(theEntity, myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ switch (myEntities[aPos].type) {
+ case SLVS_E_POINT_IN_2D:
+ case SLVS_E_POINT_IN_3D:
+ fixPoint(myEntities[aPos], aNewConstraints);
+ break;
+ case SLVS_E_LINE_SEGMENT:
+ fixLine(myEntities[aPos], aNewConstraints);
+ break;
+ case SLVS_E_CIRCLE:
+ fixCircle(myEntities[aPos], aNewConstraints);
+ break;
+ case SLVS_E_ARC_OF_CIRCLE:
+ fixArc(myEntities[aPos], aNewConstraints);
+ break;
+ default:
+ break;
+ }
+ }
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- return isInteract(aFeature);
+ return aNewConstraints;
}
-bool SketchSolver_Storage::isConsistent() const
+void SketchSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
+ std::vector<Slvs_hConstraint>& theCreated)
{
- // Check the constraints are valid
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIter = myConstraintMap.begin();
- for (; aCIter != myConstraintMap.end(); ++aCIter)
- if (!aCIter->first->data() || !aCIter->first->data()->isValid())
- return false;
- // Check the features are valid
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
- for (; aFIter != myFeatureMap.end(); aFIter++)
- if (!aFIter->first->data() || !aFIter->first->data()->isValid())
- return false;
- return true;
-}
-
-void SketchSolver_Storage::removeInvalidEntities()
-{
- // Remove invalid constraints
- std::list<ConstraintPtr> anInvalidConstraints;
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIter = myConstraintMap.begin();
- for (; aCIter != myConstraintMap.end(); ++aCIter)
- if (!aCIter->first->data() || !aCIter->first->data()->isValid())
- anInvalidConstraints.push_back(aCIter->first);
- std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
- for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
- removeConstraint(*anInvCIt);
- // Remove invalid features
- std::list<FeaturePtr> anInvalidFeatures;
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
- for (; aFIter != myFeatureMap.end(); aFIter++)
- if (!aFIter->first->data() || !aFIter->first->data()->isValid())
- anInvalidFeatures.push_back(aFIter->first);
- std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
- for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
- removeEntity(*anInvFIt);
-}
-
-EntityWrapperPtr SketchSolver_Storage::getNormal() const
-{
- EntityWrapperPtr aSketch = sketch();
- if (!aSketch)
- return aSketch;
-
- // Find normal entity
- const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
- for (; aSIt != aSketchSubs.end(); ++aSIt)
- if ((*aSIt)->type() == ENTITY_NORMAL)
- return *aSIt;
- return EntityWrapperPtr();
-}
-
-const EntityWrapperPtr& SketchSolver_Storage::sketch() const
-{
- static EntityWrapperPtr aDummySketch;
-
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (aFIt->second->type() == ENTITY_SKETCH)
- break;
- if (aFIt == myFeatureMap.end())
- return aDummySketch;
- return aFIt->second;
+ Slvs_Constraint aConstraint;
+ Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
+ bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
+ bool isForceUpdate = (isFixed && isTemporary(aConstrID));
+ if (!isForceUpdate) { // create new constraint
+ if (isFixed) return;
+ aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
+ 0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = addConstraint(aConstraint);
+ theCreated.push_back(aConstraint.h);
+ } else { // update already existent constraint
+ if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
+ return;
+ int aPos = Search(aConstrID, myConstraints);
+ if (aPos >= 0 && aPos < (int)myConstraints.size())
+ myConstraints[aPos].ptA = thePoint.h;
+ }
}
-void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
+void SketchSolver_Storage::fixLine(const Slvs_Entity& theLine,
+ std::vector<Slvs_hConstraint>& theCreated)
{
- if (sketch())
+ Slvs_Entity aPoint[2] = {
+ getEntity(theLine.point[0]),
+ getEntity(theLine.point[1])
+ };
+
+ Slvs_Constraint anEqual;
+ if (isAxisParallel(theLine.h)) {
+ // Fix one point and a line length
+ Slvs_hConstraint aFixed;
+ if (!isPointFixed(theLine.point[0], aFixed, true) &&
+ !isPointFixed(theLine.point[1], aFixed, true))
+ fixPoint(aPoint[0], theCreated);
+ if (!isUsedInEqual(theLine.h, anEqual)) {
+ // Check the distance is not set yet
+ std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
+ for (; aDistIt != myConstraints.end(); ++aDistIt)
+ if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
+ ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
+ (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
+ return;
+ // Calculate distance between points on the line
+ double aCoords[4];
+ for (int i = 0; i < 2; i++)
+ for (int j = 0; j < 2; j++) {
+ Slvs_Param aParam = getParameter(aPoint[i].param[j]);
+ aCoords[2*i+j] = aParam.val;
+ }
+
+ double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
+ (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
+ // fix line length
+ Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
+ SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
+ theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aDistance.h = addConstraint(aDistance);
+ theCreated.push_back(aDistance.h);
+ }
return;
- addEntity(FeaturePtr(), theSketch);
+ }
+ else if (isUsedInEqual(theLine.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
+ if (isEntityFixed(anOtherEntID, true)) {
+ // Fix start point of the line (if end point is not fixed yet) ...
+ Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
+ bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
+ if (isFixed == SLVS_E_UNKNOWN)
+ fixPoint(aPoint[0], theCreated);
+ // ... and create fixed point lying on this line
+ Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
+ // Firstly, search already fixed point on line
+ bool isPonLineFixed = false;
+ Slvs_hEntity aFixedPoint;
+ std::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
+ for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
+ if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
+ isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
+ aFixedPoint = aPLIter->ptA;
+ }
+
+ if (isPonLineFixed) { // update existent constraint
+ copyEntity(aPointToCopy, aFixedPoint);
+ } else { // create new constraint
+ Slvs_hEntity aCopied = copyEntity(aPointToCopy);
+ Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
+ theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
+ aPonLine.h = addConstraint(aPonLine);
+ theCreated.push_back(aPonLine.h);
+ fixPoint(getEntity(aCopied), theCreated);
+ }
+ return;
+ }
+ }
+
+ // Fix both points
+ for (int i = 0; i < 2; i++)
+ fixPoint(aPoint[i], theCreated);
}
-void SketchSolver_Storage::blockEvents(bool isBlocked) const
+void SketchSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
+ std::vector<Slvs_hConstraint>& theCreated)
{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIter = myConstraintMap.begin();
- for (; aCIter != myConstraintMap.end(); aCIter++)
- if (aCIter->first->data() && aCIter->first->data()->isValid())
- aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
+ bool isFixRadius = true;
+ // Verify the arc is under Equal constraint
+ Slvs_Constraint anEqual;
+ if (isUsedInEqual(theCircle.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
+ if (isEntityFixed(anOtherEntID, true))
+ isFixRadius = false;
+ }
+
+ fixPoint(getEntity(theCircle.point[0]), theCreated);
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
- for (; aFIter != myFeatureMap.end(); aFIter++)
- if (aFIter->first->data() && aFIter->first->data()->isValid())
- aFIter->first->data()->blockSendAttributeUpdated(isBlocked);
+ if (isFixRadius) {
+ // Search the radius is already fixed
+ std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
+ for (; aDiamIter != myConstraints.end(); ++aDiamIter)
+ if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
+ return;
- std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAtIter = myAttributeMap.begin();
- for (; anAtIter != myAttributeMap.end(); anAtIter++)
- if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
- anAtIter->first->owner()->data()->isValid())
- anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+ // Fix radius of a circle
+ const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
+ double aRadius = getParameter(aRadEnt.param[0]).val;
+ Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
+ theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
+ aFixedR.h = addConstraint(aFixedR);
+ theCreated.push_back(aFixedR.h);
+ }
}
+void SketchSolver_Storage::fixArc(const Slvs_Entity& theArc,
+ std::vector<Slvs_hConstraint>& theCreated)
+{
+ Slvs_Entity aPoint[3] = {
+ getEntity(theArc.point[0]),
+ getEntity(theArc.point[1]),
+ getEntity(theArc.point[2])
+ };
+
+ bool isFixRadius = true;
+ std::list<Slvs_Entity> aPointsToFix;
+ aPointsToFix.push_back(aPoint[1]);
+ aPointsToFix.push_back(aPoint[2]);
+
+ // Verify the arc is under Equal constraint
+ Slvs_Constraint anEqual;
+ if (isUsedInEqual(theArc.h, anEqual)) {
+ // Check another entity of Equal is already fixed
+ Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
+ if (isEntityFixed(anOtherEntID, true)) {
+ isFixRadius = false;
+ Slvs_Entity anOtherEntity = getEntity(anOtherEntID);
+ if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
+ aPointsToFix.pop_back();
+ aPointsToFix.push_back(aPoint[0]);
+ }
+ }
+ }
+
+ Slvs_hConstraint aConstrID;
+ int aNbPointsToFix = 2; // number of fixed points for the arc
+ if (isPointFixed(theArc.point[0], aConstrID, true))
+ aNbPointsToFix--;
+ double anArcPoints[3][2];
+ for (int i = 0; i < 3; i++) {
+ const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]);
+ for (int j = 0; j < 2; j++)
+ anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val;
+ }
+
+ // Radius of the arc
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1]));
+ std::shared_ptr<GeomAPI_Pnt2d> aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1]));
+ double aRadius = aCenter->distance(aStart);
+
+ // Update end point of the arc to be on a curve
+ std::shared_ptr<GeomAPI_Pnt2d> anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1]));
+ double aDistance = anEnd->distance(aCenter);
+ std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
+ if (aDistance < tolerance)
+ aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
+ else
+ aDir = aDir->multiplied(aRadius / aDistance);
+ double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
+ const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = getParameter(aEndPoint.param[i]);
+ aParam.val = xy[i];
+ updateParameter(aParam);
+ }
+ std::list<Slvs_Entity>::iterator aPtIt = aPointsToFix.begin();
+ for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
+ fixPoint(*aPtIt, theCreated);
+
+ if (isFixRadius) {
+ // Fix radius of the arc
+ bool isExists = false;
+ std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
+ for (; anIt != myConstraints.end() && !isExists; ++anIt)
+ if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h)
+ isExists = true;
+ if (!isExists) {
+ Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER,
+ theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN);
+ aFixedR.h = addConstraint(aFixedR);
+ theCreated.push_back(aFixedR.h);
+ }
+ }
+}
+bool SketchSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const
+{
+ std::vector<Slvs_Constraint>::const_iterator anIter = myConstraints.begin();
+ for (; anIter != myConstraints.end(); anIter++)
+ if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) &&
+ anIter->entityA == theEntity)
+ return true;
+ return false;
+}
-// ============== Auxiliary functions ====================================
-bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
- const std::list<ConstraintWrapperPtr>& theCVec2)
+bool SketchSolver_Storage::isUsedInEqual(
+ const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const
{
- if (theCVec1.size() != theCVec2.size())
+ // Check the entity is used in Equal constraint
+ std::vector<Slvs_Constraint>::const_iterator anEqIter = myConstraints.begin();
+ for (; anEqIter != myConstraints.end(); anEqIter++)
+ if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES ||
+ anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN ||
+ anEqIter->type == SLVS_C_EQUAL_RADIUS) &&
+ (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) {
+ theEqual = *anEqIter;
+ return true;
+ }
+ return false;
+}
+
+bool SketchSolver_Storage::isNeedToResolve()
+{
+ if (myConstraints.empty())
return false;
- std::list<bool> aChecked(theCVec2.size(), false);
- std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
- for (; anIt1 != theCVec1.end(); ++anIt1) {
- std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
- std::list<bool>::iterator aCheckIt = aChecked.begin();
- while (aCheckIt != aChecked.end() && *aCheckIt) {
- ++aCheckIt;
- ++anIt2;
- }
- for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
- if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
- *aCheckIt = true;
- break;
- }
- // the same constraint is not found
- if (anIt2 == theCVec2.end())
- return false;
+ if (!myNeedToResolve) {
+ // Verify the updated parameters are used in constraints
+ std::set<Slvs_hEntity> aPoints;
+ std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
+ for (; anEntIt != myEntities.end(); ++anEntIt) {
+ for (int i = 0; i < 4 && anEntIt->param[i] != SLVS_E_UNKNOWN; ++i)
+ if (myUpdatedParameters.find(anEntIt->param[i]) != myUpdatedParameters.end()) {
+ aPoints.insert(anEntIt->h);
+ break;
+ }
+ }
+ std::set<Slvs_hEntity> anEntities = aPoints;
+ for (anEntIt = myEntities.begin(); anEntIt != myEntities.end(); ++anEntIt) {
+ for (int i = 0; i < 4 && anEntIt->point[i] != SLVS_E_UNKNOWN; ++i)
+ if (aPoints.find(anEntIt->point[i]) != aPoints.end()) {
+ anEntities.insert(anEntIt->h);
+ break;
+ }
+ }
+
+ std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end() && !myNeedToResolve; ++aCIt) {
+ Slvs_hEntity anAttrs[6] =
+ {aCIt->ptA, aCIt->ptB, aCIt->entityA, aCIt->entityB, aCIt->entityC, aCIt->entityD};
+ for (int i = 0; i < 6; i++)
+ if (anAttrs[i] != SLVS_E_UNKNOWN && anEntities.find(anAttrs[i]) != anEntities.end()) {
+ myNeedToResolve = true;
+ break;
+ }
+ }
}
- return true;
+
+ myUpdatedParameters.clear();
+ return myNeedToResolve;
+}
+
+
+
+
+
+
+// ========================================================
+// ========= Auxiliary functions ===============
+// ========================================================
+
+template<typename T>
+int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
+{
+ int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
+ int aVecSize = theEntities.size();
+ if (theEntities.empty())
+ return 1;
+ while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
+ aResIndex--;
+ while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
+ aResIndex++;
+ if (aResIndex == -1 || (aResIndex < aVecSize && theEntities[aResIndex].h != theEntityID))
+ aResIndex = aVecSize;
+ return aResIndex;
+}
+
+bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
+{
+ return fabs(theParam1.val - theParam2.val) > tolerance;
+}
+
+bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
+{
+ int i = 0;
+ for (; theEntity1.param[i] != 0 && i < 4; i++)
+ if (theEntity1.param[i] != theEntity2.param[i])
+ return true;
+ i = 0;
+ for (; theEntity1.point[i] != 0 && i < 4; i++)
+ if (theEntity1.point[i] != theEntity2.point[i])
+ return true;
+ return false;
+}
+
+bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
+{
+ return theConstraint1.ptA != theConstraint2.ptA ||
+ theConstraint1.ptB != theConstraint2.ptB ||
+ theConstraint1.entityA != theConstraint2.entityA ||
+ theConstraint1.entityB != theConstraint2.entityB ||
+ theConstraint1.entityC != theConstraint2.entityC ||
+ theConstraint1.entityD != theConstraint2.entityD ||
+ fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;
}
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
// File: SketchSolver_Storage.h
-// Created: 30 Nov 2015
+// Created: 18 Mar 2015
// Author: Artem ZHIDKOV
#ifndef SketchSolver_Storage_H_
#define SketchSolver_Storage_H_
-#include <SketchSolver.h>
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SketchSolver_IEntityWrapper.h>
-#include <SketchSolver_IParameterWrapper.h>
-#include <SketchSolver_ISolver.h>
+#include "SketchSolver.h"
+#include <SketchSolver_Solver.h>
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_Feature.h>
-#include <SketchPlugin_Constraint.h>
+#include <list>
+#include <memory>
+#include <set>
+#include <vector>
/** \class SketchSolver_Storage
* \ingroup Plugins
- * \brief Interface to map SketchPlugin features to the entities of corresponding solver.
+ * \brief Contains all necessary data in SolveSpace format to solve a single group of constraints
*/
class SketchSolver_Storage
{
-private:
+public:
SketchSolver_Storage();
- SketchSolver_Storage(const SketchSolver_Storage&);
- SketchSolver_Storage& operator=(const SketchSolver_Storage&);
-public:
- SketchSolver_Storage(const GroupID& theGroup)
- : myGroupID(theGroup),
- myNeedToResolve(false)
- {}
-
- /// \brief Change mapping between constraint from SketchPlugin and
- /// a constraint applicable for corresponding solver.
- /// \param theConstraint [in] original SketchPlugin constraint
- /// \param theSolverConstraint [in] solver's constraints
- SKETCHSOLVER_EXPORT void addConstraint(ConstraintPtr theConstraint,
- ConstraintWrapperPtr theSolverConstraints);
- /// \brief Change mapping between constraint from SketchPlugin and
- /// the list of constraints applicable for corresponding solver.
- /// \param theConstraint [in] original SketchPlugin constraint
- /// \param theSolverConstraints [in] list of solver's constraints
- SKETCHSOLVER_EXPORT
- void addConstraint(ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints);
-
- /// \brief Convert feature to the form applicable for specific solver and map it
- /// \param theFeature [in] feature to convert
- /// \param theGroup [in] id of the group where the feature should be placed
- /// \return \c true if the feature has been created or updated
- SKETCHSOLVER_EXPORT bool update(FeaturePtr theFeature, const GroupID& theGroup = GID_UNKNOWN);
- /// \brief Convert attribute to the form applicable for specific solver and map it
- /// \param theFeature [in] feature to convert
- /// \return \c true if the attribute has been created or updated
- SKETCHSOLVER_EXPORT bool update(AttributePtr theAttribute, const GroupID& theGroup = GID_UNKNOWN);
-
- /// \brief Returns constraint related to corresponding constraint
- SKETCHSOLVER_EXPORT
- const std::list<ConstraintWrapperPtr>& constraint(const ConstraintPtr& theConstraint) const;
-
- /// \brief Returns entity related to corresponding feature
- SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
- /// \brief Returns entity related to corresponding attribute
- SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const;
-
-//// /// \brief Returns parameter related to corresponding scalar attribute
-//// SKETCHSOLVER_EXPORT
-//// const ParameterWrapperPtr& parameter(const AttributeDoublePtr& theAttribute) const;
-
- /// \brief Return parsed sketch entity
- const EntityWrapperPtr& sketch() const;
- /// \brief Set parsed sketch entity.
- /// Be careful, this method does not update fields of the storage specific for the solver.
- /// Does not update if the sketch already exists.
- void setSketch(const EntityWrapperPtr& theSketch);
-
- /// \brief Mark two points as coincident
- virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave) = 0;
-
- /// \brief Shows the storage has any constraint twice
- virtual bool hasDuplicatedConstraint() const = 0;
-
- /// \brief Removes constraint from the storage
- /// \return \c true if the constraint and all its parameters are removed successfully
- virtual bool removeConstraint(ConstraintPtr theConstraint) = 0;
- /// \brief Removes feature from the storage
- /// \return \c true if the feature and its attributes are removed successfully;
- /// \c false if the feature or any it attribute is used by remaining constraints.
- virtual bool removeEntity(FeaturePtr theFeature) = 0;
- /// \brief Removes attribute from the storage
- /// \return \c true if the attribute is not used by remaining features and constraints
- virtual bool removeEntity(AttributePtr theAttribute) = 0;
-
- /// \brief Remove all features became invalid
- SKETCHSOLVER_EXPORT void removeInvalidEntities();
-
- /// \brief Mark specified constraint as temporary
- virtual void setTemporary(ConstraintPtr theConstraint) = 0;
- /// \brief Returns number of temporary constraints
- virtual size_t nbTemporary() const = 0;
- /// \brief Remove temporary constraints
- /// \param theNbConstraints [in] number of temporary constraints to be deleted
- /// \return number of remaining temporary constraints
- virtual size_t removeTemporary(size_t theNbConstraints = 1) = 0;
-
- /// \brief Check whether the feature or its attributes are used by this storage
- /// \param theFeature [in] feature to be checked
- /// \return \c true if the feature interacts with the storage
- bool isInteract(const FeaturePtr& theFeature) const;
- /// \brief Check whether the attribute is used by this storage
- /// \param theAttribute [in] attribute to be checked
- /// \return \c true if the attribute interacts with the storage
- bool isInteract(const AttributePtr& theAttribute) const;
-
- /// \brief Check the features is not removed
- bool isConsistent() const;
+ /** \brief Add new parameter to the current group
+ * \param[in] theParam SolveSpace parameter
+ * \return the ID of added parameter
+ */
+ Slvs_hParam addParameter(const Slvs_Param& theParam);
+ /** \brief Updates parameter in the current group. If the ID of parameter is zero, the new item will be added
+ * \param[in] theParam SolveSpace parameter
+ * \return the ID of updated/added parameter
+ */
+ Slvs_hParam updateParameter(const Slvs_Param& theParam);
+ /** \brief Removes the parameter by its ID
+ * \param[in] theParamID index of parameter to be removed
+ * \return \c true if the parameter was successfully removed
+ */
+ bool removeParameter(const Slvs_hParam& theParamID);
+ /// \brief Returns the parameter by its ID
+ const Slvs_Param& getParameter(const Slvs_hParam& theParamID) const;
+
+ /** \brief Add new entity to the current group
+ * \param[in] theEntity SolveSpace entity
+ * \return the ID of added entity
+ */
+ Slvs_hEntity addEntity(const Slvs_Entity& theEntity);
+ /** \brief Updates entity in the current group. If the ID of entity is zero, the new item will be added
+ * \param[in] theEntity SolveSpace entity
+ * \return the ID of updated/added entity
+ */
+ Slvs_hEntity updateEntity(const Slvs_Entity& theEntity);
+ /** \brief Removes the entity by its ID. All parameters used in this entity,
+ * and not used in other constraints, will be removed too.
+ * \param[in] theEntityID index of entity to be removed
+ * \return \c true if the entity was successfully removed
+ */
+ bool removeEntity(const Slvs_hEntity& theEntityID);
+ /** \brief Remove all entities, which are not used in constraints
+ */
+ void removeUnusedEntities();
+ /// \brief Returns the entity by its ID
+ const Slvs_Entity& getEntity(const Slvs_hEntity& theEntityID) const;
+ /// \brief Makes a full copy of the given entity
+ Slvs_hEntity copyEntity(const Slvs_hEntity& theCopied);
+ /// \brief Copy one entity to another
+ void copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo);
+ /// \brief Check the entity is used in constraints
+ bool isUsedByConstraints(const Slvs_hEntity& theEntityID) const;
+ /// \brief Returns maximal ID of entities in this storage
+ const Slvs_hEntity& entityMaxID() const
+ { return myEntityMaxID; }
+
+ /// \brief Verifies the current point or another coincident one is fixed
+ /// \param[in] thePointID entity to be checked fixed
+ /// \param[out] theFixed ID of constraint
+ /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
+ /// if \c false, only the point is verified
+ /// \return \c true if the point is fixed
+ bool isPointFixed(const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate = false) const;
+ /// \brief Verifies the current entity is fully fixed (may not be changed by constraints)
+ /// \param[in] theEntityID entity to be checked fixed
+ /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
+ /// if \c false, only points are verified
+ /// \return \c true if the entity is fixed
+ bool isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate = false) const;
+
+ /** \brief Add new constraint to the current group
+ * \param[in] theConstraint SolveSpace's constraint
+ * \return the ID of added constraint
+ */
+ Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
+ /** \brief Updates constraint in the current group.
+ * If the ID of constraint is zero, the new item will be added
+ * \param[in] theConstraint SolveSpace constraint
+ * \return the ID of updated/added constraint
+ */
+ Slvs_hConstraint updateConstraint(const Slvs_Constraint& theConstraint);
+ /** \brief Removes the constraint by its ID. All entities and parameters depending on this
+ * constraint, which are not used in other constraints, will be removed too.
+ * \param[in] theConstraintID index of constraint to be removed
+ * \return \c true if the constraint was successfully removed
+ */
+ bool removeConstraint(const Slvs_hConstraint& theConstraintID);
+ /// \brief Returns the constraint by its ID
+ const Slvs_Constraint& getConstraint(const Slvs_hConstraint& theConstraintID) const;
+ /// \brief Returns list of constraints of specified type
+ std::list<Slvs_Constraint> getConstraintsByType(int theConstraintType) const;
+ /// \brief Returns quantity of constraints in this storage
+ size_t nbConstraints() const
+ { return myConstraints.size(); }
+
+ /// \brief Attach constraint SLVS_C_WHERE_DRAGGED to this storage. It need to make precise calculations
+ void addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID);
+
+ /// \brief Add transient constraint
+ void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID);
+ /// \brief Remove all transient constraints
+ void removeTemporaryConstraints();
+ /// \brief Remove one temporary constraint. Preferable to remove the points under Point-on-Line constraint
+ /// \return Number of remaining temporary constraints
+ int deleteTemporaryConstraint();
+ /// \brief Checks the constraint is temporary
+ bool isTemporary(const Slvs_hConstraint& theConstraintID) const;
+ /// \brief Number of temporary constraints
+ int numberTemporary() const
+ { return (int)myTemporaryConstraints.size(); }
/// \brief Shows the sketch should be resolved
- virtual bool isNeedToResolve()
- { return myNeedToResolve; }
+ bool isNeedToResolve();
+
+ /// \brief Shows the storage has the same constraint twice
+ bool hasDuplicatedConstraint() const
+ { return myDuplicatedConstraint; }
+
/// \brief Changes the flag of group to be resolved
void setNeedToResolve(bool theFlag)
{ myNeedToResolve = theFlag; }
- /// \brief Initialize solver by constraints, entities and parameters
- virtual void initializeSolver(SolverPtr theSolver) = 0;
-
- /// \brief Update SketchPlugin features after resolving constraints
- /// \param theFixedOnly [in] if \c true the fixed points will be updated only
- virtual void refresh(bool theFixedOnly = false) const = 0;
-
- /// \brief Check if some parameters or entities are returned
- /// to the current group after removing temporary constraints
- virtual void verifyFixed() = 0;
-
- /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
- /// shows the distance from the start point.
- virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase,
- double theCoeff) = 0;
-
-protected:
- /// \brief Change mapping feature from SketchPlugin and
- /// the entity applicable for corresponding solver.
- /// \param theFeature [in] original SketchPlugin feature
- /// \param theSolverEntity [in] solver's entity, created outside
- SKETCHSOLVER_EXPORT
- void addEntity(FeaturePtr theFeature,
- EntityWrapperPtr theSolverEntity);
-
- /// \brief Change mapping attribute of a feature and the entity applicable for corresponding solver.
- /// \param theAttribute [in] original attribute
- /// \param theSolverEntity [in] solver's entity, created outside
- SKETCHSOLVER_EXPORT
- void addEntity(AttributePtr theAttribute,
- EntityWrapperPtr theSolverEntity);
-
-//// /// \brief Change mapping scalar attribute and the parameter applicable for corresponding solver.
-//// /// \param theValue [in] original attribute
-//// /// \param theSolverParam [in] solver's parameter, created outside
-//// SKETCHSOLVER_EXPORT
-//// void addParameter(AttributeDoublePtr theValue,
-//// ParameterWrapperPtr theSolverParam);
-
- /// \brief Update constraint's data
- /// \return \c true if any value is updated
- virtual bool update(ConstraintWrapperPtr& theConstraint) = 0;
- /// \brief Update entity's data
- /// \return \c true if any value is updated
- virtual bool update(EntityWrapperPtr& theEntity) = 0;
- /// \brief Update parameter's data
- /// \return \c true if the value of parameter is updated
- virtual bool update(ParameterWrapperPtr& theParameter) = 0;
-
- /// \brief Remove constraint
- /// \return \c true if the constraint and all its parameters are removed successfully
- virtual bool remove(ConstraintWrapperPtr theConstraint) = 0;
- /// \brief Remove entity
- /// \return \c true if the entity and all its parameters are removed successfully
- virtual bool remove(EntityWrapperPtr theEntity) = 0;
- /// \brief Remove parameter
- /// \return \c true if the parameter has been removed
- virtual bool remove(ParameterWrapperPtr theParameter) = 0;
-
- /// \brief Update the group for the given entity, its sub-entities and parameters
- virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup) = 0;
- /// \brief Update the group for the given parameter
- virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup) = 0;
-
- /// \brief Block or unblock events when refreshing features
- SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked) const;
+ /// \brief Returns lists of removed elements
+ void getRemoved(std::set<Slvs_hParam>& theParameters,
+ std::set<Slvs_hEntity>& theEntities,
+ std::set<Slvs_hConstraint>& theConstraints);
+
+ /// \brief Initialize constraint solver by the entities collected by current storage
+ void initializeSolver(SketchSolver_Solver& theSolver);
+
+private:
+ /// \brief Store coincident points
+ void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
+ /// \brief Remove point from lists of coincidence
+ void removeCoincidentPoint(const Slvs_hEntity& thePoint);
+ /// \brief Remove point-point coincidence
+ void removeCoincidence(const Slvs_Constraint& theCoincidence);
+
+public:
+ /// \brief Check two points are coincident
+ bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
+
+ /// \brief Check two points are coincident or have same coordinates
+ bool isEqual(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
+
+ /// \brief Check the entity is horizontal of vertical
+ bool isAxisParallel(const Slvs_hEntity& theEntity) const;
+
+ /// \brief Verifies the entity is used in any equal constraint
+ /// \param[in] theEntity entity to be found
+ /// \param[out] theEqual constraint, which uses the entity
+ /// \return \c true, if the Equal constrait is found
+ bool isUsedInEqual(const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const;
+
+ /// \brief Fixes specified entity
+ /// \param theEntity ID of the entity to be fixed
+ /// \return List of created constraints
+ std::vector<Slvs_hConstraint> fixEntity(const Slvs_hEntity& theEntity);
private:
- /// \brief Find the normal of the sketch
- EntityWrapperPtr getNormal() const;
+ /// \brief Fixes specified point
+ /// \param [in] thePoint point to be fixed
+ /// \param [out] theCreated list of the Fixed constraints created
+ void fixPoint(const Slvs_Entity& thePoint, std::vector<Slvs_hConstraint>& theCreated);
+ /// \brief Fixes specified line
+ /// \param [in] theLine line to be fixed
+ /// \param [out] theCreated list of the Fixed constraints created
+ void fixLine(const Slvs_Entity& theLine, std::vector<Slvs_hConstraint>& theCreated);
+ /// \brief Fixes specified circle
+ /// \param [in] theCircle circle to be fixed
+ /// \param [out] theCreated list of the Fixed constraints created
+ void fixCircle(const Slvs_Entity& theCircle, std::vector<Slvs_hConstraint>& theCreated);
+ /// \brief Fixes specified arc
+ /// \param [in] theArc arc to be fixed
+ /// \param [out] theCreated list of the Fixed constraints created
+ void fixArc(const Slvs_Entity& theArc, std::vector<Slvs_hConstraint>& theCreated);
-protected:
- GroupID myGroupID; ///< identifier of the group, this storage belongs to
+private:
+ Slvs_hParam myParamMaxID; ///< current parameter index (may differs with the number of parameters)
+ std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints (sorted by the identifier)
+ Slvs_hEntity myEntityMaxID; ///< current entity index (may differs with the number of entities)
+ std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints (sorted by the identifier)
+ Slvs_hConstraint myConstrMaxID; ///< current constraint index (may differs with the number of constraints)
+ std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group (sorted by the identifier)
- /// map SketchPlugin constraint to a list of solver's constraints
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> > myConstraintMap;
- /// map SketchPlugin feature to solver's entity
- std::map<FeaturePtr, EntityWrapperPtr> myFeatureMap;
- /// map attribute to solver's entity
- std::map<AttributePtr, EntityWrapperPtr> myAttributeMap;
-//// /// map scalar attribute to solver's parameter
-//// std::map<AttributeDoublePtr, ParameterWrapperPtr> myParametersMap;
+ std::vector< std::set<Slvs_hEntity> > myCoincidentPoints; ///< lists of coincident points
+ Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved
+ bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
+
+ std::set<Slvs_hConstraint> myTemporaryConstraints; ///< list of transient constraints
+ std::set<Slvs_hParam> myRemovedParameters; ///< list of just removed parameters (cleared when returning to applicant)
+ std::set<Slvs_hEntity> myRemovedEntities; ///< list of just removed entities (cleared when returning to applicant)
+ std::set<Slvs_hConstraint> myRemovedConstraints; ///< list of just removed constraints (cleared when returning to applicant)
+ std::set<Slvs_hParam> myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called)
};
typedef std::shared_ptr<SketchSolver_Storage> StoragePtr;
+++ /dev/null
-## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-FIND_PACKAGE(SolveSpace REQUIRED)
-
-SET(PROJECT_HEADERS
- SolveSpaceSolver_Solver.h
- SolveSpaceSolver_Builder.h
- SolveSpaceSolver_Storage.h
- SolveSpaceSolver_EntityWrapper.h
- SolveSpaceSolver_ParameterWrapper.h
- SolveSpaceSolver_ConstraintWrapper.h
- SolveSpaceSolver_ConstraintType.h
-)
-
-SET(PROJECT_SOURCES
- SolveSpaceSolver_Solver.cpp
- SolveSpaceSolver_Builder.cpp
- SolveSpaceSolver_Storage.cpp
- SolveSpaceSolver_EntityWrapper.cpp
- SolveSpaceSolver_ParameterWrapper.cpp
- SolveSpaceSolver_ConstraintWrapper.cpp
-)
-
-SET(PROJECT_LIBRARIES
- ${SOLVESPACE_LIBRARIES}
- SketchSolver
- ModelAPI
- GeomAPI
-)
-
-INCLUDE_DIRECTORIES(
- ${SOLVESPACE_INCLUDE_DIRS}
- ${PROJECT_SOURCE_DIR}/src/SketchSolver
- ${PROJECT_SOURCE_DIR}/src/SketchPlugin
- ${PROJECT_SOURCE_DIR}/src/ModelAPI
- ${PROJECT_SOURCE_DIR}/src/GeomAPI
- ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
-)
-
-ADD_LIBRARY(SolveSpaceSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
-TARGET_LINK_LIBRARIES(SolveSpaceSolver ${PROJECT_LIBRARIES})
-INSTALL(TARGETS SolveSpaceSolver DESTINATION plugins)
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Builder.cpp
-// Created: 25 Mar 2015
-// Author: Artem ZHIDKOV
-
-#include <SolveSpaceSolver_Builder.h>
-#include <SolveSpaceSolver_Solver.h>
-#include <SolveSpaceSolver_Storage.h>
-#include <SolveSpaceSolver_ParameterWrapper.h>
-#include <SolveSpaceSolver_EntityWrapper.h>
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_ConstraintType.h>
-
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Dir.h>
-#include <GeomDataAPI_Point.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeRefAttr.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-
-#include <math.h>
-
-
-static EntityWrapperPtr createLine(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID);
-static EntityWrapperPtr createCircle(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID);
-static EntityWrapperPtr createArc(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID);
-
-/// \brief Set flags of constraint to identify which points are coincident in the Tangency
-/// (for more information, see SolveSpace documentation)
-static void adjustTangency(ConstraintWrapperPtr theConstraint);
-/// \brief Set flags for angle constraint
-static void adjustAngle(ConstraintWrapperPtr theConstraint);
-/// \brief Update mirror points
-static void adjustMirror(ConstraintWrapperPtr theConstraint);
-/// \brief Update positions of rotated features
-static void adjustMultiRotation(ConstraintWrapperPtr theConstraint);
-/// \brief Update positions of translated features
-static void adjustMultiTranslation(ConstraintWrapperPtr theConstraint);
-
-/// \brief Transform points to be symmetric regarding to the mirror line
-static void makeMirrorPoints(EntityWrapperPtr theOriginal,
- EntityWrapperPtr theMirrored,
- EntityWrapperPtr theMirrorLine);
-
-
-
-// Initialization of constraint builder self pointer
-BuilderPtr SolveSpaceSolver_Builder::mySelf = SolveSpaceSolver_Builder::getInstance();
-
-BuilderPtr SolveSpaceSolver_Builder::getInstance()
-{
- if (!mySelf) {
- mySelf = BuilderPtr(new SolveSpaceSolver_Builder);
- SketchSolver_Manager::instance()->setBuilder(mySelf);
- }
- return mySelf;
-}
-
-StoragePtr SolveSpaceSolver_Builder::createStorage(const GroupID& theGroup) const
-{
- return StoragePtr(new SolveSpaceSolver_Storage(theGroup));
-}
-
-SolverPtr SolveSpaceSolver_Builder::createSolver() const
-{
- return SolverPtr(new SolveSpaceSolver_Solver);
-}
-
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createConstraint(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& thePoint1,
- const EntityWrapperPtr& thePoint2,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2) const
-{
- if (theType == CONSTRAINT_SYMMETRIC)
- return createMirror(theConstraint, theGroupID, theSketchID,
- thePoint1, thePoint2, theEntity1);
-
- int aType = ConstraintType::toSolveSpace(theType);
- if (aType == SLVS_C_UNKNOWN)
- return std::list<ConstraintWrapperPtr>();
-
- Slvs_hEntity aSlvsEntities[4] = {SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN};
- EntityWrapperPtr anOriginal[4] = {thePoint1, thePoint2, theEntity1, theEntity2};
- std::list<EntityWrapperPtr> aConstrAttrList; // to be filled
- for (int i = 0; i < 4; ++i) {
- if (!anOriginal[i])
- continue;
- aSlvsEntities[i] = (Slvs_hEntity)anOriginal[i]->id();
- if (aSlvsEntities[i] == SLVS_E_UNKNOWN)
- return std::list<ConstraintWrapperPtr>(); // entity is not added into a storage, constraint can not be created
- aConstrAttrList.push_back(anOriginal[i]);
- }
-
- Slvs_Constraint aConstraint = Slvs_MakeConstraint(
- SLVS_C_UNKNOWN, (Slvs_hGroup)theGroupID, aType, (Slvs_hEntity)theSketchID,
- theValue, aSlvsEntities[0], aSlvsEntities[1], aSlvsEntities[2], aSlvsEntities[3]);
- ConstraintWrapperPtr aResult(new SolveSpaceSolver_ConstraintWrapper(theConstraint, aConstraint));
- aResult->setValue(theValue);
- aResult->setEntities(aConstrAttrList);
- adjustConstraint(aResult);
-
- return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createConstraint(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& thePoint1,
- const EntityWrapperPtr& thePoint2,
- const std::list<EntityWrapperPtr>& theTrsfEnt) const
-{
- if (theType != CONSTRAINT_MULTI_ROTATION && theType != CONSTRAINT_MULTI_TRANSLATION)
- return std::list<ConstraintWrapperPtr>();
-
- int aType = ConstraintType::toSolveSpace(theType);
- if (aType == SLVS_C_UNKNOWN)
- return std::list<ConstraintWrapperPtr>();
-
- Slvs_Constraint aConstraint =
- Slvs_MakeConstraint(SLVS_C_UNKNOWN, (Slvs_hGroup)theGroupID, aType, (Slvs_hEntity)theSketchID,
- theValue, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-
- std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
- if (thePoint2)
- aConstrAttrList.push_front(thePoint2);
- aConstrAttrList.push_front(thePoint1);
-
- ConstraintWrapperPtr aResult(new SolveSpaceSolver_ConstraintWrapper(theConstraint, aConstraint));
- aResult->setValue(theValue);
- aResult->setEntities(aConstrAttrList);
- return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-
-std::list<ConstraintWrapperPtr> SolveSpaceSolver_Builder::createMirror(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2,
- const EntityWrapperPtr& theMirrorLine) const
-{
-//// std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity1 =
-//// std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity1);
-//// std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity2 =
-//// std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity2);
-////
-//// // Make aMirrorEnt parameters to be symmetric with aBaseEnt
-//// makeMirrorEntity(theEntity1, theEntity2, theMirrorLine);
-
- Slvs_Constraint aConstraint;
- std::list<ConstraintWrapperPtr> aResult;
- std::list<EntityWrapperPtr> aConstrAttrList;
- if (theEntity1->type() == ENTITY_POINT) {
- if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
- makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
-
- aConstraint = Slvs_MakeConstraint(
- SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID, SLVS_C_SYMMETRIC_LINE, (Slvs_hEntity)theSketchID,
- 0.0, (Slvs_hEntity)theEntity1->id(), (Slvs_hEntity)theEntity2->id(),
- (Slvs_hEntity)theMirrorLine->id(), SLVS_E_UNKNOWN);
-
- aConstrAttrList.push_back(theEntity1);
- aConstrAttrList.push_back(theEntity2);
- aConstrAttrList.push_back(theMirrorLine);
-
- ConstraintWrapperPtr aWrapper(new SolveSpaceSolver_ConstraintWrapper(
- theConstraint, aConstraint));
- aWrapper->setEntities(aConstrAttrList);
- aResult.push_back(aWrapper);
- }
- else if (theEntity1->type() == ENTITY_LINE) {
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
- for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
- std::list<ConstraintWrapperPtr> aMrrList =
- createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- }
- }
- else if (theEntity1->type() == ENTITY_CIRCLE) {
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
- for (; anIt1 != aPoints1.end(); ++anIt1)
- if ((*anIt1)->type() == ENTITY_POINT)
- break;
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
- for (; anIt2 != aPoints2.end(); ++anIt2)
- if ((*anIt2)->type() == ENTITY_POINT)
- break;
-
- std::list<ConstraintWrapperPtr> aMrrList =
- createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
- // Additional constraint for equal radii
- aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
- 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- }
- else if (theEntity1->type() == ENTITY_ARC) {
- // Do not allow mirrored arc recalculate its position until coordinated of all points recalculated
- FeaturePtr aMirrArc = theEntity2->baseFeature();
- aMirrArc->data()->blockSendAttributeUpdated(true);
-
- std::list<ConstraintWrapperPtr> aMrrList;
- std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
- if ((*anIt2)->group() == theGroupID) // mirrored point is not fixed
- makeMirrorPoints(theEntity1->subEntities().front(),
- theEntity2->subEntities().front(), theMirrorLine);
-
- // Workaround to avoid problems in SolveSpace.
- // The symmetry of two arcs will be done using symmetry of three points on these arcs:
- // start point, end point, and any other point on the arc
- std::list<EntityWrapperPtr> aBaseArcPoints(++anIt1, theEntity1->subEntities().end());
- std::list<EntityWrapperPtr> aMirrorArcPoints(++anIt2, theEntity2->subEntities().end());
- // indices of points of arc, center corresponds center, first point corresponds last point
- aMirrorArcPoints.reverse();
-
-//// EntityWrapperPtr aBothArcs[2] = {theEntity1, theEntity2};
-//// EntityWrapperPtr aBothMiddlePoints[2];
-//// for (int i = 0; i < 2; i++) {
-//// aBothMiddlePoints[i] = calculateMiddlePoint(aBothArcs[i], 0.5, theGroupID, theSketchID);
-//// // additional constraint point-on-curve
-//// aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_PT_ON_CIRCLE,
-//// 0.0, aBothMiddlePoints[i], EntityWrapperPtr(), aBothArcs[i]);
-//// aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-//////// if (i == 0) {
-//////// // additional constraint for the point to be in the middle of a base arc
-//////// Slvs_Entity aLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-//////// myGroup->getWorkplaneId(), aBothArcs[i].point[1], aBothMiddlePoints[i]);
-//////// aLine1.h = myStorage->addEntity(aLine1);
-//////// Slvs_Entity aLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
-//////// myGroup->getWorkplaneId(), aBothArcs[i].point[2], aBothMiddlePoints[i]);
-//////// aLine2.h = myStorage->addEntity(aLine2);
-//////// Slvs_Constraint aMiddleConstr = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
-//////// SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(),
-//////// 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aLine1.h, aLine2.h);
-//////// aMiddleConstr.h = myStorage->addConstraint(aMiddleConstr);
-//////// mySlvsConstraints.push_back(aMiddleConstr.h);
-//////// }
-//// }
-////
-//// aBaseArcPoints.push_back(aBothMiddlePoints[0]);
-//// aMirrorArcPoints.push_back(aBothMiddlePoints[1]);
- anIt1 = aBaseArcPoints.begin();
- anIt2 = aMirrorArcPoints.begin();
- for (; anIt1 != aBaseArcPoints.end(); ++anIt1, ++anIt2) {
- aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- }
- // Restore event sending
- aMirrArc->data()->blockSendAttributeUpdated(false);
- }
- return aResult;
-}
-
-void SolveSpaceSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
-{
- SketchSolver_ConstraintType aType = theConstraint->type();
- // Update flags in constraints
- if (aType == CONSTRAINT_TANGENT_ARC_ARC || aType == CONSTRAINT_TANGENT_ARC_LINE)
- adjustTangency(theConstraint);
- else if (aType == CONSTRAINT_ANGLE)
- adjustAngle(theConstraint);
- else if (aType == CONSTRAINT_SYMMETRIC)
- adjustMirror(theConstraint);
- else if (aType == CONSTRAINT_MULTI_ROTATION)
- adjustMultiRotation(theConstraint);
- else if (aType == CONSTRAINT_MULTI_TRANSLATION)
- adjustMultiTranslation(theConstraint);
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createFeature(
- FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID) const
-{
- static EntityWrapperPtr aDummy;
- if (!theFeature->data()->isValid())
- return aDummy;
-
- // Sketch
- CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
- if (aSketch)
- return createSketchEntity(aSketch, theGroupID);
-
- // SketchPlugin features
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
- if (!aFeature)
- return aDummy;
-
- // Verify the feature by its kind
- const std::string& aFeatureKind = aFeature->getKind();
- // Line
- if (aFeatureKind == SketchPlugin_Line::ID())
- return createLine(theFeature, theAttributes, theGroupID, theSketchID);
- // Circle
- else if (aFeatureKind == SketchPlugin_Circle::ID())
- return createCircle(theFeature, theAttributes,theGroupID, theSketchID);
- // Arc
- else if (aFeatureKind == SketchPlugin_Arc::ID())
- return createArc(theFeature, theAttributes,theGroupID, theSketchID);
- // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
- else if (aFeatureKind == SketchPlugin_Point::ID()) {
- AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
- if (!aPoint->isInitialized())
- return aDummy;
- EntityWrapperPtr aSub = createAttribute(aPoint, theGroupID, theSketchID);
- if (!aSub)
- return aDummy;
-
- const Slvs_Entity& aSubEnt =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(aSub)->entity();
- EntityWrapperPtr aNewEntity(new SolveSpaceSolver_EntityWrapper(theFeature, aSubEnt));
- aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
- return aNewEntity;
- }
-
- // wrong entity
- return aDummy;
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createAttribute(
- AttributePtr theAttribute,
- const GroupID& theGroupID,
- const EntityID& theSketchID) const
-{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- // do not create features here
- return EntityWrapperPtr();
- } else
- anAttribute = aRefAttr->attr();
- }
-
- std::list<ParameterWrapperPtr> aParameters;
- Slvs_Entity anEntity;
- anEntity.type = 0;
-
- // Point in 3D
- std::shared_ptr<GeomDataAPI_Point> aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point>(theAttribute);
- if (aPoint) {
- aParameters.push_back(createParameter(theGroupID, aPoint->x(), !aPoint->textX().empty()));
- aParameters.push_back(createParameter(theGroupID, aPoint->y(), !aPoint->textY().empty()));
- aParameters.push_back(createParameter(theGroupID, aPoint->z(), !aPoint->textZ().empty()));
- // Create entity (parameters are not filled)
- anEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- } else {
- // Point in 2D
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
- if (aPoint2D) {
- aParameters.push_back(createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
- aParameters.push_back(createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
- // Create entity (parameters are not filled)
- anEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- (Slvs_hEntity)theSketchID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- } else {
- // Scalar value (used for the distance entities)
- AttributeDoublePtr aScalar =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
- if (aScalar) {
- aParameters.push_back(createParameter(theGroupID, aScalar->value(), !aScalar->text().empty()));
- // Create entity (parameter is not filled)
- anEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- (Slvs_hEntity)theSketchID, SLVS_E_UNKNOWN);
- }
- }
- }
-
- if (anEntity.type == 0) {
- // unknown attribute type
- return EntityWrapperPtr();
- }
-
- EntityWrapperPtr aResult(new SolveSpaceSolver_EntityWrapper(theAttribute, anEntity));
- aResult->setParameters(aParameters);
- return aResult;
-}
-
-
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createSketchEntity(
- CompositeFeaturePtr theSketch,
- const GroupID& theGroupID) const
-{
- DataPtr aSketchData = theSketch->data();
- if (!aSketchData || !aSketchData->isValid())
- return EntityWrapperPtr(); // the sketch is incorrect
-
- // Get parameters of workplane
- AttributePtr aDirX = aSketchData->attribute(SketchPlugin_Sketch::DIRX_ID());
- AttributePtr aNorm = aSketchData->attribute(SketchPlugin_Sketch::NORM_ID());
- AttributePtr anOrigin = aSketchData->attribute(SketchPlugin_Sketch::ORIGIN_ID());
- if (!anOrigin->isInitialized() || !aNorm->isInitialized() || !aDirX->isInitialized())
- return EntityWrapperPtr();
-
- EntityWrapperPtr aNewEnt;
- std::list<EntityWrapperPtr> aSubs;
-
- // Create SolveSpace entity corresponding to the sketch origin
- aNewEnt = createAttribute(anOrigin, theGroupID);
- if (!aNewEnt)
- return EntityWrapperPtr();
- aSubs.push_back(aNewEnt);
-
- // Create SolveSpace entity corresponding the the sketch normal
- aNewEnt = createNormal(aNorm, aDirX, theGroupID);
- if (!aNewEnt)
- return EntityWrapperPtr();
- aSubs.push_back(aNewEnt);
-
- // Create workplane
- Slvs_Entity aWorkplane = Slvs_MakeWorkplane(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-
- aNewEnt = EntityWrapperPtr(
- new SolveSpaceSolver_EntityWrapper(FeaturePtr(theSketch), aWorkplane));
- aNewEnt->setSubEntities(aSubs);
- return aNewEnt;
-}
-
-EntityWrapperPtr SolveSpaceSolver_Builder::createNormal(
- AttributePtr theNormal,
- AttributePtr theDirX,
- const GroupID& theGroupID) const
-{
- std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theNormal);
- std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theDirX);
- if (!aDirX || !aNorm ||
- (fabs(aDirX->x()) + fabs(aDirX->y()) + fabs(aDirX->z()) < tolerance) ||
- !aNorm->isInitialized())
- return EntityWrapperPtr();
- // calculate Y direction
- std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aDirX->dir())));
-
- // quaternion parameters of normal vector
- double qw, qx, qy, qz;
- Slvs_MakeQuaternion(aDirX->x(), aDirX->y(), aDirX->z(), aDirY->x(), aDirY->y(), aDirY->z(), &qw,
- &qx, &qy, &qz);
- double aNormCoord[4] = { qw, qx, qy, qz };
-
- // Create parameters of the normal
- std::list<ParameterWrapperPtr> aParameters;
- for (int i = 0; i < 4; i++)
- aParameters.push_back(createParameter(theGroupID, aNormCoord[i]));
-
- // Create a normal with empty parameters
- Slvs_Entity aNormalEnt = Slvs_MakeNormal3d(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- EntityWrapperPtr aNormal(new SolveSpaceSolver_EntityWrapper(theNormal, aNormalEnt));
- aNormal->setParameters(aParameters);
- return aNormal;
-}
-
-ParameterWrapperPtr SolveSpaceSolver_Builder::createParameter(
- const GroupID& theGroup, const double theValue, const bool theExpr) const
-{
- Slvs_Param aParam = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroup, theValue);
- ParameterWrapperPtr aWrapper(new SolveSpaceSolver_ParameterWrapper(aParam));
- aWrapper->setIsParametric(theExpr);
- return aWrapper;
-}
-
-
-
-
-
-// ================ Auxiliary functions ==========================
-EntityWrapperPtr createLine(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
- AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
- if (!aStart->isInitialized() || !aEnd->isInitialized())
- return aNewEntity;
-
- EntityWrapperPtr aStartEnt, aEndEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
- if (aSlvsEntity->isBase(aStart))
- aStartEnt = aSlvsEntity;
- else if (aSlvsEntity->isBase(aEnd))
- aEndEnt = aSlvsEntity;
- }
- if (!aStartEnt || !aEndEnt)
- return aNewEntity;
-
- aSubs.push_back(aStartEnt);
- aSubs.push_back(aEndEnt);
- Slvs_Entity anEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- (Slvs_hEntity)theSketchID, (Slvs_hEntity)aStartEnt->id(), (Slvs_hEntity)aEndEnt->id());
-
- aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-EntityWrapperPtr createCircle(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
- AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
- if (!aCenter->isInitialized() || !aRadius->isInitialized())
- return aNewEntity;
-
- EntityWrapperPtr aCenterEnt, aRadiusEnt, aNormalEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
- if (aSlvsEntity->isBase(aCenter))
- aCenterEnt = aSlvsEntity;
- else if (aSlvsEntity->isBase(aRadius))
- aRadiusEnt = aSlvsEntity;
- else if (aSlvsEntity->type() == ENTITY_NORMAL)
- aNormalEnt = aSlvsEntity;
- }
- if (!aCenterEnt || !aRadiusEnt || !aNormalEnt)
- return aNewEntity;
-
- aSubs.push_back(aCenterEnt);
- aSubs.push_back(aRadiusEnt);
- Slvs_Entity anEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- (Slvs_hEntity)theSketchID, (Slvs_hEntity)aCenterEnt->id(),
- (Slvs_hEntity)aNormalEnt->id(), (Slvs_hEntity)aRadiusEnt->id());
-
- aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-EntityWrapperPtr createArc(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
- AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
- AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
- if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
- return aNewEntity;
-
- EntityWrapperPtr aCenterEnt, aStartEnt, aEndEnt, aNormalEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSlvsEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
- if (aSlvsEntity->isBase(aCenter))
- aCenterEnt = aSlvsEntity;
- else if (aSlvsEntity->isBase(aStart))
- aStartEnt = aSlvsEntity;
- else if (aSlvsEntity->isBase(aEnd))
- aEndEnt = aSlvsEntity;
- else if (aSlvsEntity->type() == ENTITY_NORMAL)
- aNormalEnt = aSlvsEntity;
- }
- if (!aCenterEnt || !aStartEnt || !aEndEnt || !aNormalEnt)
- return aNewEntity;
-
- aSubs.push_back(aCenterEnt);
- aSubs.push_back(aStartEnt);
- aSubs.push_back(aEndEnt);
- Slvs_Entity anEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, (Slvs_hGroup)theGroupID,
- (Slvs_hEntity)theSketchID, (Slvs_hEntity)aNormalEnt->id(),
- (Slvs_hEntity)aCenterEnt->id(), (Slvs_hEntity)aStartEnt->id(), (Slvs_hEntity)aEndEnt->id());
-
- aNewEntity = EntityWrapperPtr(new SolveSpaceSolver_EntityWrapper(theFeature, anEntity));
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-
-void adjustTangency(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
- // Collect start, end points of entities
- std::shared_ptr<GeomAPI_Pnt2d> aStartEntPoints[2][2];
- bool isCoinc[2][2] = {false};
- const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (int i = 0; aSIt != aSubs.end(); ++aSIt, ++i) {
- const std::list<EntityWrapperPtr>& aPoints = (*aSIt)->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aPIt = aPoints.begin();
- if ((*aSIt)->type() == ENTITY_ARC)
- ++aPIt;
- for (int j = 0; aPIt != aPoints.end(); ++aPIt, ++j) {
- aStartEntPoints[i][j] = aBuilder->point(*aPIt);
- if (i > 0) { // check coincidence
- for (int k = 0; k < 2; ++k)
- if (aStartEntPoints[i][j]->distance(aStartEntPoints[0][k]) < tolerance)
- isCoinc[0][k] = isCoinc[i][j] = true;
- }
- }
- }
-
- Slvs_Constraint& aSlvsConstraint = aConstraint->changeConstraint();
- if (isCoinc[0][0] == false && isCoinc[0][1] == true)
- aSlvsConstraint.other = 1;
- else aSlvsConstraint.other = 0;
- if (isCoinc[1][0] == false && isCoinc[1][1] == true)
- aSlvsConstraint.other2 = 1;
- else aSlvsConstraint.other2 = 0;
-}
-
-void adjustAngle(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[2][2]; // start and end points of lines
- const std::list<EntityWrapperPtr>& aConstrLines = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aCLIt = aConstrLines.begin();
- for (int i = 0; aCLIt != aConstrLines.end(); ++i, ++aCLIt) {
- const std::list<EntityWrapperPtr>& aLinePoints = (*aCLIt)->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aLPIt = aLinePoints.begin();
- for (int j = 0; aLPIt != aLinePoints.end(); ++j, ++aLPIt)
- aPoints[i][j] = aBuilder->point(*aLPIt);
- }
-
- std::shared_ptr<GeomAPI_Lin2d> aLine[2] = {
- std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0][0], aPoints[0][1])),
- std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[1][0], aPoints[1][1]))
- };
- std::shared_ptr<GeomAPI_Pnt2d> anIntersection = aLine[0]->intersect(aLine[1]);
- if (!anIntersection)
- return;
- double aDist[2][2];
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- aDist[i][j] = anIntersection->distance(aPoints[i][j]);
- if (fabs(aDist[i][j]) <= tolerance)
- aDist[i][j] = 0.0;
- }
- if (aDist[i][0] > tolerance && aDist[i][1] > tolerance &&
- aDist[i][0] + aDist[i][1] < aPoints[i][0]->distance(aPoints[i][1]) + 2.0 * tolerance) {
- // the intersection point is an inner point of the line,
- // we change the sign of distance till start point to calculate correct coordinates
- // after rotation
- aDist[i][0] *= -1.0;
- }
- }
- std::shared_ptr<GeomAPI_Dir2d> aDir[2];
- for (int i = 0; i < 2; i++) {
- if (aDist[i][1] > fabs(aDist[i][0]))
- aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
- aPoints[i][1]->xy()->decreased(anIntersection->xy())));
- else {
- aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
- aPoints[i][0]->xy()->decreased(anIntersection->xy())));
- // main direction is opposite => change signs
- if (aDist[i][0] < 0.0) {
- aDist[i][0] *= -1.0;
- aDist[i][1] *= -1.0;
- }
- }
- }
-
- Slvs_Constraint& aSlvsConstraint = aConstraint->changeConstraint();
- aSlvsConstraint.other = false;
- for (int i = 0; i < 2; i++)
- if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
- aSlvsConstraint.other = !aSlvsConstraint.other;
-}
-
-void adjustMirror(ConstraintWrapperPtr theConstraint)
-{
- std::vector<EntityWrapperPtr> aPoints;
- EntityWrapperPtr aMirrorLine;
-
- const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (; anIt != aSubs.end(); ++anIt) {
- if ((*anIt)->type() == ENTITY_POINT)
- aPoints.push_back(*anIt);
- else if ((*anIt)->type() == ENTITY_LINE)
- aMirrorLine = *anIt;
- }
-
- makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
-}
-
-void makeMirrorPoints(EntityWrapperPtr theOriginal,
- EntityWrapperPtr theMirrored,
- EntityWrapperPtr theMirrorLine)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
- std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
- // orthogonal direction
- aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
- std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
- double aDist = aVec->dot(aMLDir->xy());
- aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
- double aCoord[2] = {aVec->x(), aVec->y()};
- std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
- for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
- (*aMIt)->setValue(aCoord[i]);
-
- // update corresponding attribute
- AttributePtr anAttr = std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMirrored)->baseAttribute();
- if (anAttr) {
- std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
- aMirroredPnt->setValue(aCoord[0], aCoord[1]);
- }
-}
-
-static void rotate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
- std::shared_ptr<GeomAPI_Pnt2d> theCenter,
- double theSin, double theCos)
-{
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSource =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSource);
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aDest =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theDest);
-
- if (theSource->type() == ENTITY_POINT) {
- // Rotate single point
- std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSource->baseAttribute());
- std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDest->baseAttribute());
- if (aSrcAttr && aDstAttr) {
- std::shared_ptr<GeomAPI_XY> aVec = aSrcAttr->pnt()->xy()->decreased(theCenter->xy());
- double aNewX = aVec->x() * theCos - aVec->y() * theSin;
- double aNewY = aVec->x() * theSin + aVec->y() * theCos;
- aDstAttr->setValue(theCenter->x() + aNewX, theCenter->y() + aNewY);
- }
- return;
- }
-
- FeaturePtr aDestFeature = aDest->baseFeature();
- if (aDestFeature)
- aDestFeature->data()->blockSendAttributeUpdated(true);
-
- // Rotate points of the feature
- const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
- const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
- for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
- aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
- rotate(*aSrcIt, *aDstIt, theCenter, theSin, theCos);
-
- if (aDestFeature)
- aDestFeature->data()->blockSendAttributeUpdated(false);
-}
-
-static void translate(EntityWrapperPtr theSource, EntityWrapperPtr theDest,
- std::shared_ptr<GeomAPI_XY> theDelta)
-{
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSource =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSource);
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aDest =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theDest);
-
- if (theSource->type() == ENTITY_POINT) {
- // Translate single point
- std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSource->baseAttribute());
- std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDest->baseAttribute());
- if (aSrcAttr && aDstAttr)
- aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
- return;
- }
-
- FeaturePtr aDestFeature = aDest->baseFeature();
- if (aDestFeature)
- aDestFeature->data()->blockSendAttributeUpdated(true);
-
- // Translate points of the feature
- const std::list<EntityWrapperPtr>& aSrcSubs = theSource->subEntities();
- const std::list<EntityWrapperPtr>& aDstSubs = theDest->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSrcIt, aDstIt;
- for (aSrcIt = aSrcSubs.begin(), aDstIt = aDstSubs.begin();
- aSrcIt != aSrcSubs.end() && aDstIt != aDstSubs.end(); ++aSrcIt, ++aDstIt)
- translate(*aSrcIt, *aDstIt, theDelta);
-
- if (aDestFeature)
- aDestFeature->data()->blockSendAttributeUpdated(false);
-}
-
-void adjustMultiRotation(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- double anAngleRad = theConstraint->value() * PI / 180.0;
- double aSin = sin(anAngleRad);
- double aCos = cos(anAngleRad);
-
- const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
- std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSIt++);
- std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
- for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
- rotate(*aPrevIt, *aSIt, aCenter, aSin, aCos);
-}
-
-void adjustMultiTranslation(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
- std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aBuilder->point(*aSIt++);
- std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aBuilder->point(*aSIt++);
- std::shared_ptr<GeomAPI_XY> aDelta = aEndPnt->xy()->decreased(aStartPnt->xy());
-
- std::list<EntityWrapperPtr>::const_iterator aPrevIt = aSIt++;
- for (; aSIt != aSubs.end(); ++aPrevIt, ++aSIt)
- translate(*aPrevIt, *aSIt, aDelta);
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Builder.h
-// Created: 25 Mar 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Builder_H_
-#define SolveSpaceSolver_Builder_H_
-
-#include <SketchSolver_Builder.h>
-#include <SketchSolver_Constraint.h>
-
-#include <SketchPlugin_Constraint.h>
-
-#include <ModelAPI_CompositeFeature.h>
-
-/** \class SolveSpaceSolver_Builder
- * \ingroup Plugins
- * \brief Create bridges between SketchPlugin constraints and SolveSpace constraints
- */
-class SolveSpaceSolver_Builder : public SketchSolver_Builder
-{
-private:
- /// Default constructor
- SolveSpaceSolver_Builder() {}
-
-public:
- /// \brief Returns single instance of builder
- static BuilderPtr getInstance();
-
- /// \brief Creates a storage specific for used solver
- virtual StoragePtr createStorage(const GroupID& theGroup) const;
- /// \brief Creates specific solver
- virtual SolverPtr createSolver() const;
-
- /// \brief Creates new constraint(s) using given parameters
- /// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
- /// \param theType [in] type of constraint
- /// \param theValue [in] numeric characteristic of constraint (e.g. distance or radius) if applicable
- /// \param theEntity1 [in] first attribute of constraint
- /// \param theEntity2 [in] second attribute of constraint
- /// \param theEntity3 [in] third attribute of constraint
- /// \param theEntity4 [in] fourth attribute of constraint
- /// \return Created list of wrappers of constraints applicable for specific solver.
- /// Most of constraint types lead to single constraint, but there are some kind of
- /// constraints (e.g. mirror), which may produce couple of constraints.
- virtual std::list<ConstraintWrapperPtr>
- createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
- const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
- const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const;
-
- /// \brief Creates new multi-translation or multi-rotation constraint
- /// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
- /// \param theType [in] type of constraint
- /// \param theValue [in] numeric characteristic of constraint (angle for multi-rotation) if applicable
- /// \param thePoint1 [in] center for multi-rotation or start point for multi-translation
- /// \param thePoint2 [in] end point for multi-translation (empty for multi-rotation)
- /// \param theTrsfEnt [in] list of transformed entities
- virtual std::list<ConstraintWrapperPtr>
- createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const SketchSolver_ConstraintType& theType,
- const double& theValue,
- const EntityWrapperPtr& thePoint1,
- const EntityWrapperPtr& thePoint2,
- const std::list<EntityWrapperPtr>& theTrsfEnt) const;
-
- /// \brief Update flags for several kinds of constraints
- virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const;
-
- /// \brief Creates a feature using list of already created attributes
- /// \param theFeature [in] feature to create
- /// \param theAttributes [in] attributes of the feature
- /// \param theGroupID [in] group the feature belongs to
- /// \param theSketchID [in] sketch the feature belongs to
- /// \return Created wrapper of the feature applicable for specific solver
- virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID = EID_UNKNOWN) const;
-
- /// \brief Creates an attribute
- /// \param theAttribute [in] attribute to create
- /// \param theGroup [in] group the attribute belongs to
- /// \param theSketchID [in] sketch the attribute belongs to
- /// \return Created wrapper of the attribute applicable for specific solver
- virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
- const GroupID& theGroup,
- const EntityID& theSketchID = EID_UNKNOWN) const;
-
-private:
- /// \brief Create necessary constraints to make two object symmetric relatively a given line
- std::list<ConstraintWrapperPtr> createMirror(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2,
- const EntityWrapperPtr& theMirrorLine) const;
-
- /// \brief Converts sketch parameters to the entity applicable for the solver.
- /// \param theSketch [in] the element to be converted
- /// \param theGroupID [in] group where the sketch should be created
- /// \return Entity respective the sketch or empty pointer, it the sketch has incorrect attributes
- EntityWrapperPtr createSketchEntity(CompositeFeaturePtr theSketch,
- const GroupID& theGroupID) const;
-
- /// \brief Converts two axes of sketch's trihedron to the normal entity
- /// \param theNormal [in] direction of the normal of the sketch
- /// \param theDirX [in] direction of the X axis of the sketch
- /// \param theGroupID [in] group, the normal belongs to
- /// \return Created entity or empty pointer, if there are incorrect attributes
- EntityWrapperPtr createNormal(AttributePtr theNormal,
- AttributePtr theDirX,
- const GroupID& theGroupID) const;
-
- /// \brief Converts a value to SolveSpace parameter
- /// \param theGroup [in] group to store parameter
- /// \param theValue [in] value of parameter
- /// \param theExpr [in] shows the parameter is given by expression
- /// \return Created parameter's wrapper
- ParameterWrapperPtr createParameter(const GroupID& theGroup,
- const double theValue = 0.0,
- const bool theExpr = false) const;
-
-private:
- static BuilderPtr mySelf;
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_ConstraintType.h
-// Created: 8 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ConstraintType_H_
-#define SolveSpaceSolver_ConstraintType_H_
-
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-namespace ConstraintType
-{
- /// \brief Convert constraint type from SketchSolver to SolveSpace
- static int toSolveSpace(SketchSolver_ConstraintType theType)
- {
- switch (theType) {
- case CONSTRAINT_PT_PT_COINCIDENT: return SLVS_C_POINTS_COINCIDENT;
- case CONSTRAINT_PT_ON_LINE: return SLVS_C_PT_ON_LINE;
- case CONSTRAINT_PT_ON_CIRCLE: return SLVS_C_PT_ON_CIRCLE;
- case CONSTRAINT_PT_PT_DISTANCE: return SLVS_C_PT_PT_DISTANCE;
- case CONSTRAINT_PT_LINE_DISTANCE: return SLVS_C_PT_LINE_DISTANCE;
- case CONSTRAINT_ANGLE: return SLVS_C_ANGLE;
- case CONSTRAINT_RADIUS: return SLVS_C_DIAMETER;
- case CONSTRAINT_FIXED: return SLVS_C_WHERE_DRAGGED;
- case CONSTRAINT_HORIZONTAL: return SLVS_C_HORIZONTAL;
- case CONSTRAINT_VERTICAL: return SLVS_C_VERTICAL;
- case CONSTRAINT_PARALLEL: return SLVS_C_PARALLEL;
- case CONSTRAINT_PERPENDICULAR: return SLVS_C_PERPENDICULAR;
- case CONSTRAINT_SYMMETRIC: return SLVS_C_SYMMETRIC_LINE;
- case CONSTRAINT_EQUAL_LINES: return SLVS_C_EQUAL_LENGTH_LINES;
- case CONSTRAINT_EQUAL_LINE_ARC: return SLVS_C_EQUAL_LINE_ARC_LEN;
- case CONSTRAINT_EQUAL_RADIUS: return SLVS_C_EQUAL_RADIUS;
- case CONSTRAINT_TANGENT_ARC_LINE: return SLVS_C_ARC_LINE_TANGENT;
- case CONSTRAINT_TANGENT_ARC_ARC: return SLVS_C_CURVE_CURVE_TANGENT;
- case CONSTRAINT_MULTI_ROTATION: return SLVS_C_MULTI_ROTATION;
- case CONSTRAINT_MULTI_TRANSLATION: return SLVS_C_MULTI_TRANSLATION;
- default: break;
- }
- return SLVS_C_UNKNOWN;
- }
-
- /// \brief Convert constraint type from SolveSpace to SketchSolver
- static SketchSolver_ConstraintType fromSolveSpace(int theType)
- {
- switch (theType) {
- case SLVS_C_POINTS_COINCIDENT: return CONSTRAINT_PT_PT_COINCIDENT;
- case SLVS_C_PT_ON_LINE: return CONSTRAINT_PT_ON_LINE;
- case SLVS_C_PT_ON_CIRCLE: return CONSTRAINT_PT_ON_CIRCLE;
- case SLVS_C_PT_PT_DISTANCE: return CONSTRAINT_PT_PT_DISTANCE;
- case SLVS_C_PT_LINE_DISTANCE: return CONSTRAINT_PT_LINE_DISTANCE;
- case SLVS_C_EQUAL_LENGTH_LINES: return CONSTRAINT_EQUAL_LINES;
- case SLVS_C_EQUAL_LINE_ARC_LEN: return CONSTRAINT_EQUAL_LINE_ARC;
- case SLVS_C_SYMMETRIC_LINE: return CONSTRAINT_SYMMETRIC;
- case SLVS_C_HORIZONTAL: return CONSTRAINT_HORIZONTAL;
- case SLVS_C_VERTICAL: return CONSTRAINT_VERTICAL;
- case SLVS_C_DIAMETER: return CONSTRAINT_RADIUS;
- case SLVS_C_ANGLE: return CONSTRAINT_ANGLE;
- case SLVS_C_PARALLEL: return CONSTRAINT_PARALLEL;
- case SLVS_C_PERPENDICULAR: return CONSTRAINT_PERPENDICULAR;
- case SLVS_C_ARC_LINE_TANGENT: return CONSTRAINT_TANGENT_ARC_LINE;
- case SLVS_C_EQUAL_RADIUS: return CONSTRAINT_EQUAL_RADIUS;
- case SLVS_C_WHERE_DRAGGED: return CONSTRAINT_FIXED;
- case SLVS_C_CURVE_CURVE_TANGENT: return CONSTRAINT_TANGENT_ARC_ARC;
- case SLVS_C_MULTI_ROTATION: return CONSTRAINT_MULTI_ROTATION;
- case SLVS_C_MULTI_TRANSLATION: return CONSTRAINT_MULTI_TRANSLATION;
- default: break;
- }
- return CONSTRAINT_UNKNOWN;
- }
-}
-
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_ConstraintWrapper.cpp
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_ConstraintType.h>
-#include <math.h>
-
-SolveSpaceSolver_ConstraintWrapper::SolveSpaceSolver_ConstraintWrapper(
- const ConstraintPtr& theOriginal,
- const Slvs_Constraint& theConstraint)
- : mySlvsConstraint(theConstraint)
-{
- myBaseConstraint = theOriginal;
- myValue = mySlvsConstraint.valA;
-}
-
-ConstraintID SolveSpaceSolver_ConstraintWrapper::id() const
-{
- return (ConstraintID)mySlvsConstraint.h;
-}
-
-void SolveSpaceSolver_ConstraintWrapper::setGroup(const GroupID& theGroup)
-{
- mySlvsConstraint.group = (Slvs_hGroup)theGroup;
- std::list<EntityWrapperPtr>::iterator aSubsIt = myConstrained.begin();
- for (; aSubsIt != myConstrained.end(); ++aSubsIt)
- (*aSubsIt)->setGroup(theGroup);
-}
-
-SketchSolver_ConstraintType SolveSpaceSolver_ConstraintWrapper::type() const
-{
- return ConstraintType::fromSolveSpace(mySlvsConstraint.type);
-}
-
-void SolveSpaceSolver_ConstraintWrapper::setValue(const double& theValue)
-{
- double aValue = theValue;
- if (type() == CONSTRAINT_RADIUS)
- aValue *= 2.0; // NOTE: SolveSpace uses constraint DIAMETER
-
- SketchSolver_IConstraintWrapper::setValue(aValue);
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isUsed(FeaturePtr theFeature) const
-{
- std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
- for (; anIt != myConstrained.end(); ++anIt)
- if ((*anIt)->isUsed(theFeature))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isUsed(AttributePtr theAttribute) const
-{
- std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
- for (; anIt != myConstrained.end(); ++anIt)
- if ((*anIt)->isUsed(theAttribute))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::isEqual(const ConstraintWrapperPtr& theOther)
-{
- const Slvs_Constraint anOtherConstraint =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theOther)->constraint();
- if (mySlvsConstraint.type != anOtherConstraint.type)
- return false;
-
- // Verify SolveSpace entities. If they are equal, no need additional checking of parameters.
- if (mySlvsConstraint.group == anOtherConstraint.group &&
- mySlvsConstraint.ptA == anOtherConstraint.ptA &&
- mySlvsConstraint.ptB == anOtherConstraint.ptB &&
- mySlvsConstraint.entityA == anOtherConstraint.entityA &&
- mySlvsConstraint.entityB == anOtherConstraint.entityB &&
- mySlvsConstraint.entityC == anOtherConstraint.entityC &&
- mySlvsConstraint.entityD == anOtherConstraint.entityD &&
- fabs(mySlvsConstraint.valA - anOtherConstraint.valA) < tolerance) {
- return true;
- }
-
- // Verify equality of values
- if (fabs(myValue - theOther->value()) > tolerance)
- return false;
-
- // Verify equality of entities
- const std::list<EntityWrapperPtr>& anOtherSubs = theOther->entities();
- if (myConstrained.size() != anOtherSubs.size())
- return false;
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = myConstrained.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != myConstrained.end(); ++aMySubsIt, ++anOtherSubsIt)
- if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
- return false;
- return true;
-}
-
-bool SolveSpaceSolver_ConstraintWrapper::update(const ConstraintWrapperPtr& theOther)
-{
- bool isUpdated = false;
-
- std::list<EntityWrapperPtr> aMySubs = entities();
- std::list<EntityWrapperPtr> anOtherSubs = theOther->entities();
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
- ++aMySubsIt, ++anOtherSubsIt)
- isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
- if (fabs(value() - theOther->value()) > tolerance) {
- myValue = theOther->value();
- isUpdated = true;
- }
- return isUpdated;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_ConstraintWrapper.h
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ConstraintWrapper_H_
-#define SolveSpaceSolver_ConstraintWrapper_H_
-
-#include <SketchSolver_IConstraintWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-
-/**
- * Wrapper providing operations with SovleSpace constraints.
- */
-class SolveSpaceSolver_ConstraintWrapper : public SketchSolver_IConstraintWrapper
-{
-public:
- SolveSpaceSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
- const Slvs_Constraint& theConstraint);
-
- /// \brief Return SolveSpace constraint
- const Slvs_Constraint& constraint() const
- { return mySlvsConstraint; }
- /// \brief Return SolveSpace constraint to change
- Slvs_Constraint& changeConstraint()
- { return mySlvsConstraint; }
-
- /// \brief Return ID of current entity
- virtual ConstraintID id() const;
-
- /// \brief Change group for the constraint
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the constraint belongs to
- virtual const GroupID& group() const
- { return (GroupID)mySlvsConstraint.group; }
-
- /// \brief Return type of current entity
- virtual SketchSolver_ConstraintType type() const;
-
- /// \brief Assign numeric parameter of constraint
- virtual void setValue(const double& theValue);
-
- /// \brief Verify the feature is used in the constraint
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used in the constraint
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current constraint with other
- virtual bool isEqual(const ConstraintWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this constraint by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther);
-
-private:
- Slvs_Constraint mySlvsConstraint;
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_EntityWrapper.cpp
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#include <SolveSpaceSolver_EntityWrapper.h>
-
-SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper(
- const FeaturePtr theFeature, const Slvs_Entity& theEntity)
- : myEntity(theEntity)
-{
- myBaseFeature = theFeature;
-}
-
-SolveSpaceSolver_EntityWrapper::SolveSpaceSolver_EntityWrapper(
- const AttributePtr theAttribute, const Slvs_Entity& theEntity)
- : myEntity(theEntity)
-{
- myBaseAttribute = theAttribute;
-}
-
-EntityID SolveSpaceSolver_EntityWrapper::id() const
-{
- return (EntityID)myEntity.h;
-}
-
-void SolveSpaceSolver_EntityWrapper::setGroup(const GroupID& theGroup)
-{
- myEntity.group = (Slvs_hGroup)theGroup;
- std::list<EntityWrapperPtr>::iterator aSubsIt = mySubEntities.begin();
- for (; aSubsIt != mySubEntities.end(); ++aSubsIt)
- (*aSubsIt)->setGroup(theGroup);
- std::list<ParameterWrapperPtr>::iterator aPIt = myParameters.begin();
- for (; aPIt != myParameters.end(); ++aPIt)
- (*aPIt)->setGroup(theGroup);
-}
-
-SketchSolver_EntityType SolveSpaceSolver_EntityWrapper::type() const
-{
- switch (myEntity.type) {
- case SLVS_E_POINT_IN_3D:
- case SLVS_E_POINT_IN_2D: return ENTITY_POINT;
- case SLVS_E_LINE_SEGMENT: return ENTITY_LINE;
- case SLVS_E_CIRCLE: return ENTITY_CIRCLE;
- case SLVS_E_ARC_OF_CIRCLE: return ENTITY_ARC;
- case SLVS_E_NORMAL_IN_3D:
- case SLVS_E_NORMAL_IN_2D: return ENTITY_NORMAL;
- case SLVS_E_DISTANCE: return ENTITY_SCALAR;
- case SLVS_E_WORKPLANE: return ENTITY_SKETCH;
- default: break;
- }
- return ENTITY_UNKNOWN;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isUsed(FeaturePtr theFeature) const
-{
- if (isBase(theFeature))
- return true;
-
- std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
- for (; anIt != mySubEntities.end(); ++anIt)
- if ((*anIt)->isUsed(theFeature))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isUsed(AttributePtr theAttribute) const
-{
- if (isBase(theAttribute))
- return true;
-
- std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
- for (; anIt != mySubEntities.end(); ++anIt)
- if ((*anIt)->isUsed(theAttribute))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_EntityWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
- if (type() != theOther->type())
- return false;
-
- // Verify Equality of sub-entities
- const std::list<EntityWrapperPtr>& anOtherSubs = theOther->subEntities();
- if (mySubEntities.size() != anOtherSubs.size())
- return false;
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = mySubEntities.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != mySubEntities.end(); ++aMySubsIt, ++anOtherSubsIt)
- if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
- return false;
-
- // Verify equality of parameters
- const std::list<ParameterWrapperPtr>& anOtherParams = theOther->parameters();
- if (myParameters.size() != anOtherParams.size())
- return false;
- std::list<ParameterWrapperPtr>::const_iterator aMyIt = myParameters.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherIt = anOtherParams.begin();
- for (; aMyIt != myParameters.end(); ++aMyIt, ++anOtherIt)
- if (!(*aMyIt)->isEqual(*anOtherIt))
- return false;
- return true;
-}
-
-bool SolveSpaceSolver_EntityWrapper::update(const EntityWrapperPtr& theOther)
-{
- bool isUpdated = false;
-
- std::list<EntityWrapperPtr> aMySubs = subEntities();
- std::list<EntityWrapperPtr> anOtherSubs = theOther->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
- ++aMySubsIt, ++anOtherSubsIt)
- isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
- std::list<ParameterWrapperPtr> aMyParams = parameters();
- std::list<ParameterWrapperPtr> anOtherParams = theOther->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aMyParIt = aMyParams.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherParIt = anOtherParams.begin();
- for (; aMyParIt != aMyParams.end() && anOtherParIt != anOtherParams.end();
- ++aMyParIt, ++anOtherParIt)
- isUpdated = (*aMyParIt)->update(*anOtherParIt);
- return isUpdated;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_EntityWrapper.h
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_EntityWrapper_H_
-#define SolveSpaceSolver_EntityWrapper_H_
-
-#include <SketchSolver_IEntityWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-/**
- * Wrapper providing operations with SolveSpace entities.
- */
-class SolveSpaceSolver_EntityWrapper : public SketchSolver_IEntityWrapper
-{
-public:
- SolveSpaceSolver_EntityWrapper(const FeaturePtr theFeature, const Slvs_Entity& theEntity);
- SolveSpaceSolver_EntityWrapper(const AttributePtr theAttribute, const Slvs_Entity& theEntity);
-
- /// \brief Return SolveSpace entity
- const Slvs_Entity& entity() const
- { return myEntity; }
- /// \brief Return SolveSpace entity to change
- Slvs_Entity& changeEntity()
- { return myEntity; }
-
- /// \brief Return ID of current entity
- virtual EntityID id() const;
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the entity belongs to
- virtual const GroupID& group() const
- { return (GroupID)myEntity.group; }
-
- /// \brief Return type of current entity
- virtual SketchSolver_EntityType type() const;
-
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const EntityWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther);
-
-private:
- Slvs_Entity myEntity;
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_ParameterWrapper.cpp
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#include <SolveSpaceSolver_ParameterWrapper.h>
-
-#include <math.h>
-
-SolveSpaceSolver_ParameterWrapper::SolveSpaceSolver_ParameterWrapper(const Slvs_Param& theParam)
- : myParameter(theParam)
-{
-}
-
-ParameterID SolveSpaceSolver_ParameterWrapper::id() const
-{
- return (ParameterID)myParameter.h;
-}
-
-void SolveSpaceSolver_ParameterWrapper::setValue(double theValue)
-{
- myParameter.val = theValue;
-}
-
-double SolveSpaceSolver_ParameterWrapper::value() const
-{
- return myParameter.val;
-}
-
-bool SolveSpaceSolver_ParameterWrapper::isEqual(const ParameterWrapperPtr& theOther)
-{
- std::shared_ptr<SolveSpaceSolver_ParameterWrapper> anOtherParam =
- std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theOther);
- return anOtherParam && fabs(value() - anOtherParam->value()) < tolerance;
-}
-
-bool SolveSpaceSolver_ParameterWrapper::update(const ParameterWrapperPtr& theOther)
-{
- std::shared_ptr<SolveSpaceSolver_ParameterWrapper> anOther =
- std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theOther);
- if (fabs(value() - anOther->value()) < tolerance)
- return false;
- myParameter.val = anOther->value();
- myIsParametric = theOther->isParametric();
- return true;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_ParameterWrapper.h
-// Created: 2 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_ParameterWrapper_H_
-#define SolveSpaceSolver_ParameterWrapper_H_
-
-#include <SketchSolver_IParameterWrapper.h>
-#include <SolveSpaceSolver_Solver.h>
-
-/**
- * Wrapper providing operations with parameters in SolveSpace.
- */
-class SolveSpaceSolver_ParameterWrapper : public SketchSolver_IParameterWrapper
-{
-public:
- SolveSpaceSolver_ParameterWrapper(const Slvs_Param& theParam);
-
- /// \brief Return SolveSpace parameter
- const Slvs_Param& parameter() const
- { return myParameter; }
- /// \brief Return SolveSpace parameter to change
- Slvs_Param& changeParameter()
- { return myParameter; }
-
- /// \brief Return ID of current parameter
- virtual ParameterID id() const;
-
- /// \brief Change group for the parameter
- virtual void setGroup(const GroupID& theGroup)
- { myParameter.group = (Slvs_hGroup)theGroup; }
-
- /// \brief Return identifier of the group the parameter belongs to
- virtual const GroupID& group() const
- { return (GroupID)myParameter.group; }
-
- /// \brief Change value of parameter
- virtual void setValue(double theValue);
- /// \brief Return value of parameter
- virtual double value() const;
-
- /// \brief Compare current parameter with other
- virtual bool isEqual(const ParameterWrapperPtr& theOther);
-
- /// \brief Update value of parameter by the given one
- /// \return \c true if the value of parameter is changed
- virtual bool update(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther);
-
-private:
- Slvs_Param myParameter;
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Solver.cpp
-// Created: 07 May 2014
-// Author: Artem ZHIDKOV
-
-#include "SolveSpaceSolver_Solver.h"
-#include <Events_LongOp.h>
-
-SolveSpaceSolver_Solver::SolveSpaceSolver_Solver()
-{
- // Nullify all elements of the set of equations
- myEquationsSystem.param = 0;
- myEquationsSystem.params = 0;
- myEquationsSystem.entity = 0;
- myEquationsSystem.entities = 0;
- myEquationsSystem.constraint = 0;
- myEquationsSystem.constraints = 0;
- myEquationsSystem.failed = 0;
- myEquationsSystem.faileds = 0;
-
- myEquationsSystem.dragged[0] = 0;
- myEquationsSystem.dragged[1] = 0;
- myEquationsSystem.dragged[2] = 0;
- myEquationsSystem.dragged[3] = 0;
-
- // If the set of constraints is inconsistent,
- // the failed field will contain wrong constraints
- myEquationsSystem.calculateFaileds = 0;
-}
-
-SolveSpaceSolver_Solver::~SolveSpaceSolver_Solver()
-{
- if (myEquationsSystem.constraint)
- delete[] myEquationsSystem.constraint;
- myEquationsSystem.constraint = 0;
- if (myEquationsSystem.failed)
- delete[] myEquationsSystem.failed;
- myEquationsSystem.failed = 0;
-}
-
-void SolveSpaceSolver_Solver::setParameters(Slvs_Param* theParameters, int theSize)
-{
- myEquationsSystem.param = theParameters;
- myEquationsSystem.params = theSize;
-}
-
-
-void SolveSpaceSolver_Solver::setDraggedParameters(const Slvs_hParam* theDragged)
-{
- for (unsigned int i = 0; i < 4; i++)
- myEquationsSystem.dragged[i] = theDragged[i];
-}
-
-void SolveSpaceSolver_Solver::setEntities(Slvs_Entity* theEntities, int theSize)
-{
- myEquationsSystem.entity = theEntities;
- myEquationsSystem.entities = theSize;
-}
-
-void SolveSpaceSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
-{
- if (!myEquationsSystem.constraint) {
- myEquationsSystem.constraint = new Slvs_Constraint[theSize];
- myEquationsSystem.constraints = theSize;
- myEquationsSystem.failed = new Slvs_hConstraint[theSize];
- }
- else if (myEquationsSystem.constraints != theSize) {
- if (theSize > myEquationsSystem.constraints) {
- delete[] myEquationsSystem.constraint;
- myEquationsSystem.constraint = new Slvs_Constraint[theSize];
- if (myEquationsSystem.failed)
- delete[] myEquationsSystem.failed;
- myEquationsSystem.failed = new Slvs_hConstraint[theSize];
- }
- myEquationsSystem.constraints = theSize;
- }
- memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
- memset(myEquationsSystem.failed, SLVS_C_UNKNOWN, theSize * sizeof(Slvs_hConstraint));
-}
-
-
-SketchSolver_SolveStatus SolveSpaceSolver_Solver::solve()
-{
- if (myEquationsSystem.constraints <= 0)
- return STATUS_EMPTYSET;
-
- myEquationsSystem.calculateFaileds = myFindFaileds ? 1 : 0;
-
- Events_LongOp::start(this);
- Slvs_Solve(&myEquationsSystem, myGroup);
- Events_LongOp::end(this);
-
- SketchSolver_SolveStatus aStatus;
- switch (myEquationsSystem.result) {
- case SLVS_RESULT_OKAY:
- aStatus = STATUS_OK;
- break;
- case SLVS_RESULT_INCONSISTENT:
- case SLVS_RESULT_DIDNT_CONVERGE:
- case SLVS_RESULT_TOO_MANY_UNKNOWNS:
- aStatus = STATUS_INCONSISTENT;
- break;
- default:
- aStatus = STATUS_FAILED;
- }
- return aStatus;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Solver.h
-// Created: 07 May 2014
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Solver_H_
-#define SolveSpaceSolver_Solver_H_
-
-#include <SketchSolver_ISolver.h>
-
-// Need to be defined before including SolveSpace to avoid additional dependences on Windows platform
-#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES)
-typedef unsigned int UINT32;
-#else
-#include <stdint.h>
-#endif
-#include <string.h>
-#include <slvs.h>
-
-#include <vector>
-
-// Unknown constraint (for error reporting)
-#define SLVS_C_UNKNOWN 0
-// Fillet constraint identifier
-#define SLVS_C_FILLET 100100
-// Multi-rotation constraint identifier
-#define SLVS_C_MULTI_ROTATION 100101
-// Multi-translation constraint identifier
-#define SLVS_C_MULTI_TRANSLATION 100102
-// Unknown entity
-#define SLVS_E_UNKNOWN 0
-// Unknown group
-#define SLVS_G_UNKNOWN 0
-// Group ID to store external objects
-#define SLVS_G_OUTOFGROUP 1
-
-/** \class SolveSpaceSolver_Solver
- * \ingroup Plugins
- * \brief Performs high-level operations to solve sketch in SolveSpace.
- */
-class SolveSpaceSolver_Solver : public SketchSolver_ISolver
-{
- public:
- SolveSpaceSolver_Solver();
- virtual ~SolveSpaceSolver_Solver();
-
- /** \brief Change array of parameters
- * \param[in] theParameters pointer to the array of parameters
- * \param[in] theSize size of this array
- */
- void setParameters(Slvs_Param* theParameters, int theSize);
-
- /** \brief Change array of entities
- * \param[in] theEntities pointer to the array of entities
- * \param[in] theSize size of this array
- */
- void setEntities(Slvs_Entity* theEntities, int theSize);
-
- /** \brief Change array of constraints
- * \param[in] theConstraints pointer to the array of constraints
- * \param[in] theSize size of this array
- */
- void setConstraints(Slvs_Constraint* theConstraints, int theSize);
-
- /** \brief Store the parameters of the point which was moved by user.
- * The solver will watch this items to be constant
- * \param[in] theDragged list of parameters (not more than 4) which should not be changed during solving
- */
- void setDraggedParameters(const Slvs_hParam* theDragged);
-
- /** \brief Solve the set of equations
- * \return identifier whether solution succeeded
- */
- virtual SketchSolver_SolveStatus solve();
-
- private:
- Slvs_System myEquationsSystem; ///< set of equations for solving in SolveSpace
-};
-
-#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Storage.cpp
-// Created: 18 Mar 2015
-// Author: Artem ZHIDKOV
-
-#include <SolveSpaceSolver_Storage.h>
-#include <SolveSpaceSolver_ConstraintWrapper.h>
-#include <SolveSpaceSolver_EntityWrapper.h>
-#include <SolveSpaceSolver_ParameterWrapper.h>
-#include <SolveSpaceSolver_Builder.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <math.h>
-#include <assert.h>
-
-#include <GeomDataAPI_Point.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeDouble.h>
-
-/** \brief Search the entity/parameter with specified ID in the list of elements
- * \param[in] theEntityID unique ID of the element
- * \param[in] theEntities list of elements
- * \return position of the found element or -1 if the element is not found
- */
-template<typename T>
-static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
-
-/// \brief Compare two parameters to be different
-static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
-/// \brief Compare two entities to be different
-static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
-/// \brief Compare two constraints to be different
-static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
-
-
-SolveSpaceSolver_Storage::SolveSpaceSolver_Storage(const GroupID& theGroup)
- : SketchSolver_Storage(theGroup),
- myWorkplaneID(SLVS_E_UNKNOWN),
- myParamMaxID(SLVS_E_UNKNOWN),
- myEntityMaxID(SLVS_E_UNKNOWN),
- myConstrMaxID(SLVS_C_UNKNOWN),
- myFixed(SLVS_E_UNKNOWN),
- myDuplicatedConstraint(false)
-{
-}
-
-bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
-{
- bool isUpdated = false;
- std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
- Slvs_Constraint aSlvsConstr = getConstraint((Slvs_hConstraint)aConstraint->id());
- if (aSlvsConstr.h == SLVS_C_UNKNOWN)
- aSlvsConstr = aConstraint->constraint();
-
- // update value of constraint if exist
- if (fabs(aSlvsConstr.valA - theConstraint->value()) > tolerance) {
- aSlvsConstr.valA = theConstraint->value();
- isUpdated = true;
- }
-
- // update constrained entities
- Slvs_hEntity* aPnts[2] = {&aSlvsConstr.ptA, &aSlvsConstr.ptB};
- Slvs_hEntity* anEnts[4] = {&aSlvsConstr.entityA, &aSlvsConstr.entityB,
- &aSlvsConstr.entityC, &aSlvsConstr.entityD};
- int aPtInd = 0;
- int aEntInd = 0;
-
- std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
- std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
- for (; anIt != anEntities.end(); ++anIt) {
- isUpdated = update(*anIt) || isUpdated;
-
- Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
- if ((*anIt)->type() == ENTITY_POINT) {
- if (*(aPnts[aPtInd]) != anID) {
- *(aPnts[aPtInd]) = anID;
- isUpdated = true;
- }
- ++aPtInd;
- } else {
- if (*(anEnts[aEntInd]) != anID) {
- *(anEnts[aEntInd]) = anID;
- isUpdated = true;
- }
- ++aEntInd;
- }
- }
-
- // update constraint itself (do not update constraints Multi)
- if (aSlvsConstr.type != SLVS_C_MULTI_ROTATION && aSlvsConstr.type != SLVS_C_MULTI_TRANSLATION) {
- if (aSlvsConstr.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
- aSlvsConstr.wrkpl = myWorkplaneID;
- if (aSlvsConstr.group == SLVS_G_UNKNOWN)
- aSlvsConstr.group = (Slvs_hGroup)myGroupID;
- Slvs_hConstraint aConstrID = updateConstraint(aSlvsConstr);
- if (aSlvsConstr.h == SLVS_C_UNKNOWN) {
- aConstraint->changeConstraint() = getConstraint(aConstrID);
- isUpdated = true;
- }
- }
- return isUpdated;
-}
-
-bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
-{
- bool isUpdated = false;
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
- Slvs_Entity aSlvsEnt = getEntity((Slvs_hEntity)anEntity->id());
- if (aSlvsEnt.h == SLVS_E_UNKNOWN)
- aSlvsEnt = anEntity->entity();
-
- std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::iterator aPIt;
- // if the entity is an attribute, need to update its coordinates
- if (anEntity->baseAttribute()) {
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
- EntityWrapperPtr anUpdAttr = aBuilder->createAttribute(anEntity->baseAttribute(), GID_UNKNOWN);
- if (anUpdAttr) {
- std::list<ParameterWrapperPtr> anUpdParams = anUpdAttr->parameters();
- std::list<ParameterWrapperPtr>::iterator anUpdIt = anUpdParams.begin();
- for (aPIt = aParams.begin(); aPIt != aParams.end() && anUpdIt != anUpdParams.end();
- ++aPIt, ++anUpdIt) {
- (*aPIt)->update(*anUpdIt);
- }
- }
- }
-
- // update parameters
- int anInd = 0;
- for (aPIt = aParams.begin(); aPIt != aParams.end(); ++aPIt, ++anInd) {
- assert(anInd < 4);
- isUpdated = update(*aPIt) || isUpdated;
- if (aSlvsEnt.param[anInd] != (Slvs_hEntity)(*aPIt)->id()) {
- isUpdated = true;
- aSlvsEnt.param[anInd] = (Slvs_hEntity)(*aPIt)->id();
- }
- }
-
- // update sub-entities
- std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
- for (anInd = 0; aSIt != aSubEntities.end(); ++aSIt, ++anInd) {
- assert(anInd < 4);
- isUpdated = update(*aSIt) || isUpdated;
-
- Slvs_hEntity anID = Slvs_hEntity((*aSIt)->id());
- if ((*aSIt)->type() == ENTITY_NORMAL)
- aSlvsEnt.normal = anID;
- else if ((*aSIt)->type() == ENTITY_SCALAR)
- aSlvsEnt.distance = anID;
- else if (aSlvsEnt.point[anInd] != anID) {
- aSlvsEnt.point[anInd] = anID;
- isUpdated = true;
- }
- }
-
- // update entity itself
- if (aSlvsEnt.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
- aSlvsEnt.wrkpl = myWorkplaneID;
- if (aSlvsEnt.group == SLVS_G_UNKNOWN)
- aSlvsEnt.group = (Slvs_hGroup)myGroupID;
- Slvs_hEntity anEntID = updateEntity(aSlvsEnt);
- if (aSlvsEnt.h == SLVS_E_UNKNOWN) {
- anEntity->changeEntity() = getEntity(anEntID);
- isUpdated = true;
-
- if (anEntity->type() == ENTITY_SKETCH)
- storeWorkplane(anEntity);
- }
- return isUpdated;
-}
-
-bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr& theParameter)
-{
- std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aParameter =
- std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theParameter);
- const Slvs_Param& aParam = getParameter((Slvs_hParam)aParameter->id());
- if (aParam.h != SLVS_E_UNKNOWN && fabs(aParam.val - aParameter->value()) < tolerance)
- return false;
- Slvs_Param aParamToUpd = aParameter->parameter();
- if (aParamToUpd.group == SLVS_G_UNKNOWN)
- aParamToUpd.group = aParameter->isParametric() ? (Slvs_hGroup)GID_OUTOFGROUP : (Slvs_hGroup)myGroupID;
-//// else if (aParameter->isParametric() && aParamToUpd.group != (Slvs_hGroup)GID_OUTOFGROUP)
-//// aParameter->setGroup(GID_OUTOFGROUP);
- Slvs_hParam anID = updateParameter(aParamToUpd);
- if (aParam.h == SLVS_E_UNKNOWN) // new parameter
- aParameter->changeParameter() = getParameter(anID);
- return true;
-}
-
-void SolveSpaceSolver_Storage::storeWorkplane(EntityWrapperPtr theSketch)
-{
- myWorkplaneID = (Slvs_hEntity)theSketch->id();
-
- // Update sub-entities of the sketch
- std::list<EntityWrapperPtr> aSubEntities = theSketch->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
- for (; aSIt != aSubEntities.end(); ++aSIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSub =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSIt);
- aSub->changeEntity().wrkpl = myWorkplaneID;
- }
-
- // Update all stored entities
- std::vector<Slvs_Entity>::iterator anIt = myEntities.begin();
- for (; anIt != myEntities.end(); ++anIt)
- anIt->wrkpl = myWorkplaneID;
-}
-
-void SolveSpaceSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
-{
- std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
- for (; aPIt != aParams.end(); ++aPIt)
- changeGroup(*aPIt, theGroup);
-
- std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++aSIt)
- changeGroup(*aSIt, theGroup);
-
- if (theEntity->group() != theGroup) {
- theEntity->setGroup(theGroup);
- int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- myEntities[aPos].group = (Slvs_hGroup)theGroup;
- setNeedToResolve(true);
- }
- }
-}
-
-void SolveSpaceSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
-{
- GroupID aGroup = theGroup;
- if (theParam->isParametric())
- aGroup = GID_OUTOFGROUP;
- if (theParam->group() == aGroup)
- return;
-
- theParam->setGroup(aGroup);
- int aPos = Search((Slvs_hParam)theParam->id(), myParameters);
- if (aPos >= 0 && aPos < (int)myParameters.size()) {
- myParameters[aPos].group = (Slvs_hGroup)aGroup;
- setNeedToResolve(true);
- }
-}
-
-void SolveSpaceSolver_Storage::addCoincidentPoints(
- EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
-{
- if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
- return;
-
- // Search available coincidence
- CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(theMaster);
- CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(theSlave);
- if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) {
- // try to find master and slave points in the lists of slaves of already existent coincidences
- CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
- for (; anIt != myCoincidentPoints.end(); ++anIt) {
- if (anIt->second.find(theMaster) != anIt->second.end())
- aMasterFound = anIt;
- else if (anIt->second.find(theSlave) != anIt->second.end())
- aSlaveFound = anIt;
-
- if (aMasterFound != myCoincidentPoints.end() && aSlaveFound != myCoincidentPoints.end())
- break;
- }
- }
-
- if (aMasterFound == myCoincidentPoints.end()) {
- // create new group
- myCoincidentPoints[theMaster] = std::set<EntityWrapperPtr>();
- aMasterFound = myCoincidentPoints.find(theMaster);
- } else if (aMasterFound == aSlaveFound)
- return; // already coincident
-
- if (aSlaveFound != myCoincidentPoints.end()) {
- // A slave has been found, we need to attach all points coincident with it to the new master
- std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
- aNewSlaves.insert(aSlaveFound->first);
- myCoincidentPoints.erase(aSlaveFound);
-
- std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
- for (; aSlIt != aNewSlaves.end(); ++aSlIt)
- addCoincidentPoints(theMaster, *aSlIt);
- } else {
- // Update the slave if it was used in constraints and features
- replaceInFeatures(theSlave, theMaster);
- replaceInConstraints(theSlave, theMaster);
-
- // Remove slave entity
- removeEntity((Slvs_hEntity)theSlave->id());
-
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointMaster =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMaster);
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointSlave =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theSlave);
- aPointSlave->changeEntity() = aPointMaster->entity();
- aPointSlave->setParameters(aPointMaster->parameters());
-
- aMasterFound->second.insert(theSlave);
- }
-}
-
-void SolveSpaceSolver_Storage::replaceInFeatures(
- EntityWrapperPtr theSource, EntityWrapperPtr theDest)
-{
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator anIt = myFeatureMap.begin();
- for (; anIt != myFeatureMap.end(); ++anIt) {
- bool isUpdated = false;
- std::list<EntityWrapperPtr> aSubs = anIt->second->subEntities();
- std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
- for (; aSubIt != aSubs.end(); ++aSubIt)
- if ((*aSubIt)->id() == theSource->id()) {
- (*aSubIt)->update(theDest);
- isUpdated = true;
- }
-
- if (!isUpdated)
- continue;
-
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aWrapper =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(anIt->second);
- // update SolveSpace entity
- Slvs_Entity anEnt = aWrapper->entity();
- for (int i = 0; i < 4; ++i)
- if (anEnt.point[i] == (Slvs_hEntity)theSource->id())
- anEnt.point[i] = (Slvs_hEntity)theDest->id();
- anEnt.h = updateEntity(anEnt);
- aWrapper->changeEntity() = anEnt;
-
- // update sub-entities
- aWrapper->setSubEntities(aSubs);
- }
-}
-
-void SolveSpaceSolver_Storage::replaceInConstraints(
- EntityWrapperPtr theSource, EntityWrapperPtr theDest)
-{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- anIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCIt;
- for (; anIt != myConstraintMap.end(); ++anIt)
- for (aCIt = anIt->second.begin(); aCIt != anIt->second.end(); ++aCIt) {
- // Do not process coincidence between points
- // (these constraints are stored to keep the structure of constraints).
- if ((*aCIt)->type() == CONSTRAINT_PT_PT_COINCIDENT)
- continue;
-
- bool isUpdated = false;
- std::list<EntityWrapperPtr> aSubs = (*aCIt)->entities();
- std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
- for (; aSubIt != aSubs.end(); ++aSubIt)
- if ((*aSubIt)->id() == theSource->id()) {
- (*aSubIt)->update(theDest);
- isUpdated = true;
- }
-
- if (!isUpdated)
- continue;
-
- std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aWrapper =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(*aCIt);
- // change constraint entities
- Slvs_Constraint aConstr = aWrapper->constraint();
- if (aConstr.ptA == (Slvs_hEntity)theSource->id())
- aConstr.ptA = (Slvs_hEntity)theDest->id();
- if (aConstr.ptB == (Slvs_hEntity)theSource->id())
- aConstr.ptB = (Slvs_hEntity)theDest->id();
-
- // check the constraint is duplicated
- std::vector<Slvs_Constraint>::const_iterator aSlvsCIt = myConstraints.begin();
- for (; aSlvsCIt != myConstraints.end(); ++aSlvsCIt)
- if (aConstr.h != aSlvsCIt->h &&
- aConstr.type == aSlvsCIt->type &&
- aConstr.ptA == aSlvsCIt->ptA && aConstr.ptB == aSlvsCIt->ptB &&
- aConstr.entityA == aSlvsCIt->entityA && aConstr.entityB == aSlvsCIt->entityB &&
- aConstr.entityC == aSlvsCIt->entityC && aConstr.entityD == aSlvsCIt->entityD) {
- removeConstraint(aConstr.h);
- aConstr = *aSlvsCIt;
- break;
- }
-
- if (aSlvsCIt != myConstraints.end()) {
- // constraint is duplicated, search its wrapper to add the mapping
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- anIt2 = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCIt2;
- for (; anIt2 != myConstraintMap.end(); ++anIt2)
- for (aCIt2 = anIt2->second.begin(); aCIt2 != anIt2->second.end(); ++aCIt2)
- if ((Slvs_hConstraint)(*aCIt2)->id() == aConstr.h) {
- addSameConstraints(*aCIt2, aWrapper);
- break;
- }
- } else
- aConstr.h = updateConstraint(aConstr);
- aWrapper->changeConstraint() = aConstr;
-
- // update sub-entities
- aWrapper->setEntities(aSubs);
- }
-}
-
-void SolveSpaceSolver_Storage::addSameConstraints(ConstraintWrapperPtr theConstraint1,
- ConstraintWrapperPtr theConstraint2)
-{
- SameConstraintMap::iterator anIt = myEqualConstraints.begin();
- for (; anIt != myEqualConstraints.end(); ++anIt) {
- if (anIt->find(theConstraint1) != anIt->end()) {
- anIt->insert(theConstraint2);
- return;
- }
- else if (anIt->find(theConstraint2) != anIt->end()) {
- anIt->insert(theConstraint1);
- return;
- }
- }
- // group not found => create new one
- std::set<ConstraintWrapperPtr> aNewGroup;
- aNewGroup.insert(theConstraint1);
- aNewGroup.insert(theConstraint2);
- myEqualConstraints.push_back(aNewGroup);
-}
-
-
-EntityWrapperPtr SolveSpaceSolver_Storage::calculateMiddlePoint(
- EntityWrapperPtr theBase, double theCoeff)
-{
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
-
- std::shared_ptr<GeomAPI_XY> aMidPoint;
- if (theBase->type() == ENTITY_LINE) {
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
- const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 2; ++i, ++anIt)
- aPoints[i] = aBuilder->point(*anIt);
- aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
- aPoints[1]->xy()->multiplied(theCoeff));
- }
- else if (theBase->type() == ENTITY_ARC) {
- double theX, theY;
- double anArcPoint[3][2];
- const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 3; ++i, ++anIt) {
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
- anArcPoint[i][0] = aPoint->x();
- anArcPoint[i][1] = aPoint->y();
- }
- // project last point of arc on the arc
- double x = anArcPoint[1][0] - anArcPoint[0][0];
- double y = anArcPoint[1][1] - anArcPoint[0][1];
- double aRad = sqrt(x*x + y*y);
- x = anArcPoint[2][0] - anArcPoint[0][0];
- y = anArcPoint[2][1] - anArcPoint[0][1];
- double aNorm = sqrt(x*x + y*y);
- if (aNorm >= tolerance) {
- anArcPoint[2][0] = x * aRad / aNorm;
- anArcPoint[2][1] = y * aRad / aNorm;
- }
- anArcPoint[1][0] -= anArcPoint[0][0];
- anArcPoint[1][1] -= anArcPoint[0][1];
- if (theCoeff < tolerance) {
- theX = anArcPoint[0][0] + anArcPoint[1][0];
- theY = anArcPoint[0][1] + anArcPoint[1][1];
- } else if (1 - theCoeff < tolerance) {
- theX = anArcPoint[0][0] + anArcPoint[2][0];
- theY = anArcPoint[0][1] + anArcPoint[2][1];
- } else {
- std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
- std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
- double anAngle = aStartDir->angle(aEndDir);
- if (anAngle < 0)
- anAngle += 2.0 * PI;
- anAngle *= theCoeff;
- double aCos = cos(anAngle);
- double aSin = sin(anAngle);
- theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
- theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
- }
- aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
- }
-
- if (!aMidPoint)
- return EntityWrapperPtr();
-
- std::list<ParameterWrapperPtr> aParameters;
- Slvs_Param aParam1 = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, aMidPoint->x());
- aParam1.h = addParameter(aParam1);
- aParameters.push_back(ParameterWrapperPtr(new SolveSpaceSolver_ParameterWrapper(aParam1)));
- Slvs_Param aParam2 = Slvs_MakeParam(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID, aMidPoint->y());
- aParam2.h = addParameter(aParam2);
- aParameters.push_back(ParameterWrapperPtr(new SolveSpaceSolver_ParameterWrapper(aParam2)));
- // Create entity (parameters are not filled)
- Slvs_Entity anEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, (Slvs_hGroup)myGroupID,
- (Slvs_hEntity)myWorkplaneID, aParam1.h, aParam2.h);
- anEntity.h = addEntity(anEntity);
-
- EntityWrapperPtr aResult(new SolveSpaceSolver_EntityWrapper(AttributePtr(), anEntity));
- aResult->setParameters(aParameters);
- return aResult;
-}
-
-
-
-
-
-
-Slvs_hParam SolveSpaceSolver_Storage::addParameter(const Slvs_Param& theParam)
-{
- if (theParam.h > 0 && theParam.h <= myParamMaxID) {
- // parameter is already used, rewrite it
- return updateParameter(theParam);
- }
-
- Slvs_Param aParam = theParam;
- if (aParam.h > myParamMaxID)
- myParamMaxID = aParam.h;
- else
- aParam.h = ++myParamMaxID;
- myParameters.push_back(aParam);
- myNeedToResolve = true;
- return aParam.h;
-}
-
-Slvs_hParam SolveSpaceSolver_Storage::updateParameter(const Slvs_Param& theParam)
-{
- if (theParam.h > 0 && theParam.h <= myParamMaxID) {
- // parameter already used, rewrite it
- int aPos = Search(theParam.h, myParameters);
- if (aPos >= 0 && aPos < (int)myParameters.size()) {
- if (IsNotEqual(myParameters[aPos], theParam))
- myUpdatedParameters.insert(theParam.h);
- myParameters[aPos] = theParam;
- return theParam.h;
- }
- }
-
- // Parameter is not found, add new one
- Slvs_Param aParam = theParam;
- aParam.h = 0;
- return addParameter(aParam);
-}
-
-bool SolveSpaceSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
-{
- int aPos = Search(theParamID, myParameters);
- if (aPos >= 0 && aPos < (int)myParameters.size()) {
- // Firstly, search the parameter is not used elsewhere
- std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
- for (; anEntIter != myEntities.end(); anEntIter++) {
- for (int i = 0; i < 4; i++)
- if (anEntIter->param[i] == theParamID)
- return false;
- }
- // Remove parameter
- myParameters.erase(myParameters.begin() + aPos);
- myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
- myNeedToResolve = true;
-//// myRemovedParameters.insert(theParamID);
- return true;
- }
-//// else if (myRemovedParameters.find(theParamID) != myRemovedParameters.end())
-//// return true;
- return true;
-}
-
-const Slvs_Param& SolveSpaceSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
-{
- int aPos = Search(theParamID, myParameters);
- if (aPos >= 0 && aPos < (int)myParameters.size())
- return myParameters[aPos];
-
- // Parameter is not found, return empty object
- static Slvs_Param aDummy;
- aDummy.h = 0;
- return aDummy;
-}
-
-
-Slvs_hEntity SolveSpaceSolver_Storage::addEntity(const Slvs_Entity& theEntity)
-{
- if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
- // Entity is already used, rewrite it
- return updateEntity(theEntity);
- }
-
- Slvs_Entity aEntity = theEntity;
- if (aEntity.h > myEntityMaxID)
- myEntityMaxID = aEntity.h;
- else
- aEntity.h = ++myEntityMaxID;
- myEntities.push_back(aEntity);
- myNeedToResolve = true;
- return aEntity.h;
-}
-
-Slvs_hEntity SolveSpaceSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
-{
- if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
- // Entity already used, rewrite it
- int aPos = Search(theEntity.h, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
- myEntities[aPos] = theEntity;
- return theEntity.h;
- }
- }
-
- // Entity is not found, add new one
- Slvs_Entity aEntity = theEntity;
- aEntity.h = 0;
- return addEntity(aEntity);
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
-{
- bool aResult = true;
- int aPos = Search(theEntityID, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- // Firstly, check the entity and its attributes is not used elsewhere
- std::set<Slvs_hEntity> anEntAndSubs;
- anEntAndSubs.insert(theEntityID);
- for (int i = 0; i < 4; i++)
- if (myEntities[aPos].point[i] != SLVS_E_UNKNOWN)
- anEntAndSubs.insert(myEntities[aPos].point[i]);
-
- std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
- for (; anEntIter != myEntities.end(); anEntIter++) {
- if (anEntAndSubs.find(anEntIter->h) != anEntAndSubs.end())
- continue;
- for (int i = 0; i < 4; i++)
- if (anEntAndSubs.find(anEntIter->point[i]) != anEntAndSubs.end())
- return false;
- if (anEntAndSubs.find(anEntIter->distance) != anEntAndSubs.end())
- return false;
- }
- std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++) {
- Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
- aConstrIter->entityA, aConstrIter->entityB,
- aConstrIter->entityC, aConstrIter->entityD};
- for (int i = 0; i < 6; i++)
- if (anEntAndSubs.find(anEntIDs[i]) != anEntAndSubs.end())
- return false;
- }
- // The entity is not used, remove it and its parameters
- Slvs_Entity anEntity = myEntities[aPos];
- myEntities.erase(myEntities.begin() + aPos);
- myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
- if (anEntity.distance != SLVS_E_UNKNOWN)
- aResult = aResult && removeParameter(anEntity.distance);
- for (int i = 0; i < 4; i++)
- if (anEntity.param[i] != SLVS_E_UNKNOWN)
- aResult = removeParameter(anEntity.param[i]) && aResult;
- for (int i = 0; i < 4; i++)
- if (anEntity.point[i] != SLVS_E_UNKNOWN)
- aResult = removeEntity(anEntity.point[i]) && aResult;
- myNeedToResolve = true;
-//// myRemovedEntities.insert(theEntityID);
-//// if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
-//// removeCoincidentPoint(theEntityID);
- }
-//// else if (myRemovedEntities.find(theEntityID) != myRemovedEntities.end())
-//// return true;
- return aResult;
-}
-
-void SolveSpaceSolver_Storage::removeUnusedEntities()
-{
- std::set<Slvs_hEntity> anUnusedEntities;
- std::vector<Slvs_Entity>::const_iterator aEIt = myEntities.begin();
- for (; aEIt != myEntities.end(); ++aEIt) {
- if (aEIt->h == aEIt->wrkpl) {
- // don't remove workplane
- anUnusedEntities.erase(aEIt->point[0]);
- anUnusedEntities.erase(aEIt->normal);
- continue;
- }
- anUnusedEntities.insert(aEIt->h);
- }
-
- std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
- for (; aCIt != myConstraints.end(); ++aCIt) {
- Slvs_hEntity aSubs[6] = {
- aCIt->entityA, aCIt->entityB,
- aCIt->entityC, aCIt->entityD,
- aCIt->ptA, aCIt->ptB};
- for (int i = 0; i < 6; i++) {
- if (aSubs[i] != SLVS_E_UNKNOWN) {
- anUnusedEntities.erase(aSubs[i]);
- int aPos = Search(aSubs[i], myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- for (int j = 0; j < 4; j++)
- if (myEntities[aPos].point[j] != SLVS_E_UNKNOWN)
- anUnusedEntities.erase(myEntities[aPos].point[j]);
- if (myEntities[aPos].distance != SLVS_E_UNKNOWN)
- anUnusedEntities.erase(myEntities[aPos].distance);
- }
- }
- }
- }
-
- std::set<Slvs_hEntity>::const_iterator anEntIt = anUnusedEntities.begin();
- while (anEntIt != anUnusedEntities.end()) {
- int aPos = Search(*anEntIt, myEntities);
- if (aPos < 0 && aPos >= (int)myEntities.size())
- continue;
- Slvs_Entity anEntity = myEntities[aPos];
- // Remove entity if and only if all its parameters unused
- bool isUsed = false;
- if (anEntity.distance != SLVS_E_UNKNOWN &&
- anUnusedEntities.find(anEntity.distance) == anUnusedEntities.end())
- isUsed = true;
- for (int i = 0; i < 4 && !isUsed; i++)
- if (anEntity.point[i] != SLVS_E_UNKNOWN &&
- anUnusedEntities.find(anEntity.point[i]) == anUnusedEntities.end())
- isUsed = true;
- if (isUsed) {
- anUnusedEntities.erase(anEntity.distance);
- for (int i = 0; i < 4; i++)
- if (anEntity.point[i] != SLVS_E_UNKNOWN)
- anUnusedEntities.erase(anEntity.point[i]);
- std::set<Slvs_hEntity>::iterator aRemoveIt = anEntIt++;
- anUnusedEntities.erase(aRemoveIt);
- continue;
- }
- ++anEntIt;
- }
-
- for (anEntIt = anUnusedEntities.begin(); anEntIt != anUnusedEntities.end(); ++anEntIt) {
- int aPos = Search(*anEntIt, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- // Remove entity and its parameters
- Slvs_Entity anEntity = myEntities[aPos];
- myEntities.erase(myEntities.begin() + aPos);
- myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
- if (anEntity.distance != SLVS_E_UNKNOWN)
- removeParameter(anEntity.distance);
- for (int i = 0; i < 4; i++)
- if (anEntity.param[i] != SLVS_E_UNKNOWN)
- removeParameter(anEntity.param[i]);
- for (int i = 0; i < 4; i++)
- if (anEntity.point[i] != SLVS_E_UNKNOWN)
- removeEntity(anEntity.point[i]);
-//// myRemovedEntities.insert(*anEntIt);
-//// if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
-//// removeCoincidentPoint(*anEntIt);
- }
- }
-
- if (!anUnusedEntities.empty())
- myNeedToResolve = true;
-}
-
-bool SolveSpaceSolver_Storage::isUsedByConstraints(const Slvs_hEntity& theEntityID) const
-{
- std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
- for (; aCIt != myConstraints.end(); ++aCIt) {
- Slvs_hEntity aSubs[6] = {
- aCIt->entityA, aCIt->entityB,
- aCIt->entityC, aCIt->entityD,
- aCIt->ptA, aCIt->ptB};
- for (int i = 0; i < 6; i++)
- if (aSubs[i] != SLVS_E_UNKNOWN && aSubs[i] == theEntityID)
- return true;
- }
- return false;
-}
-
-const Slvs_Entity& SolveSpaceSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
-{
- int aPos = Search(theEntityID, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size())
- return myEntities[aPos];
-
- // Entity is not found, return empty object
- static Slvs_Entity aDummy;
- aDummy.h = SLVS_E_UNKNOWN;
- return aDummy;
-}
-
-Slvs_hEntity SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theCopied)
-{
- int aPos = Search(theCopied, myEntities);
- if (aPos < 0 || aPos >= (int)myEntities.size())
- return SLVS_E_UNKNOWN;
-
- Slvs_Entity aCopy = myEntities[aPos];
- aCopy.h = SLVS_E_UNKNOWN;
- int i = 0;
- while (aCopy.point[i] != SLVS_E_UNKNOWN) {
- aCopy.point[i] = copyEntity(aCopy.point[i]);
- i++;
- }
- if (aCopy.param[0] != SLVS_E_UNKNOWN) {
- aPos = Search(aCopy.param[0], myParameters);
- i = 0;
- while (aCopy.param[i] != SLVS_E_UNKNOWN) {
- Slvs_Param aNewParam = myParameters[aPos];
- aNewParam.h = SLVS_E_UNKNOWN;
- aCopy.param[i] = addParameter(aNewParam);
- i++;
- aPos++;
- }
- }
- return addEntity(aCopy);
-}
-
-void SolveSpaceSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo)
-{
- int aPosFrom = Search(theFrom, myEntities);
- int aPosTo = Search(theTo, myEntities);
- if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() ||
- aPosTo < 0 || aPosTo >= (int)myEntities.size())
- return;
-
- Slvs_Entity aEntFrom = myEntities[aPosFrom];
- Slvs_Entity aEntTo = myEntities[aPosTo];
- int i = 0;
- while (aEntFrom.point[i] != SLVS_E_UNKNOWN) {
- copyEntity(aEntFrom.point[i], aEntTo.point[i]);
- i++;
- }
- if (aEntFrom.param[0] != SLVS_E_UNKNOWN) {
- aPosFrom = Search(aEntFrom.param[0], myParameters);
- aPosTo = Search(aEntTo.param[0], myParameters);
- i = 0;
- while (aEntFrom.param[i] != SLVS_E_UNKNOWN) {
- myParameters[aPosTo++].val = myParameters[aPosFrom++].val;
- i++;
- }
- }
-}
-
-
-bool SolveSpaceSolver_Storage::isPointFixed(
- const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
-{
- // Search the set of coincident points
- std::set<Slvs_hEntity> aCoincident;
- aCoincident.insert(thePointID);
-//// std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
-//// for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
-//// if (aCPIter->find(thePointID) != aCPIter->end()) {
-//// aCoincident = *aCPIter;
-//// break;
-//// }
-
- // Check whether one of coincident points is out-of-group
- std::set<Slvs_hEntity>::const_iterator aCoincIt = aCoincident.begin();
- for (; aCoincIt != aCoincident.end(); ++aCoincIt) {
- Slvs_Entity aPoint = getEntity(*aCoincIt);
- if (aPoint.group == SLVS_G_OUTOFGROUP)
- return true;
- }
-
- // Search the Rigid constraint
- theFixed = SLVS_C_UNKNOWN;
- std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++)
- if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
- aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
- theFixed = aConstrIter->h;
- if (aConstrIter->ptA == thePointID)
- return true;
- }
- if (theFixed != SLVS_C_UNKNOWN)
- return true;
-
- if (theAccurate) {
- // Try to find the fixed entity which uses such point or its coincidence
- std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
- for (; anEntIter != myEntities.end(); anEntIter++) {
- for (int i = 0; i < 4; i++) {
- Slvs_hEntity aPt = anEntIter->point[i];
- if (aPt != SLVS_E_UNKNOWN &&
- (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
- if (isEntityFixed(anEntIter->h, true))
- return true;
- }
- }
- }
- }
- return SLVS_E_UNKNOWN;
-}
-
-bool SolveSpaceSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
-{
- int aPos = Search(theEntityID, myEntities);
- if (aPos < 0 || aPos >= (int)myEntities.size())
- return false;
-
- // Firstly, find how many points are under Rigid constraint
- int aNbFixed = 0;
- for (int i = 0; i < 4; i++) {
- Slvs_hEntity aPoint = myEntities[aPos].point[i];
- if (aPoint == SLVS_E_UNKNOWN)
- continue;
-
- std::set<Slvs_hEntity> aCoincident;
- aCoincident.insert(aPoint);
-//// std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
-//// for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
-//// if (aCPIter->find(aPoint) != aCPIter->end()) {
-//// aCoincident = *aCPIter;
-//// break;
-//// }
-
- // Search the Rigid constraint
- std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++)
- if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
- aCoincident.find(aConstrIter->ptA) != aCoincident.end())
- aNbFixed++;
- }
-
- std::list<Slvs_Constraint> aList;
- std::list<Slvs_Constraint>::iterator anIt;
- Slvs_hConstraint aTempID; // used in isPointFixed() method
-
- if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
- if (aNbFixed == 2)
- return true;
- else if (aNbFixed == 0 || !theAccurate)
- return false;
- // Additional check (the line may be fixed if it is used by different constraints):
- // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
- aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
- break;
- if (anIt != aList.end()) {
- aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
- aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
- Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
- if (isEntityFixed(anOther, false))
- return true;
- }
- }
- // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints
- aList = getConstraintsByType(SLVS_C_PARALLEL);
- aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
- aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
- aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
- Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
- if (isEntityFixed(anOther, false))
- break;
- }
- if (anIt != aList.end()) {
- aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
- (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
- return true;
- }
- // 3. Another verifiers ...
- } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
- if (aNbFixed == 0)
- return false;
- // Search for Diameter constraint
- aList = getConstraintsByType(SLVS_C_DIAMETER);
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID)
- return true;
- if (!theAccurate)
- return false;
- // Additional check (the circle may be fixed if it is used by different constraints):
- // 1. The circle is used in Equal constraint and another entity is fixed
- aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
- Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
- if (isEntityFixed(anOther, false))
- return true;
- }
- // 2. Another verifiers ...
- } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
- if (aNbFixed > 2)
- return true;
- else if (aNbFixed <= 1)
- return false;
- // Search for Diameter constraint
- aList = getConstraintsByType(SLVS_C_DIAMETER);
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID)
- return true;
- if (!theAccurate)
- return false;
- // Additional check (the arc may be fixed if it is used by different constraints):
- // 1. The arc is used in Equal constraint and another entity is fixed
- aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
- aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
- for (anIt = aList.begin(); anIt != aList.end(); anIt++)
- if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
- Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
- if (isEntityFixed(anOther, false))
- return true;
- }
- // 2. Another verifiers ...
- }
- return false;
-}
-
-
-Slvs_hConstraint SolveSpaceSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
-{
- if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
- // Constraint is already used, rewrite it
- return updateConstraint(theConstraint);
- }
-
- Slvs_Constraint aConstraint = theConstraint;
-
- // Find a constraint with same type uses same arguments to show user overconstraint situation
- std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
- for (; aCIt != myConstraints.end(); aCIt++) {
- if (aConstraint.type != aCIt->type)
- continue;
- if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
- aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
- aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
- myDuplicatedConstraint = true;
- }
-
- if (aConstraint.h > myConstrMaxID)
- myConstrMaxID = aConstraint.h;
- else
- aConstraint.h = ++myConstrMaxID;
- myConstraints.push_back(aConstraint);
- myNeedToResolve = true;
-//// if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
-//// addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
- return aConstraint.h;
-}
-
-Slvs_hConstraint SolveSpaceSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
-{
- if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
- // Constraint already used, rewrite it
- int aPos = Search(theConstraint.h, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size()) {
- myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
- myConstraints[aPos] = theConstraint;
-//// if (theConstraint.type == SLVS_C_POINTS_COINCIDENT)
-//// addCoincidentPoints(theConstraint.ptA, theConstraint.ptB);
- return theConstraint.h;
- }
- }
-
- // Constraint is not found, add new one
- Slvs_Constraint aConstraint = theConstraint;
- aConstraint.h = 0;
- return addConstraint(aConstraint);
-}
-
-bool SolveSpaceSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
-{
- bool aResult = true;
- int aPos = Search(theConstraintID, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size()) {
- Slvs_Constraint aConstraint = myConstraints[aPos];
- myConstraints.erase(myConstraints.begin() + aPos);
- myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
- myNeedToResolve = true;
-//// myRemovedConstraints.insert(theConstraintID);
-//// if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
-//// removeCoincidence(aConstraint);
-
- // Remove all entities
- Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
- aConstraint.entityA, aConstraint.entityB,
- aConstraint.entityC, aConstraint.entityD};
- for (int i = 0; i < 6; i++)
- if (anEntities[i] != SLVS_E_UNKNOWN)
- aResult = removeEntity(anEntities[i]) && aResult;
- // remove temporary fixed point, if available
- if (myFixed == theConstraintID)
- myFixed = SLVS_E_UNKNOWN;
- if (myDuplicatedConstraint) {
- // Check the duplicated constraints are still available
- myDuplicatedConstraint = false;
- std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
- std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
- for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
- for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
- if (anIt1->type != anIt2->type)
- continue;
- if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
- anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
- anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
- myDuplicatedConstraint = true;
- }
- }
- }
-//// else if (myRemovedConstraints.find(theConstraintID) != myRemovedConstraints.end())
-//// return true;
- return aResult;
-}
-
-const Slvs_Constraint& SolveSpaceSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
-{
- int aPos = Search(theConstraintID, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size())
- return myConstraints[aPos];
-
- // Constraint is not found, return empty object
- static Slvs_Constraint aDummy;
- aDummy.h = 0;
- return aDummy;
-}
-
-std::list<Slvs_Constraint> SolveSpaceSolver_Storage::getConstraintsByType(int theConstraintType) const
-{
- std::list<Slvs_Constraint> aResult;
- std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
- for (; aCIter != myConstraints.end(); aCIter++)
- if (aCIter->type == theConstraintType)
- aResult.push_back(*aCIter);
- return aResult;
-}
-
-
-void SolveSpaceSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
-{
- if (myFixed != SLVS_E_UNKNOWN)
- return; // the point is already fixed
- int aPos = Search(theConstraintID, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size())
- myFixed = theConstraintID;
-}
-
-void SolveSpaceSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
-{
- myTemporaryConstraints.insert(theConstraintID);
-}
-
-void SolveSpaceSolver_Storage::removeAllTemporary()
-{
- myTemporaryConstraints.clear();
-}
-
-size_t SolveSpaceSolver_Storage::removeTemporary(size_t theNbConstraints)
-{
- if (myTemporaryConstraints.empty())
- return 0;
- // Search the point-on-line or a non-rigid constraint
- std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
- for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
- int aPos = Search(*aCIt, myConstraints);
- if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
- break;
- std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end(); anIt++)
- if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
- break;
- if (anIt != myConstraints.end())
- break;
- }
- if (aCIt == myTemporaryConstraints.end())
- aCIt = myTemporaryConstraints.begin();
- bool aNewFixed = false;
-
- size_t aNbRemain = theNbConstraints;
- while (aNbRemain > 0 && aCIt != myTemporaryConstraints.end()) {
- aNewFixed = aNewFixed || (*aCIt == myFixed);
- --aNbRemain;
-
- std::set<Slvs_hConstraint>::iterator aRemoveIt = aCIt++;
- removeConstraint(*aRemoveIt);
- myTemporaryConstraints.erase(aRemoveIt);
- if (aCIt == myTemporaryConstraints.end())
- aCIt = myTemporaryConstraints.begin();
- }
-
- if (aNewFixed) {
- for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
- int aPos = Search(*aCIt, myConstraints);
- if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
- myFixed = *aCIt;
- break;
- }
- }
- }
- return myTemporaryConstraints.size();
-}
-
-bool SolveSpaceSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
-{
- return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
-}
-
-
-////void SolveSpaceSolver_Storage::getRemoved(
-//// std::set<Slvs_hParam>& theParameters,
-//// std::set<Slvs_hEntity>& theEntities,
-//// std::set<Slvs_hConstraint>& theConstraints)
-////{
-//// theParameters = myRemovedParameters;
-//// theEntities = myRemovedEntities;
-//// theConstraints = myRemovedConstraints;
-////
-//// myRemovedParameters.clear();
-//// myRemovedEntities.clear();
-//// myRemovedConstraints.clear();
-////}
-
-void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
-{
- std::shared_ptr<SolveSpaceSolver_Solver> aSolver =
- std::dynamic_pointer_cast<SolveSpaceSolver_Solver>(theSolver);
- if (!aSolver)
- return;
-
- if (myConstraints.empty()) {
- // Adjust all arc to place their points correctly
- std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
- for (; anEntIt != myEntities.end(); ++anEntIt)
- if (anEntIt->type == SLVS_E_ARC_OF_CIRCLE)
- adjustArc(*anEntIt);
- }
-
- aSolver->setParameters(myParameters.data(), (int)myParameters.size());
- aSolver->setEntities(myEntities.data(), (int)myEntities.size());
-
- // Copy constraints excluding the fixed one
- std::vector<Slvs_Constraint> aConstraints = myConstraints;
- if (myFixed != SLVS_E_UNKNOWN) {
- Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
- std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
- for (; anIt != aConstraints.end(); anIt++)
- if (anIt->h == myFixed) {
- aFixedPoint = anIt->ptA;
- aConstraints.erase(anIt);
- break;
- }
- // set dragged parameters
- int aPos = Search(aFixedPoint, myEntities);
- aSolver->setDraggedParameters(myEntities[aPos].param);
- }
- aSolver->setConstraints(aConstraints.data(), (int)aConstraints.size());
-}
-
-////void SolveSpaceSolver_Storage::addCoincidentPoints(
-//// const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
-////{
-//// std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
-//// std::vector< std::set<Slvs_hEntity> >::iterator aFoundIter = myCoincidentPoints.end(); // already found coincidence
-//// bool isFound = false;
-//// for (; aCIter != myCoincidentPoints.end(); aCIter++) {
-//// bool isFirstFound = aCIter->find(thePoint1) != aCIter->end();
-//// bool isSecondFound = aCIter->find(thePoint2) != aCIter->end();
-//// isFound = isFound || isFirstFound || isSecondFound;
-//// if (isFirstFound && isSecondFound)
-//// break; // already coincident
-//// else if (isFirstFound || isSecondFound) {
-//// if (aFoundIter != myCoincidentPoints.end()) {
-//// // merge two sets
-//// aFoundIter->insert(aCIter->begin(), aCIter->end());
-//// myCoincidentPoints.erase(aCIter);
-//// break;
-//// } else
-//// aFoundIter = aCIter;
-//// aCIter->insert(thePoint1);
-//// aCIter->insert(thePoint2);
-//// }
-//// }
-//// // coincident points not found
-//// if (!isFound) {
-//// std::set<Slvs_hEntity> aNewSet;
-//// aNewSet.insert(thePoint1);
-//// aNewSet.insert(thePoint2);
-//// myCoincidentPoints.push_back(aNewSet);
-//// }
-////}
-////
-////void SolveSpaceSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint)
-////{
-//// std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
-//// for (; aCIter != myCoincidentPoints.end(); aCIter++)
-//// if (aCIter->find(thePoint) != aCIter->end()) {
-//// aCIter->erase(thePoint);
-//// if (aCIter->size() <= 1)
-//// myCoincidentPoints.erase(aCIter);
-//// break;
-//// }
-////}
-////
-////void SolveSpaceSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence)
-////{
-//// // Find set of coincident points
-//// std::vector< std::set<Slvs_hEntity> >::iterator aCIt = myCoincidentPoints.begin();
-//// for (; aCIt != myCoincidentPoints.end(); ++aCIt)
-//// if (aCIt->find(theCoincidence.ptA) != aCIt->end() ||
-//// aCIt->find(theCoincidence.ptB) != aCIt->end())
-//// break;
-//// if (aCIt == myCoincidentPoints.end())
-//// return;
-////
-//// // Leave only the points which are still coincident
-//// std::set<Slvs_hEntity> aRemainCoincidence;
-//// std::vector<Slvs_Constraint>::const_iterator aConstrIt = myConstraints.begin();
-//// for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
-//// if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT)
-//// continue;
-//// if (aCIt->find(aConstrIt->ptA) != aCIt->end() ||
-//// aCIt->find(aConstrIt->ptB) != aCIt->end()) {
-//// aRemainCoincidence.insert(aConstrIt->ptA);
-//// aRemainCoincidence.insert(aConstrIt->ptB);
-//// }
-//// }
-//// if (aRemainCoincidence.size() <= 1)
-//// myCoincidentPoints.erase(aCIt);
-//// else
-//// aCIt->swap(aRemainCoincidence);
-////}
-////
-////bool SolveSpaceSolver_Storage::isCoincident(
-//// const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-////{
-//// std::vector< std::set<Slvs_hEntity> >::const_iterator aCIter = myCoincidentPoints.begin();
-//// for (; aCIter != myCoincidentPoints.end(); aCIter++)
-//// if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end())
-//// return true;
-//// return false;
-////}
-
-bool SolveSpaceSolver_Storage::isEqual(
- const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
-{
-//// if (isCoincident(thePoint1, thePoint2))
-//// return true;
-
- // Precise checking of coincidence: verify that points have equal coordinates
- int aEnt1Pos = Search(thePoint1, myEntities);
- int aEnt2Pos = Search(thePoint2, myEntities);
- if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
- aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
- double aDist[2];
- int aParamPos;
- for (int i = 0; i < 2; i++) {
- aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
- aDist[i] = myParameters[aParamPos].val;
- aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
- aDist[i] -= myParameters[aParamPos].val;
- }
- if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
- return true;
- }
- return false;
-}
-
-
-std::vector<Slvs_hConstraint> SolveSpaceSolver_Storage::fixEntity(const Slvs_hEntity& theEntity)
-{
- std::vector<Slvs_hConstraint> aNewConstraints;
-
- int aPos = Search(theEntity, myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- switch (myEntities[aPos].type) {
- case SLVS_E_POINT_IN_2D:
- case SLVS_E_POINT_IN_3D:
- fixPoint(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_LINE_SEGMENT:
- fixLine(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_CIRCLE:
- fixCircle(myEntities[aPos], aNewConstraints);
- break;
- case SLVS_E_ARC_OF_CIRCLE:
- fixArc(myEntities[aPos], aNewConstraints);
- break;
- default:
- break;
- }
- }
-
- return aNewConstraints;
-}
-
-void SolveSpaceSolver_Storage::fixPoint(const Slvs_Entity& thePoint,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- Slvs_Constraint aConstraint;
- Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
- bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
- bool isForceUpdate = (isFixed && isTemporary(aConstrID));
- if (!isForceUpdate) { // create new constraint
- if (isFixed) return;
- aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
- 0.0, thePoint.h, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- aConstraint.h = addConstraint(aConstraint);
- theCreated.push_back(aConstraint.h);
- } else { // update already existent constraint
- if (!isFixed || aConstrID == SLVS_E_UNKNOWN)
- return;
- int aPos = Search(aConstrID, myConstraints);
- if (aPos >= 0 && aPos < (int)myConstraints.size())
- myConstraints[aPos].ptA = thePoint.h;
- }
-}
-
-void SolveSpaceSolver_Storage::fixLine(const Slvs_Entity& theLine,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- Slvs_Entity aPoint[2] = {
- getEntity(theLine.point[0]),
- getEntity(theLine.point[1])
- };
-
- Slvs_Constraint anEqual;
- if (isAxisParallel(theLine.h)) {
- // Fix one point and a line length
- Slvs_hConstraint aFixed;
- if (!isPointFixed(theLine.point[0], aFixed, true) &&
- !isPointFixed(theLine.point[1], aFixed, true))
- fixPoint(aPoint[0], theCreated);
- if (!isUsedInEqual(theLine.h, anEqual)) {
- // Check the distance is not set yet
- std::vector<Slvs_Constraint>::const_iterator aDistIt = myConstraints.begin();
- for (; aDistIt != myConstraints.end(); ++aDistIt)
- if ((aDistIt->type == SLVS_C_PT_PT_DISTANCE) &&
- ((aDistIt->ptA == theLine.point[0] && aDistIt->ptB == theLine.point[1]) ||
- (aDistIt->ptA == theLine.point[1] && aDistIt->ptB == theLine.point[0])))
- return;
- // Calculate distance between points on the line
- double aCoords[4];
- for (int i = 0; i < 2; i++)
- for (int j = 0; j < 2; j++) {
- Slvs_Param aParam = getParameter(aPoint[i].param[j]);
- aCoords[2*i+j] = aParam.val;
- }
-
- double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
- (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
- // fix line length
- Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group,
- SLVS_C_PT_PT_DISTANCE, theLine.wrkpl, aLength,
- theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
- aDistance.h = addConstraint(aDistance);
- theCreated.push_back(aDistance.h);
- }
- return;
- }
- else if (isUsedInEqual(theLine.h, anEqual)) {
- // Check another entity of Equal is already fixed
- Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
- if (isEntityFixed(anOtherEntID, true)) {
- // Fix start point of the line (if end point is not fixed yet) ...
- Slvs_hConstraint anEndFixedID = SLVS_E_UNKNOWN;
- bool isFixed = isPointFixed(theLine.point[1], anEndFixedID, true);
- if (isFixed == SLVS_E_UNKNOWN)
- fixPoint(aPoint[0], theCreated);
- // ... and create fixed point lying on this line
- Slvs_hEntity aPointToCopy = anEndFixedID == SLVS_E_UNKNOWN ? theLine.point[1] : theLine.point[0];
- // Firstly, search already fixed point on line
- bool isPonLineFixed = false;
- Slvs_hEntity aFixedPoint;
- std::vector<Slvs_Constraint>::const_iterator aPLIter = myConstraints.begin();
- for (; aPLIter != myConstraints.end() && !isPonLineFixed; ++aPLIter)
- if (aPLIter->type == SLVS_C_PT_ON_LINE && aPLIter->entityA == theLine.h) {
- isPonLineFixed = isPointFixed(aPLIter->ptA, anEndFixedID);
- aFixedPoint = aPLIter->ptA;
- }
-
- if (isPonLineFixed) { // update existent constraint
- copyEntity(aPointToCopy, aFixedPoint);
- } else { // create new constraint
- Slvs_hEntity aCopied = copyEntity(aPointToCopy);
- Slvs_Constraint aPonLine = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theLine.group, SLVS_C_PT_ON_LINE,
- theLine.wrkpl, 0.0, aCopied, SLVS_E_UNKNOWN, theLine.h, SLVS_E_UNKNOWN);
- aPonLine.h = addConstraint(aPonLine);
- theCreated.push_back(aPonLine.h);
- fixPoint(getEntity(aCopied), theCreated);
- }
- return;
- }
- }
-
- // Fix both points
- for (int i = 0; i < 2; i++)
- fixPoint(aPoint[i], theCreated);
-}
-
-void SolveSpaceSolver_Storage::fixCircle(const Slvs_Entity& theCircle,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- bool isFixRadius = true;
- // Verify the arc is under Equal constraint
- Slvs_Constraint anEqual;
- if (isUsedInEqual(theCircle.h, anEqual)) {
- // Check another entity of Equal is already fixed
- Slvs_hEntity anOtherEntID = anEqual.entityA == theCircle.h ? anEqual.entityB : anEqual.entityA;
- if (isEntityFixed(anOtherEntID, true))
- isFixRadius = false;
- }
-
- fixPoint(getEntity(theCircle.point[0]), theCreated);
-
- if (isFixRadius) {
- // Search the radius is already fixed
- std::vector<Slvs_Constraint>::const_iterator aDiamIter = myConstraints.begin();
- for (; aDiamIter != myConstraints.end(); ++aDiamIter)
- if (aDiamIter->type == SLVS_C_DIAMETER && aDiamIter->entityA == theCircle.h)
- return;
-
- // Fix radius of a circle
- const Slvs_Entity& aRadEnt = getEntity(theCircle.distance);
- double aRadius = getParameter(aRadEnt.param[0]).val;
- Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theCircle.group, SLVS_C_DIAMETER,
- theCircle.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theCircle.h, SLVS_E_UNKNOWN);
- aFixedR.h = addConstraint(aFixedR);
- theCreated.push_back(aFixedR.h);
- }
-}
-
-void SolveSpaceSolver_Storage::fixArc(const Slvs_Entity& theArc,
- std::vector<Slvs_hConstraint>& theCreated)
-{
- Slvs_Entity aPoint[3] = {
- getEntity(theArc.point[0]),
- getEntity(theArc.point[1]),
- getEntity(theArc.point[2])
- };
-
- bool isFixRadius = true;
- std::list<Slvs_Entity> aPointsToFix;
- aPointsToFix.push_back(aPoint[1]);
- aPointsToFix.push_back(aPoint[2]);
-
- // Verify the arc is under Equal constraint
- Slvs_Constraint anEqual;
- if (isUsedInEqual(theArc.h, anEqual)) {
- // Check another entity of Equal is already fixed
- Slvs_hEntity anOtherEntID = anEqual.entityA == theArc.h ? anEqual.entityB : anEqual.entityA;
- if (isEntityFixed(anOtherEntID, true)) {
- isFixRadius = false;
- Slvs_Entity anOtherEntity = getEntity(anOtherEntID);
- if (anOtherEntity.type == SLVS_E_LINE_SEGMENT) {
- aPointsToFix.pop_back();
- aPointsToFix.push_back(aPoint[0]);
- }
- }
- }
-
- Slvs_hConstraint aConstrID;
- int aNbPointsToFix = 2; // number of fixed points for the arc
- if (isPointFixed(theArc.point[0], aConstrID, true))
- aNbPointsToFix--;
-
- double anArcPoints[3][2];
- for (int i = 0; i < 3; i++) {
- const Slvs_Entity& aPointOnArc = getEntity(theArc.point[i]);
- for (int j = 0; j < 2; j++)
- anArcPoints[i][j] = getParameter(aPointOnArc.param[j]).val;
- }
-
- // Radius of the arc
- std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(anArcPoints[0][0], anArcPoints[0][1]));
- std::shared_ptr<GeomAPI_Pnt2d> aStart(new GeomAPI_Pnt2d(anArcPoints[1][0], anArcPoints[1][1]));
- double aRadius = aCenter->distance(aStart);
-
- // Update end point of the arc to be on a curve
- std::shared_ptr<GeomAPI_Pnt2d> anEnd(new GeomAPI_Pnt2d(anArcPoints[2][0], anArcPoints[2][1]));
- double aDistance = anEnd->distance(aCenter);
- std::shared_ptr<GeomAPI_XY> aDir = anEnd->xy()->decreased(aCenter->xy());
- if (aDistance < tolerance)
- aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0);
- else
- aDir = aDir->multiplied(aRadius / aDistance);
- double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()};
- const Slvs_Entity& aEndPoint = getEntity(theArc.point[2]);
- for (int i = 0; i < 2; i++) {
- Slvs_Param aParam = getParameter(aEndPoint.param[i]);
- aParam.val = xy[i];
- updateParameter(aParam);
- }
-
- std::list<Slvs_Entity>::iterator aPtIt = aPointsToFix.begin();
- for (; aNbPointsToFix > 0; aPtIt++, aNbPointsToFix--)
- fixPoint(*aPtIt, theCreated);
-
- if (isFixRadius) {
- // Fix radius of the arc
- bool isExists = false;
- std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end() && !isExists; ++anIt)
- if (anIt->type == SLVS_C_DIAMETER && anIt->entityA == theArc.h)
- isExists = true;
- if (!isExists) {
- Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, theArc.group, SLVS_C_DIAMETER,
- theArc.wrkpl, aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, theArc.h, SLVS_E_UNKNOWN);
- aFixedR.h = addConstraint(aFixedR);
- theCreated.push_back(aFixedR.h);
- }
- }
-}
-
-
-bool SolveSpaceSolver_Storage::isAxisParallel(const Slvs_hEntity& theEntity) const
-{
- std::vector<Slvs_Constraint>::const_iterator anIter = myConstraints.begin();
- for (; anIter != myConstraints.end(); anIter++)
- if ((anIter->type == SLVS_C_HORIZONTAL || anIter->type == SLVS_C_VERTICAL) &&
- anIter->entityA == theEntity)
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsedInEqual(
- const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const
-{
- // Check the entity is used in Equal constraint
- std::vector<Slvs_Constraint>::const_iterator anEqIter = myConstraints.begin();
- for (; anEqIter != myConstraints.end(); anEqIter++)
- if ((anEqIter->type == SLVS_C_EQUAL_LENGTH_LINES ||
- anEqIter->type == SLVS_C_EQUAL_LINE_ARC_LEN ||
- anEqIter->type == SLVS_C_EQUAL_RADIUS) &&
- (anEqIter->entityA == theEntity || anEqIter->entityB == theEntity)) {
- theEqual = *anEqIter;
- return true;
- }
- return false;
-}
-
-////bool SolveSpaceSolver_Storage::isNeedToResolve()
-////{
-//// if (myConstraints.empty())
-//// return false;
-////
-//// if (!myNeedToResolve) {
-//// // Verify the updated parameters are used in constraints
-//// std::set<Slvs_hEntity> aPoints;
-//// std::vector<Slvs_Entity>::const_iterator anEntIt = myEntities.begin();
-//// for (; anEntIt != myEntities.end(); ++anEntIt) {
-//// for (int i = 0; i < 4 && anEntIt->param[i] != SLVS_E_UNKNOWN; ++i)
-//// if (myUpdatedParameters.find(anEntIt->param[i]) != myUpdatedParameters.end()) {
-//// aPoints.insert(anEntIt->h);
-//// break;
-//// }
-//// }
-//// std::set<Slvs_hEntity> anEntities = aPoints;
-//// for (anEntIt = myEntities.begin(); anEntIt != myEntities.end(); ++anEntIt) {
-//// for (int i = 0; i < 4 && anEntIt->point[i] != SLVS_E_UNKNOWN; ++i)
-//// if (aPoints.find(anEntIt->point[i]) != aPoints.end()) {
-//// anEntities.insert(anEntIt->h);
-//// break;
-//// }
-//// }
-////
-//// std::vector<Slvs_Constraint>::const_iterator aCIt = myConstraints.begin();
-//// for (; aCIt != myConstraints.end() && !myNeedToResolve; ++aCIt) {
-//// Slvs_hEntity anAttrs[6] =
-//// {aCIt->ptA, aCIt->ptB, aCIt->entityA, aCIt->entityB, aCIt->entityC, aCIt->entityD};
-//// for (int i = 0; i < 6; i++)
-//// if (anAttrs[i] != SLVS_E_UNKNOWN && anEntities.find(anAttrs[i]) != anEntities.end()) {
-//// myNeedToResolve = true;
-//// break;
-//// }
-//// }
-//// }
-////
-//// myUpdatedParameters.clear();
-//// return myNeedToResolve;
-////}
-
-void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint)
-{
- // TODO
-}
-
-bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
-{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
- aFound = myConstraintMap.find(theConstraint);
- if (aFound == myConstraintMap.end())
- return true; // no constraint, already deleted
-
- // Remove constraint
- std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
- myConstraintMap.erase(aFound);
- // Remove SolveSpace constraints
- bool isFullyRemoved = true;
- std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
- while (anIt != aConstrList.end()) {
- if (remove(*anIt)) {
- std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
- aConstrList.erase(aRemoveIt);
- } else {
- isFullyRemoved = false;
- ++anIt;
- }
- }
- if (!isFullyRemoved)
- myConstraintMap[theConstraint] = aConstrList;
- return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
- std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
- for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
- if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt)->isBase(theEntity))
- return true;
- return false;
-}
-
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
- std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
- for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
- if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSubIt)->isBase(theSubEntity))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt)
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, theFeature))
- return true;
- // check attributes
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt)
- if (isUsed(*anIt))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(AttributePtr theAttribute) const
-{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
- anAttribute = aRefAttr->attr();
- }
-
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt)
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, anAttribute))
- return true;
- return false;
-}
-
-
-bool SolveSpaceSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
- if (aFound == myFeatureMap.end())
- return false; // feature not found, nothing to delete
-
- // Check the feature is not used by constraints
- if (isUsed(theFeature))
- return false; // the feature is used, don't remove it
-
- // Remove feature
- EntityWrapperPtr anEntity = aFound->second;
- myFeatureMap.erase(aFound);
- if (remove(anEntity))
- return true;
- // feature is not removed, revert operation
- myFeatureMap[theFeature] = anEntity;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
- std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
- if (aFound == myAttributeMap.end())
- return false; // attribute not found, nothing to delete
-
- // Check the attribute is not used by constraints
- if (isUsed(theAttribute))
- return false; // the attribute is used, don't remove it
- // Check the attribute is not used by other features
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it
- return false;
-
- // Remove attribute
- EntityWrapperPtr anEntity = aFound->second;
- myAttributeMap.erase(aFound);
- if (remove(anEntity))
- return true;
- // attribute is not removed, revert operation
- myAttributeMap[theAttribute] = anEntity;
- return false;
-}
-
-
-bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
-{
- std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<SolveSpaceSolver_ConstraintWrapper>(theConstraint);
-
- // verify whether the constraint has duplicated
- SameConstraintMap::iterator anEqIt = myEqualConstraints.begin();
- for (; anEqIt != myEqualConstraints.end(); ++anEqIt)
- if (anEqIt->find(aConstraint) != anEqIt->end()) {
- anEqIt->erase(aConstraint);
- break;
- }
- if (anEqIt != myEqualConstraints.end())
- return true;
-
- bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id());
-
- std::list<EntityWrapperPtr>::const_iterator anIt = aConstraint->entities().begin();
- for (; anIt != aConstraint->entities().end(); ++anIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
- FeaturePtr aBaseFeature = anEntity->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved = removeEntity(anEntity->baseAttribute()) && isFullyRemoved;
- }
-
- return isFullyRemoved;
-}
-
-bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity)
-{
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
- bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id());
-
- std::list<EntityWrapperPtr>::const_iterator anEntIt = anEntity->subEntities().begin();
- for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSubEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt);
- FeaturePtr aBaseFeature = aSubEntity->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved;
- }
-
- std::list<ParameterWrapperPtr>::const_iterator aParIt = anEntity->parameters().begin();
- for (; aParIt != anEntity->parameters().end(); ++aParIt)
- isFullyRemoved = remove(*aParIt) && isFullyRemoved;
- return isFullyRemoved;
-}
-
-bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
-{
- return removeParameter((Slvs_hParam)theParameter->id());
-}
-
-
-void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
-{
- blockEvents(true);
-
- std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
- std::list<ParameterWrapperPtr> aParams;
- std::list<ParameterWrapperPtr>::const_iterator aParIt;
- for (; anIt != myAttributeMap.end(); ++anIt) {
- // update parameter wrappers and obtain values of attributes
- aParams = anIt->second->parameters();
- double aCoords[3];
- bool isUpd[3] = {false};
- int i = 0;
- for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
- std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aWrapper =
- std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(*aParIt);
- if (!theFixedOnly || aWrapper->group() == GID_OUTOFGROUP || aWrapper->isParametric()) {
- aWrapper->changeParameter().val = getParameter((Slvs_hParam)aWrapper->id()).val;
- aCoords[i] = aWrapper->value();
- isUpd[i] = true;
- }
- }
- if (!isUpd[0] && !isUpd[1] && !isUpd[2])
- continue; // nothing is updated
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
- if (aPoint2D) {
- if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > tolerance) ||
- (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > tolerance)) {
- if (!isUpd[0]) aCoords[0] = aPoint2D->x();
- if (!isUpd[1]) aCoords[1] = aPoint2D->y();
- aPoint2D->setValue(aCoords[0], aCoords[1]);
- }
- continue;
- }
- AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
- if (aScalar) {
- if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > tolerance)
- aScalar->setValue(aCoords[0]);
- continue;
- }
- std::shared_ptr<GeomDataAPI_Point> aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point>(anIt->first);
- if (aPoint) {
- if ((isUpd[0] && fabs(aPoint->x() - aCoords[0]) > tolerance) ||
- (isUpd[1] && fabs(aPoint->y() - aCoords[1]) > tolerance) ||
- (isUpd[2] && fabs(aPoint->z() - aCoords[2]) > tolerance))
- if (!isUpd[0]) aCoords[0] = aPoint->x();
- if (!isUpd[1]) aCoords[1] = aPoint->y();
- if (!isUpd[2]) aCoords[2] = aPoint->z();
- aPoint->setValue(aCoords[0], aCoords[1], aCoords[2]);
- continue;
- }
- }
-
- blockEvents(false);
-}
-
-void SolveSpaceSolver_Storage::verifyFixed()
-{
- std::map<AttributePtr, EntityWrapperPtr>::iterator anAttrIt = myAttributeMap.begin();
- for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
- const std::list<ParameterWrapperPtr>& aParameters = anAttrIt->second->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aParIt = aParameters.begin();
- for (; aParIt != aParameters.end(); ++aParIt)
- if ((*aParIt)->group() == GID_OUTOFGROUP) {
- Slvs_Param aParam = getParameter((Slvs_hParam)(*aParIt)->id());
- if (aParam.group != (Slvs_hParam)GID_OUTOFGROUP) {
- aParam.group = (Slvs_hParam)GID_OUTOFGROUP;
- updateParameter(aParam);
- }
- }
- }
-}
-
-
-void SolveSpaceSolver_Storage::adjustArc(const Slvs_Entity& theArc)
-{
- double anArcPoints[3][2];
- double aDist[3] = {0.0};
- bool isFixed[3] = {false};
- for (int i = 0; i < 3; ++i) {
- Slvs_Entity aPoint = getEntity(theArc.point[i]);
- isFixed[i] = (aPoint.group != (Slvs_hGroup)myGroupID);
- anArcPoints[i][0] = getParameter(aPoint.param[0]).val;
- anArcPoints[i][1] = getParameter(aPoint.param[1]).val;
- if (i > 0) {
- anArcPoints[i][0] -= anArcPoints[0][0];
- anArcPoints[i][1] -= anArcPoints[0][1];
- aDist[i] = sqrt(anArcPoints[i][0] * anArcPoints[i][0] +
- anArcPoints[i][1] * anArcPoints[i][1]);
- }
- }
-
- if (fabs(aDist[1] - aDist[2]) < tolerance)
- return;
-
- int anInd = 2;
- while (anInd > 0 && isFixed[anInd])
- --anInd;
- if (anInd < 1)
- return; // adjust only start or end point of the arc
-
- anArcPoints[anInd][0] /= aDist[anInd];
- anArcPoints[anInd][1] /= aDist[anInd];
-
- Slvs_Entity aPoint = getEntity(theArc.point[anInd]);
- for (int i = 0; i < 2; ++i) {
- Slvs_Param aParam = getParameter(aPoint.param[i]);
- aParam.val = anArcPoints[0][i] + aDist[3-anInd] * anArcPoints[anInd][i];
- updateParameter(aParam);
- }
-}
-
-
-
-
-
-
-
-// ========================================================
-// ========= Auxiliary functions ===============
-// ========================================================
-
-template<typename T>
-int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
-{
- int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
- int aVecSize = theEntities.size();
- if (theEntities.empty())
- return 1;
- while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
- aResIndex--;
- while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
- aResIndex++;
- if (aResIndex == -1 || (aResIndex < aVecSize && theEntities[aResIndex].h != theEntityID))
- aResIndex = aVecSize;
- return aResIndex;
-}
-
-bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
-{
- return fabs(theParam1.val - theParam2.val) > tolerance;
-}
-
-bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
-{
- int i = 0;
- for (; theEntity1.param[i] != 0 && i < 4; i++)
- if (theEntity1.param[i] != theEntity2.param[i])
- return true;
- i = 0;
- for (; theEntity1.point[i] != 0 && i < 4; i++)
- if (theEntity1.point[i] != theEntity2.point[i])
- return true;
- return false;
-}
-
-bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
-{
- return theConstraint1.ptA != theConstraint2.ptA ||
- theConstraint1.ptB != theConstraint2.ptB ||
- theConstraint1.entityA != theConstraint2.entityA ||
- theConstraint1.entityB != theConstraint2.entityB ||
- theConstraint1.entityC != theConstraint2.entityC ||
- theConstraint1.entityD != theConstraint2.entityD ||
- fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SolveSpaceSolver_Storage.h
-// Created: 18 Mar 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SolveSpaceSolver_Storage_H_
-#define SolveSpaceSolver_Storage_H_
-
-#include <SketchSolver_Storage.h>
-#include <SolveSpaceSolver_Solver.h>
-
-#include <list>
-#include <memory>
-#include <set>
-#include <vector>
-
-typedef std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > CoincidentPointsMap;
-typedef std::list< std::set<ConstraintWrapperPtr> > SameConstraintMap;
-
-/** \class SolveSpaceSolver_Storage
- * \ingroup Plugins
- * \brief Contains all necessary data in SolveSpace format to solve a single group of constraints
- */
-class SolveSpaceSolver_Storage : public SketchSolver_Storage
-{
-public:
- SolveSpaceSolver_Storage(const GroupID& theGroup);
-
-// ============= Inherited from SketchSolver_Storage =============
-
- /// \brief Update constraint's data
- /// \return \c true if any value is updated
- virtual bool update(ConstraintWrapperPtr& theConstraint);
- /// \brief Update entity's data
- /// \return \c true if any value is updated
- virtual bool update(EntityWrapperPtr& theEntity);
- /// \brief Update parameter's data
- /// \return \c true if the value of parameter is updated
- virtual bool update(ParameterWrapperPtr& theParameter);
-
- /// \brief Removes constraint from the storage
- /// \return \c true if the constraint and all its parameters are remove successfully
- virtual bool removeConstraint(ConstraintPtr theConstraint);
- /// \brief Removes feature from the storage
- /// \return \c true if the feature and its attributes are removed successfully;
- /// \c false if the feature or any it attribute is used by remaining constraints.
- virtual bool removeEntity(FeaturePtr theFeature);
- /// \brief Removes attribute from the storage
- /// \return \c true if the attribute is not used by remaining features and constraints
- virtual bool removeEntity(AttributePtr theAttribute);
-
- /// \brief Update SketchPlugin features after resolving constraints
- /// \param theFixedOnly [in] if \c true the fixed points will be updated only
- virtual void refresh(bool theFixedOnly = false) const;
-
- /// \brief Check if some parameters or entities are returned
- /// to the current group after removing temporary constraints
- virtual void verifyFixed();
-
- /// \brief Mark two points as coincident
- virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave);
-
- /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
- /// shows the distance from the start point.
- virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase, double theCoeff);
-
-protected:
- /// \brief Remove constraint
- /// \return \c true if the constraint and all its parameters are removed successfully
- virtual bool remove(ConstraintWrapperPtr theConstraint);
- /// \brief Remove entity
- /// \return \c true if the entity and all its parameters are removed successfully
- virtual bool remove(EntityWrapperPtr theEntity);
- /// \brief Remove parameter
- /// \return \c true if the parameter has been removed
- virtual bool remove(ParameterWrapperPtr theParameter);
-
- /// \brief Update the group for the given entity, its sub-entities and parameters
- virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup);
- /// \brief Update the group for the given parameter
- virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup);
-
-
-// ============= Own methods =============
-public:
- /// \brief Obtain and store identifier of sketch
- void storeWorkplane(EntityWrapperPtr theSketch);
-
- /** \brief Add new parameter to the current group
- * \param[in] theParam SolveSpace parameter
- * \return the ID of added parameter
- */
- Slvs_hParam addParameter(const Slvs_Param& theParam);
- /** \brief Updates parameter in the current group. If the ID of parameter is zero, the new item will be added
- * \param[in] theParam SolveSpace parameter
- * \return the ID of updated/added parameter
- */
- Slvs_hParam updateParameter(const Slvs_Param& theParam);
- /** \brief Removes the parameter by its ID
- * \param[in] theParamID index of parameter to be removed
- * \return \c true if the parameter was successfully removed
- */
- bool removeParameter(const Slvs_hParam& theParamID);
- /// \brief Returns the parameter by its ID
- const Slvs_Param& getParameter(const Slvs_hParam& theParamID) const;
-
- /** \brief Add new entity to the current group
- * \param[in] theEntity SolveSpace entity
- * \return the ID of added entity
- */
- Slvs_hEntity addEntity(const Slvs_Entity& theEntity);
- /** \brief Updates entity in the current group. If the ID of entity is zero, the new item will be added
- * \param[in] theEntity SolveSpace entity
- * \return the ID of updated/added entity
- */
- Slvs_hEntity updateEntity(const Slvs_Entity& theEntity);
- /** \brief Removes the entity by its ID. All parameters used in this entity,
- * and not used in other constraints, will be removed too.
- * \param[in] theEntityID index of entity to be removed
- * \return \c true if the entity was successfully removed
- */
- bool removeEntity(const Slvs_hEntity& theEntityID);
- /** \brief Remove all entities, which are not used in constraints
- */
- void removeUnusedEntities();
- /// \brief Returns the entity by its ID
- const Slvs_Entity& getEntity(const Slvs_hEntity& theEntityID) const;
- /// \brief Makes a full copy of the given entity
- Slvs_hEntity copyEntity(const Slvs_hEntity& theCopied);
- /// \brief Copy one entity to another
- void copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo);
- /// \brief Check the entity is used in constraints
- bool isUsedByConstraints(const Slvs_hEntity& theEntityID) const;
- /// \brief Returns maximal ID of entities in this storage
- const Slvs_hEntity& entityMaxID() const
- { return myEntityMaxID; }
-
- /// \brief Verifies the current point or another coincident one is fixed
- /// \param[in] thePointID entity to be checked fixed
- /// \param[out] theFixed ID of constraint
- /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
- /// if \c false, only the point is verified
- /// \return \c true if the point is fixed
- bool isPointFixed(const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate = false) const;
- /// \brief Verifies the current entity is fully fixed (may not be changed by constraints)
- /// \param[in] theEntityID entity to be checked fixed
- /// \param[in] theAccurate if \c true, the calculation will be made for all type of constraints,
- /// if \c false, only points are verified
- /// \return \c true if the entity is fixed
- bool isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate = false) const;
-
- /** \brief Add new constraint to the current group
- * \param[in] theConstraint SolveSpace's constraint
- * \return the ID of added constraint
- */
- Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
- /** \brief Updates constraint in the current group.
- * If the ID of constraint is zero, the new item will be added
- * \param[in] theConstraint SolveSpace constraint
- * \return the ID of updated/added constraint
- */
- Slvs_hConstraint updateConstraint(const Slvs_Constraint& theConstraint);
- /** \brief Removes the constraint by its ID. All entities and parameters depending on this
- * constraint, which are not used in other constraints, will be removed too.
- * \param[in] theConstraintID index of constraint to be removed
- * \return \c true if the constraint was successfully removed
- */
- bool removeConstraint(const Slvs_hConstraint& theConstraintID);
- /// \brief Returns the constraint by its ID
- const Slvs_Constraint& getConstraint(const Slvs_hConstraint& theConstraintID) const;
- /// \brief Returns list of constraints of specified type
- std::list<Slvs_Constraint> getConstraintsByType(int theConstraintType) const;
- /// \brief Returns quantity of constraints in this storage
- size_t nbConstraints() const
- { return myConstraints.size(); }
-
- /// \brief Attach constraint SLVS_C_WHERE_DRAGGED to this storage. It need to make precise calculations
- void addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID);
-
- /// \brief Add transient constraint
- void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID);
- /// \brief Mark specified constraint as temporary
- virtual void setTemporary(ConstraintPtr theConstraint);
- /// \brief Remove all transient constraints
- void removeAllTemporary();
- /// \brief Remove temporary constraint s. Preferable to remove the points under Point-on-Line constraint
- /// \param theNbConstraints [in] number of temporary constraints to be deleted
- /// \return Number of remaining temporary constraints
- virtual size_t removeTemporary(size_t theNbConstraints);
- /// \brief Checks the constraint is temporary
- bool isTemporary(const Slvs_hConstraint& theConstraintID) const;
- /// \brief Number of temporary constraints
- virtual size_t nbTemporary() const
- { return myTemporaryConstraints.size(); }
-
- /// \brief Shows the storage has the same constraint twice
- virtual bool hasDuplicatedConstraint() const
- { return myDuplicatedConstraint; }
-
-//// /// \brief Returns lists of removed elements
-//// void getRemoved(std::set<Slvs_hParam>& theParameters,
-//// std::set<Slvs_hEntity>& theEntities,
-//// std::set<Slvs_hConstraint>& theConstraints);
-
-//// /// \brief Shows the sketch should be resolved
-//// virtual bool isNeedToResolve();
-
- /// \brief Initialize constraint solver by the entities collected by current storage
- virtual void initializeSolver(SolverPtr theSolver);
-
-////private:
-//// /// \brief Store coincident points
-//// void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
-//// /// \brief Remove point from lists of coincidence
-//// void removeCoincidentPoint(const Slvs_hEntity& thePoint);
-//// /// \brief Remove point-point coincidence
-//// void removeCoincidence(const Slvs_Constraint& theCoincidence);
-
-public:
-//// /// \brief Check two points are coincident
-//// bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
-
- /// \brief Check two points are coincident or have same coordinates
- bool isEqual(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const;
-
- /// \brief Check the entity is horizontal of vertical
- bool isAxisParallel(const Slvs_hEntity& theEntity) const;
-
- /// \brief Verifies the entity is used in any equal constraint
- /// \param[in] theEntity entity to be found
- /// \param[out] theEqual constraint, which uses the entity
- /// \return \c true, if the Equal constrait is found
- bool isUsedInEqual(const Slvs_hEntity& theEntity, Slvs_Constraint& theEqual) const;
-
- /// \brief Fixes specified entity
- /// \param theEntity ID of the entity to be fixed
- /// \return List of created constraints
- std::vector<Slvs_hConstraint> fixEntity(const Slvs_hEntity& theEntity);
-
-private:
- /// \brief Fixes specified point
- /// \param [in] thePoint point to be fixed
- /// \param [out] theCreated list of the Fixed constraints created
- void fixPoint(const Slvs_Entity& thePoint, std::vector<Slvs_hConstraint>& theCreated);
- /// \brief Fixes specified line
- /// \param [in] theLine line to be fixed
- /// \param [out] theCreated list of the Fixed constraints created
- void fixLine(const Slvs_Entity& theLine, std::vector<Slvs_hConstraint>& theCreated);
- /// \brief Fixes specified circle
- /// \param [in] theCircle circle to be fixed
- /// \param [out] theCreated list of the Fixed constraints created
- void fixCircle(const Slvs_Entity& theCircle, std::vector<Slvs_hConstraint>& theCreated);
- /// \brief Fixes specified arc
- /// \param [in] theArc arc to be fixed
- /// \param [out] theCreated list of the Fixed constraints created
- void fixArc(const Slvs_Entity& theArc, std::vector<Slvs_hConstraint>& theCreated);
-
- /// \brief Update arc points to be on circle sharp.
- void adjustArc(const Slvs_Entity& theArc);
-
- /// \brief Verify the feature or any its attribute is used by constraint
- bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used by constraint
- bool isUsed(AttributePtr theAttirubute) const;
-
- /// \brief Replace sub-entity theSource in all features by theDest
- void replaceInFeatures(EntityWrapperPtr theSource, EntityWrapperPtr theDest);
- /// \brief Replace constrained entity theSource by theDest in all constraints;
- void replaceInConstraints(EntityWrapperPtr theSource, EntityWrapperPtr theDest);
-
- /// \brief Add pair of constraints which have same representation in SolveSpace notation.
- ///
- /// These constraints may be different and become the same after the substitution
- /// of point coincidence.
- void addSameConstraints(ConstraintWrapperPtr theConstraint1, ConstraintWrapperPtr theConstraint2);
-
-private:
- Slvs_hEntity myWorkplaneID; ///< identifier of workplane
-
- Slvs_hParam myParamMaxID; ///< current parameter index (may differs with the number of parameters)
- std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints (sorted by the identifier)
- Slvs_hEntity myEntityMaxID; ///< current entity index (may differs with the number of entities)
- std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints (sorted by the identifier)
- Slvs_hConstraint myConstrMaxID; ///< current constraint index (may differs with the number of constraints)
- std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group (sorted by the identifier)
-
- CoincidentPointsMap myCoincidentPoints; ///< lists of coincident points (first is a master point, second is a set of slaves)
- Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
-
- bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
-
- std::set<Slvs_hConstraint> myTemporaryConstraints; ///< list of transient constraints
-//// std::set<Slvs_hParam> myRemovedParameters; ///< list of just removed parameters (cleared when returning to applicant)
-//// std::set<Slvs_hEntity> myRemovedEntities; ///< list of just removed entities (cleared when returning to applicant)
-//// std::set<Slvs_hConstraint> myRemovedConstraints; ///< list of just removed constraints (cleared when returning to applicant)
- std::set<Slvs_hParam> myUpdatedParameters; ///< list of just updated parameters (cleared when isNeedToResolve() called)
-
- SameConstraintMap myEqualConstraints; ///< list of groups of equal constraints
-};
-
-#endif