2. Implementation of PlaneGCS solver connection.
3. Update test cases according new behavior.
<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="SolveSpaceSolver"/> -->
+ <plugin library="PlaneGCSSolver"/>
<plugin library="GeomValidators"/>
<plugin library="DFBrowser" internal="true"/>
</plugins>
return true;
}
+
+void GeomAPI_Edge::getRange(double& theFirst, double& theLast) const
+{
+ const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve((const TopoDS_Edge&)aShape, theFirst, theLast);
+}
/// Returns true if the current edge is geometrically equal to the given edge
GEOMAPI_EXPORT
bool isEqual(const std::shared_ptr<GeomAPI_Shape> theEdge) const;
+
+ /// Returns range of parameter on the curve
+ GEOMAPI_EXPORT
+ void getRange(double& theFirst, double& theLast) const;
};
#endif
"""
from GeomDataAPI import *
from ModelAPI import *
+import math
#=========================================================================
# Initialization of the test
#=========================================================================
assert (aLineAStartPoint.y() == 25)
assert (aLineAEndPoint.y() == 25)
# length of the line is the same
-assert (aLineAEndPoint.x() - aLineAStartPoint.x() == 100)
+assert (math.fabs(aLineAEndPoint.x() - aLineAStartPoint.x() - 100) < 1.e-10)
#=========================================================================
# Change the length value of the constraint
#=========================================================================
aLength.setValue(140.)
aLengthConstraint.execute()
aSession.finishOperation()
-assert (aLineAEndPoint.x() - aLineAStartPoint.x() == 140)
+assert (math.fabs(aLineAEndPoint.x() - aLineAStartPoint.x() - 140) < 1.e-10)
#=========================================================================
# TODO: improve test
# 1. remove constraint, move line's start point to
aSession.finishOperation()
# Check that constarints doesn't affected lines' values
-assert (kLineAStart == (aLineAStartPoint.x(), aLineAStartPoint.y()))
-assert (kLineAEnd == (aLineAEndPoint.x(), aLineAEndPoint.y()))
-assert (kLineBStart == (aLineBStartPoint.x(), aLineBStartPoint.y()))
-assert (kLineBEnd == (aLineBEndPoint.x(), aLineBEndPoint.y()))
-assert (kLineCStart == (aLineCStartPoint.x(), aLineCStartPoint.y()))
-assert (kLineCEnd == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineAStartPoint.x(), aLineAStartPoint.y()) == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineBStartPoint.x(), aLineBStartPoint.y()) == (aLineAEndPoint.x(), aLineAEndPoint.y()))
+assert ((aLineCStartPoint.x(), aLineCStartPoint.y()) == (aLineBEndPoint.x(), aLineBEndPoint.y()))
#=========================================================================
# Check that moving line A does not affect lines
#=========================================================================
aLineAEndPoint.setValue(90., 0.)
aSession.finishOperation()
# Check that constarint keep features' values
-assert (kLineAStart == (aLineAStartPoint.x(), aLineAStartPoint.y()))
-assert (kLineAEnd == (aLineAEndPoint.x(), aLineAEndPoint.y()))
-assert (kLineBStart == (aLineBStartPoint.x(), aLineBStartPoint.y()))
-assert (kLineBEnd == (aLineBEndPoint.x(), aLineBEndPoint.y()))
-assert (kLineCStart == (aLineCStartPoint.x(), aLineCStartPoint.y()))
-assert (kLineCEnd == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineAStartPoint.x(), aLineAStartPoint.y()) == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineBStartPoint.x(), aLineBStartPoint.y()) == (aLineAEndPoint.x(), aLineAEndPoint.y()))
+assert ((aLineCStartPoint.x(), aLineCStartPoint.y()) == (aLineBEndPoint.x(), aLineBEndPoint.y()))
#=========================================================================
# Check that moving line B does not affect lines
#=========================================================================
aLineBEndPoint.setValue(90., 150.)
aSession.finishOperation()
# Check that constarint keep features' values
-assert (kLineAStart == (aLineAStartPoint.x(), aLineAStartPoint.y()))
-assert (kLineAEnd == (aLineAEndPoint.x(), aLineAEndPoint.y()))
-assert (kLineBStart == (aLineBStartPoint.x(), aLineBStartPoint.y()))
-assert (kLineBEnd != (aLineBEndPoint.x(), aLineBEndPoint.y()))
-assert (kLineCStart != (aLineCStartPoint.x(), aLineCStartPoint.y()))
-assert (kLineCEnd == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineAStartPoint.x(), aLineAStartPoint.y()) == (aLineCEndPoint.x(), aLineCEndPoint.y()))
+assert ((aLineBStartPoint.x(), aLineBStartPoint.y()) == (aLineAEndPoint.x(), aLineAEndPoint.y()))
+assert ((aLineCStartPoint.x(), aLineCStartPoint.y()) == (aLineBEndPoint.x(), aLineBEndPoint.y()))
#=========================================================================
# TODO: improve test
# 1. remove constraint, move line to check that constraint are not applied
aSession.finishOperation()
anArcVecX = anArcStartPoint.x() - anArcCentr.x()
anArcVecY = anArcStartPoint.y() - anArcCentr.y()
+aLen = math.sqrt(anArcVecX**2 + anArcVecY**2)
aLineVecX = aLine1EndPoint.x() - aLine1StartPoint.x()
aLineVecY = aLine1EndPoint.y() - aLine1StartPoint.y()
+aLen = aLen * math.sqrt(aLineVecX**2 + aLineVecY**2)
aDot = anArcVecX * aLineVecX + anArcVecY * aLineVecY
-assert(math.fabs(aDot) <= 1.e-12)
+assert math.fabs(aDot) <= 2.e-6 * aLen, "Observed dot product: {0}".format(aDot)
#=========================================================================
# Add tangency constraint for arc and second line and check correctness
#=========================================================================
aSession.finishOperation()
anArcVecX = anArcEndPoint.x() - anArcCentr.x()
anArcVecY = anArcEndPoint.y() - anArcCentr.y()
+aLen = math.sqrt(anArcVecX**2 + anArcVecY**2)
aLineVecX = aLine2EndPoint.x() - aLine2StartPoint.x()
aLineVecY = aLine2EndPoint.y() - aLine2StartPoint.y()
+aLen = aLen * math.sqrt(aLineVecX**2 + aLineVecY**2)
aDot = anArcVecX * aLineVecX + anArcVecY * aLineVecY
-assert(math.fabs(aDot) <= 1.e-12)
+assert math.fabs(aDot) <= 2.e-6 * aLen, "Observed dot product: {0}".format(aDot)
#=========================================================================
# TEST 2. Arc-arc tangency
aSession.finishOperation()
anArc1VecX = anArc1EndPoint.x() - anArc1Centr.x()
anArc1VecY = anArc1EndPoint.y() - anArc1Centr.y()
+aLen = math.sqrt(anArc1VecX**2 + anArc1VecY**2)
anArc2VecX = anArc2StartPoint.x() - anArc2Centr.x()
anArc2VecY = anArc2StartPoint.y() - anArc2Centr.y()
+aLen = aLen * math.sqrt(anArc2VecX**2 + anArc2VecY**2)
aCross = anArc1VecX * anArc2VecY - anArc1VecY * anArc2VecX
-assert(math.fabs(aCross) <= 1.e-12)
+assert math.fabs(aCross) <= 2.e-6 * aLen, "Observed cross product: {0}".format(aCross)
#=========================================================================
# TEST 3. Tangency between non-connected objects should be wrong
--- /dev/null
+## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+FIND_PACKAGE(PlaneGCS REQUIRED)
+
+SET(PROJECT_HEADERS
+ PlaneGCSSolver_Defs.h
+ PlaneGCSSolver_Solver.h
+ PlaneGCSSolver_Builder.h
+ PlaneGCSSolver_Storage.h
+ PlaneGCSSolver_ConstraintWrapper.h
+ PlaneGCSSolver_EntityWrapper.h
+ PlaneGCSSolver_PointWrapper.h
+ PlaneGCSSolver_ScalarWrapper.h
+ PlaneGCSSolver_ParameterWrapper.h
+ PlaneGCSSolver_AngleWrapper.h
+)
+
+SET(PROJECT_SOURCES
+ PlaneGCSSolver_Solver.cpp
+ PlaneGCSSolver_Builder.cpp
+ PlaneGCSSolver_Storage.cpp
+ PlaneGCSSolver_ConstraintWrapper.cpp
+ PlaneGCSSolver_EntityWrapper.cpp
+ PlaneGCSSolver_PointWrapper.cpp
+ PlaneGCSSolver_ScalarWrapper.cpp
+ PlaneGCSSolver_ParameterWrapper.cpp
+ PlaneGCSSolver_AngleWrapper.cpp
+)
+
+SET(PROJECT_LIBRARIES
+ ${PLANEGCS_LIBRARIES}
+ SketchSolver
+ ModelAPI
+ GeomAPI
+)
+
+INCLUDE_DIRECTORIES(
+ ${Boost_INCLUDE_DIRS}
+ ${EIGEN3_INCLUDE_DIR}
+ ${PLANEGCS_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(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
+TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES})
+INSTALL(TARGETS PlaneGCSSolver DESTINATION plugins)
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_AngleWrapper.cpp
+// Created: 18 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_AngleWrapper.h>
+
+#include <math.h>
+
+static double deg2rad(double theDegrees)
+{
+ return theDegrees * M_PI / 180.0;
+}
+
+static double rad2deg(double theRadians)
+{
+ return theRadians * 180.0 / M_PI;
+}
+
+PlaneGCSSolver_AngleWrapper::PlaneGCSSolver_AngleWrapper(double *const theParam)
+ : PlaneGCSSolver_ParameterWrapper(theParam)
+{
+ setValue(*myValue);
+}
+
+void PlaneGCSSolver_AngleWrapper::setValue(double theValue)
+{
+ *(myValue) = deg2rad(theValue);
+}
+
+double PlaneGCSSolver_AngleWrapper::value() const
+{
+ return rad2deg(*myValue);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_AngleWrapper.h
+// Created: 18 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_AngleWrapper_H_
+#define PlaneGCSSolver_AngleWrapper_H_
+
+#include <PlaneGCSSolver_ParameterWrapper.h>
+
+/**
+ * Wrapper providing operations with angular parameters in PlaneGCS.
+ */
+class PlaneGCSSolver_AngleWrapper : public PlaneGCSSolver_ParameterWrapper
+{
+public:
+ PlaneGCSSolver_AngleWrapper(double *const theParam);
+ ~PlaneGCSSolver_AngleWrapper() {}
+
+ /// \brief Change value of parameter
+ virtual void setValue(double theValue);
+ /// \brief Return value of parameter
+ virtual double value() const;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Builder.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_Builder.h>
+#include <PlaneGCSSolver_Solver.h>
+#include <PlaneGCSSolver_Storage.h>
+#include <PlaneGCSSolver_ParameterWrapper.h>
+#include <PlaneGCSSolver_AngleWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_ConstraintWrapper.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 <SketchPlugin_ConstraintAngle.h>
+
+#include <math.h>
+
+
+#define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
+#define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
+#define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
+
+
+/// \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
+static ParameterWrapperPtr createParameter(const GroupID& theGroup,
+ const double theValue = 0.0,
+ const bool theExpr = false);
+
+static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
+ const double& theValue = 0.0);
+
+static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
+ createScalar(const GroupID& theGroupID,
+ AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
+
+static EntityWrapperPtr createLine(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID);
+static EntityWrapperPtr createCircle(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID);
+static EntityWrapperPtr createArc(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID);
+
+
+static ConstraintWrapperPtr
+ createConstraintCoincidence(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
+static ConstraintWrapperPtr
+ createConstraintPointOnEntity(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintDistancePointPoint(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
+static ConstraintWrapperPtr
+ createConstraintDistancePointLine(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintRadius(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintAngle(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
+static ConstraintWrapperPtr
+ createConstraintHorizVert(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintParallel(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
+static ConstraintWrapperPtr
+ createConstraintPerpendicular(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
+static ConstraintWrapperPtr
+ createConstraintEqual(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
+static ConstraintWrapperPtr
+ createConstraintTangent(ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
+
+
+
+/// \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 PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
+
+BuilderPtr PlaneGCSSolver_Builder::getInstance()
+{
+ if (!mySelf) {
+ mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
+ SketchSolver_Manager::instance()->setBuilder(mySelf);
+ }
+ return mySelf;
+}
+
+StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
+{
+ return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
+}
+
+SolverPtr PlaneGCSSolver_Builder::createSolver() const
+{
+ return SolverPtr(new PlaneGCSSolver_Solver);
+}
+
+
+std::list<ConstraintWrapperPtr> PlaneGCSSolver_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
+{
+ ConstraintWrapperPtr aResult;
+ ParameterWrapperPtr anIntermediate;
+ switch (theType) {
+ case CONSTRAINT_PT_PT_COINCIDENT:
+ aResult = createConstraintCoincidence(theConstraint, theGroupID,
+ GCS_POINT_WRAPPER(thePoint1), GCS_POINT_WRAPPER(thePoint2));
+ break;
+ case CONSTRAINT_PT_ON_LINE:
+ case CONSTRAINT_PT_ON_CIRCLE:
+ aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
+ GCS_POINT_WRAPPER(thePoint1), GCS_ENTITY_WRAPPER(theEntity1));
+ break;
+ case CONSTRAINT_PT_PT_DISTANCE:
+ aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
+ GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
+ GCS_POINT_WRAPPER(thePoint1), GCS_POINT_WRAPPER(thePoint2));
+ break;
+ case CONSTRAINT_PT_LINE_DISTANCE:
+ aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
+ GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
+ GCS_POINT_WRAPPER(thePoint1), GCS_ENTITY_WRAPPER(theEntity1));
+ break;
+ case CONSTRAINT_RADIUS:
+ aResult = createConstraintRadius(theConstraint, theGroupID,
+ GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
+ GCS_ENTITY_WRAPPER(theEntity1));
+ break;
+ case CONSTRAINT_ANGLE:
+ aResult = createConstraintAngle(theConstraint, theGroupID,
+ GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
+ GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ break;
+ case CONSTRAINT_FIXED:
+ break;
+ case CONSTRAINT_HORIZONTAL:
+ case CONSTRAINT_VERTICAL:
+ aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
+ GCS_ENTITY_WRAPPER(theEntity1));
+ break;
+ case CONSTRAINT_PARALLEL:
+ aResult = createConstraintParallel(theConstraint, theGroupID,
+ GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ break;
+ case CONSTRAINT_PERPENDICULAR:
+ aResult = createConstraintPerpendicular(theConstraint, theGroupID,
+ GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ break;
+ case CONSTRAINT_EQUAL_LINES:
+ anIntermediate = createParameter(theGroupID);
+ case CONSTRAINT_EQUAL_LINE_ARC:
+ case CONSTRAINT_EQUAL_RADIUS:
+ aResult = createConstraintEqual(theConstraint, theGroupID, theType,
+ GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
+ GCS_PARAMETER_WRAPPER(anIntermediate));
+ break;
+ case CONSTRAINT_TANGENT_ARC_LINE:
+ case CONSTRAINT_TANGENT_ARC_ARC:
+ aResult = createConstraintTangent(theConstraint, theGroupID, theType,
+ GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ break;
+ case CONSTRAINT_MULTI_TRANSLATION:
+ case CONSTRAINT_MULTI_ROTATION:
+ break;
+ case CONSTRAINT_SYMMETRIC:
+ return createMirror(theConstraint, theGroupID, theSketchID,
+ thePoint1, thePoint2, theEntity1);
+ default:
+ break;
+ }
+
+ if (!aResult)
+ return std::list<ConstraintWrapperPtr>();
+ adjustConstraint(aResult);
+ return std::list<ConstraintWrapperPtr>(1, aResult);
+}
+
+std::list<ConstraintWrapperPtr> PlaneGCSSolver_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
+{
+ ParameterWrapperPtr anAngleParam;
+ if (theType == CONSTRAINT_MULTI_ROTATION)
+ anAngleParam = createParamAngle(theGroupID, theValue);
+ else if (theType != CONSTRAINT_MULTI_TRANSLATION)
+ return std::list<ConstraintWrapperPtr>();
+
+ std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
+ if (thePoint2)
+ aConstrAttrList.push_front(thePoint2);
+ aConstrAttrList.push_front(thePoint1);
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
+ aResult->setGroup(theGroupID);
+ aResult->setEntities(aConstrAttrList);
+ if (anAngleParam)
+ aResult->setValueParameter(anAngleParam);
+ return std::list<ConstraintWrapperPtr>(1, aResult);
+}
+
+
+std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const EntityID& theSketchID,
+ const EntityWrapperPtr& theEntity1,
+ const EntityWrapperPtr& theEntity2,
+ const EntityWrapperPtr& theMirrorLine) const
+{
+ 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);
+
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity1);
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity2);
+
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
+ std::shared_ptr<GCS::Line> aLine =
+ std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
+
+ std::list<GCSConstraintPtr> aConstrList;
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
+ *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
+ *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
+
+ ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
+ theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
+ aSubResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aSubs.push_back(theMirrorLine);
+ aSubResult->setEntities(aSubs);
+ aResult.push_back(aSubResult);
+ }
+ 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);
+
+ // Make mirror for center and start point of original arc
+ std::list<ConstraintWrapperPtr> aMrrList;
+ std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
+ std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
+ aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
+ aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
+
+ ++anIt1;
+ ++anIt2; ++anIt2;
+ aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
+ aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
+
+ // make symmetric last point of original arc and first point of mirrored arc without additional constraint
+ ++anIt1;
+ --anIt2;
+ makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
+
+ // Additionally, make equal radii...
+ aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
+ 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
+ aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
+ // ... and make parametric length of arcs the same
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
+ std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
+ std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
+ createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
+ // By the way, recalculate start and end angles of mirrored arc
+ std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
+ std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
+ *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
+ std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
+ *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
+ *anArc2->startAngle = anOX->angle(aStartDir);
+ *anArc2->endAngle = anOX->angle(aEndDir);
+
+ std::list<GCSConstraintPtr> aConstrList;
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
+ anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
+ anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
+ aSubResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aSubs.push_back(theMirrorLine);
+ aSubResult->setEntities(aSubs);
+ aSubResult->setValueParameter(anIntermed);
+ aResult.push_back(aSubResult);
+
+ // Restore event sending
+ aMirrArc->data()->blockSendAttributeUpdated(false);
+ }
+ return aResult;
+}
+
+void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
+{
+ SketchSolver_ConstraintType aType = theConstraint->type();
+ // Update flags and parameters in constraints
+ 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 PlaneGCSSolver_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);
+ // Circle
+ else if (aFeatureKind == SketchPlugin_Circle::ID())
+ return createCircle(theFeature, theAttributes, theGroupID);
+ // Arc
+ else if (aFeatureKind == SketchPlugin_Arc::ID())
+ return createArc(theFeature, theAttributes, theGroupID);
+ // 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);
+ if (!aSub)
+ return aDummy;
+
+ GCSPointPtr aSubEnt =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
+ EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
+ aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
+ return aNewEntity;
+ }
+
+ // wrong entity
+ return aDummy;
+}
+
+EntityWrapperPtr PlaneGCSSolver_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;
+ EntityWrapperPtr aResult;
+
+ // 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()));
+ GCSPointPtr aGCSPoint(new GCS::Point);
+ aGCSPoint->x = std::dynamic_pointer_cast<
+ PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
+ aGCSPoint->y = std::dynamic_pointer_cast<
+ PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
+ // Create entity (parameters are not filled)
+ aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
+ } else {
+ // Scalar value (used for the distance entities)
+ AttributeDoublePtr aScalar =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+ if (aScalar)
+ return createScalar(theGroupID, aScalar);
+ }
+
+ if (!aResult) {
+ // unknown attribute type
+ return EntityWrapperPtr();
+ }
+
+ aResult->setGroup(theGroupID);
+ aResult->setParameters(aParameters);
+ return aResult;
+}
+
+ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
+ const GroupID& theGroupID, double theValue) const
+{
+ return ::createParameter(theGroupID, theValue);
+}
+
+
+EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
+ CompositeFeaturePtr theSketch,
+ const GroupID& theGroupID) const
+{
+ DataPtr aSketchData = theSketch->data();
+ if (!aSketchData || !aSketchData->isValid())
+ return EntityWrapperPtr(); // the sketch is incorrect
+
+ // Create dummy wrapper representing workplane
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
+ new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
+ aSketchEnt->setGroup(theGroupID);
+ aSketchEnt->setId(EID_SKETCH);
+ return aSketchEnt;
+}
+
+
+
+////EntityWrapperPtr PlaneGCSSolver_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;
+////}
+
+
+
+
+
+// ================ Auxiliary functions ==========================
+ParameterWrapperPtr createParameter(
+ const GroupID& theGroup, const double theValue, const bool theExpr)
+{
+ double* aParam = new double(theValue);
+ ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
+ aWrapper->setGroup(theGroup);
+ aWrapper->setIsParametric(theExpr);
+ return aWrapper;
+}
+
+ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
+{
+ double* aParam = new double(theValue);
+ ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
+ aWrapper->setGroup(theGroup);
+ return aWrapper;
+}
+
+std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
+ const GroupID& theGroupID,
+ AttributeDoublePtr theDoubleAttr)
+{
+ ParameterWrapperPtr aParam = createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
+ return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
+ new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
+}
+
+EntityWrapperPtr createLine(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID)
+{
+ 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;
+
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
+ std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
+ if (!aWrapper)
+ continue;
+ if (aWrapper->isBase(aStart))
+ aStartEnt = aWrapper;
+ else if (aWrapper->isBase(aEnd))
+ aEndEnt = aWrapper;
+ }
+ if (!aStartEnt || !aEndEnt)
+ return aNewEntity;
+
+ aSubs.push_back(aStartEnt);
+ aSubs.push_back(aEndEnt);
+
+ std::shared_ptr<GCS::Line> aLine(new GCS::Line);
+ aLine->p1 = *(aStartEnt->point());
+ aLine->p2 = *(aEndEnt->point());
+
+ aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
+ aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
+ aNewEntity->setSubEntities(aSubs);
+ return aNewEntity;
+}
+
+EntityWrapperPtr createCircle(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID)
+{
+ 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;
+
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
+ std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ if ((*anIt)->isBase(aCenter))
+ aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
+ else if ((*anIt)->isBase(aRadius))
+ aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
+ }
+ if (!aCenterEnt || !aRadiusEnt)
+ return aNewEntity;
+
+ aSubs.push_back(aCenterEnt);
+ aSubs.push_back(aRadiusEnt);
+
+ std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
+ aCircle->center = *(aCenterEnt->point());
+ aCircle->rad = aRadiusEnt->scalar();
+
+ aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
+ aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
+ aNewEntity->setSubEntities(aSubs);
+ return aNewEntity;
+}
+
+EntityWrapperPtr createArc(FeaturePtr theFeature,
+ const std::list<EntityWrapperPtr>& theAttributes,
+ const GroupID& theGroupID)
+{
+ 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;
+
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
+ std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
+ if (!aWrapper)
+ continue;
+ if (aWrapper->isBase(aCenter))
+ aCenterEnt = aWrapper;
+ else if (aWrapper->isBase(aStart))
+ aStartEnt = aWrapper;
+ else if (aWrapper->isBase(aEnd))
+ aEndEnt = aWrapper;
+ }
+ if (!aCenterEnt || !aStartEnt || !aEndEnt)
+ return aNewEntity;
+
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
+ aStartAng = createScalar(theGroupID);
+ aEndAng = createScalar(theGroupID);
+ aRadius = createScalar(theGroupID);
+
+ aSubs.push_back(aCenterEnt);
+ aSubs.push_back(aStartEnt);
+ aSubs.push_back(aEndEnt);
+ aSubs.push_back(aStartAng);
+ aSubs.push_back(aEndAng);
+ aSubs.push_back(aRadius);
+
+ std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
+ anArc->center = *(aCenterEnt->point());
+ anArc->start = *(aStartEnt->point());
+ anArc->end = *(aEndEnt->point());
+ anArc->startAngle = aStartAng->scalar();
+ anArc->endAngle = aEndAng->scalar();
+ anArc->rad = aRadius->scalar();
+
+ aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
+ aNewEntity->setGroup(theGroupID); // sub-entities should not change their groups, therefore they are added later
+ aNewEntity->setSubEntities(aSubs);
+ return aNewEntity;
+}
+
+
+
+ConstraintWrapperPtr createConstraintCoincidence(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
+{
+ // Create equality constraint for corresponding attributes of the points
+ std::list<GCSConstraintPtr> aConstrList;
+ std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
+ std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
+ for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
+ if (*anIt1 == *anIt2)
+ continue; // points use same parameters, no need additional constraints
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
+ aConstrList.push_back(
+ GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
+ }
+
+ ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
+ theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, thePoint1);
+ aSubs.push_back(thePoint2);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintPointOnEntity(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
+{
+ GCSConstraintPtr aNewConstr;
+
+ switch (theEntity->type()) {
+ case ENTITY_LINE: {
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnLine(*(thePoint->point()), *aLine));
+ break;
+ }
+ case ENTITY_ARC:
+ case ENTITY_CIRCLE: {
+ std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
+ aNewConstr = GCSConstraintPtr(
+ new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
+ break;
+ }
+ default:
+ return ConstraintWrapperPtr();
+ }
+
+ ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
+ theConstraint, aNewConstr, theType));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, thePoint);
+ aSubs.push_back(theEntity);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintDistancePointPoint(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
+{
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
+ *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, thePoint1);
+ aSubs.push_back(thePoint2);
+ aResult->setEntities(aSubs);
+ aResult->setValueParameter(theValue);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintDistancePointLine(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
+{
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
+ *(thePoint->point()), *(aLine), theValue->parameter()));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, thePoint);
+ aSubs.push_back(theEntity);
+ aResult->setEntities(aSubs);
+ aResult->setValueParameter(theValue);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintRadius(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
+{
+ std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity);
+ aResult->setEntities(aSubs);
+ aResult->setValueParameter(theValue);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintAngle(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
+{
+ std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+ std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
+ *(aLine1), *(aLine2), theValue->parameter()));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aResult->setEntities(aSubs);
+ aResult->setValueParameter(theValue);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintHorizVert(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
+{
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
+ GCSConstraintPtr aNewConstr;
+ if (theType == CONSTRAINT_HORIZONTAL)
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.y, aLine->p2.y));
+ else
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
+
+ ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
+ theConstraint, aNewConstr, theType));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintParallel(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
+{
+ std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+ std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintPerpendicular(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
+{
+ std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+ std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintEqual(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
+{
+ if (theType == CONSTRAINT_EQUAL_LINE_ARC)
+ return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
+
+ std::list<GCSConstraintPtr> aConstrList;
+ if (theType == CONSTRAINT_EQUAL_LINES) {
+ std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+ std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+
+ aConstrList.push_back(GCSConstraintPtr(
+ new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
+ aConstrList.push_back(GCSConstraintPtr(
+ new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
+ } else {
+ std::shared_ptr<GCS::Circle> aCirc1 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::shared_ptr<GCS::Circle> aCirc2 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
+
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
+ }
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aResult->setEntities(aSubs);
+ if (theIntermed)
+ aResult->setValueParameter(theIntermed);
+ return aResult;
+}
+
+ConstraintWrapperPtr createConstraintTangent(
+ ConstraintPtr theConstraint,
+ const GroupID& theGroupID,
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
+{
+ GCSConstraintPtr aNewConstr;
+ if (theType == CONSTRAINT_TANGENT_ARC_LINE) {
+ std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
+ } else {
+ std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
+
+ double aDX = *(aCirc1->center.x) - *(aCirc2->center.x);
+ double aDY = *(aCirc1->center.y) - *(aCirc2->center.y);
+ double aDist = sqrt(aDX * aDX + aDY * aDY);
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
+ aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
+ }
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
+ aResult->setGroup(theGroupID);
+ std::list<EntityWrapperPtr> aSubs(1, theEntity1);
+ aSubs.push_back(theEntity2);
+ aResult->setEntities(aSubs);
+ return aResult;
+}
+
+
+
+
+
+void adjustAngle(ConstraintWrapperPtr theConstraint)
+{
+ BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_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;
+ }
+ }
+ }
+
+ bool isChange = false;
+ for (int i = 0; i < 2; i++)
+ if (aLine[i]->direction()->dot(aDir[i]) < 0.0)
+ isChange = !isChange;
+ if (isChange)
+ aConstraint->setValue(180.0 - aConstraint->value());
+}
+
+////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 = PlaneGCSSolver_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<PlaneGCSSolver_PointWrapper>(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)
+{
+ if (theSource->type() == ENTITY_POINT) {
+ // Rotate single point
+ std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
+ std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->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 = theDest->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)
+{
+ if (theSource->type() == ENTITY_POINT) {
+ // Translate single point
+ std::shared_ptr<GeomDataAPI_Point2D> aSrcAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theSource->baseAttribute());
+ std::shared_ptr<GeomDataAPI_Point2D> aDstAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theDest->baseAttribute());
+ if (aSrcAttr && aDstAttr)
+ aDstAttr->setValue(aSrcAttr->x() + theDelta->x(), aSrcAttr->y() + theDelta->y());
+ return;
+ }
+
+ FeaturePtr aDestFeature = theDest->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 = PlaneGCSSolver_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 = PlaneGCSSolver_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: PlaneGCSSolver_Builder.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Builder_H_
+#define PlaneGCSSolver_Builder_H_
+
+#include <PlaneGCSSolver_Defs.h>
+
+#include <SketchSolver_Builder.h>
+#include <SketchSolver_Constraint.h>
+
+#include <SketchPlugin_Constraint.h>
+
+#include <ModelAPI_CompositeFeature.h>
+
+/** \class PlaneGCSSolver_Builder
+ * \ingroup Plugins
+ * \brief Create bridges between SketchPlugin constraints and PlaneGCS constraints
+ */
+class PlaneGCSSolver_Builder : public SketchSolver_Builder
+{
+private:
+ /// Default constructor
+ PlaneGCSSolver_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;
+
+ /// \brief Create a parameter
+ /// \param theGroupID [in] group the parameter belongs to
+ /// \param theValue [in] value of the parameter
+ /// \return Created wrapper for parameter
+ ParameterWrapperPtr createParameter(const GroupID& theGroupID, double theValue = 0.0) 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;
+
+private:
+ static BuilderPtr mySelf;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_ConstraintWrapper.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_ConstraintWrapper.h>
+
+#include <math.h>
+
+PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
+ const ConstraintPtr& theOriginal,
+ const GCSConstraintPtr& theConstraint,
+ const SketchSolver_ConstraintType& theType)
+ : myGCSConstraints(1, theConstraint),
+ myType(theType),
+ myID(CID_UNKNOWN)
+{
+ myBaseConstraint = theOriginal;
+ myValue = 0.0;
+}
+
+PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
+ const ConstraintPtr& theOriginal,
+ const std::list<GCSConstraintPtr>& theConstraints,
+ const SketchSolver_ConstraintType& theType)
+ : myGCSConstraints(theConstraints),
+ myType(theType),
+ myID(CID_UNKNOWN)
+{
+ myBaseConstraint = theOriginal;
+ myValue = 0.0;
+}
+
+void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ParameterWrapperPtr& theValue)
+{
+ myValueParam = theValue;
+ myValue = myValueParam->value();
+}
+
+void PlaneGCSSolver_ConstraintWrapper::setValue(const double& theValue)
+{
+ myValue = theValue;
+ myValueParam->setValue(theValue);
+}
+
+
+void PlaneGCSSolver_ConstraintWrapper::setGroup(const GroupID& theGroup)
+{
+ myGroup = theGroup;
+ std::list<EntityWrapperPtr>::iterator aSubsIt = myConstrained.begin();
+ for (; aSubsIt != myConstrained.end(); ++aSubsIt)
+ (*aSubsIt)->setGroup(theGroup);
+}
+
+bool PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_ConstraintWrapper::isEqual(const ConstraintWrapperPtr& theOther)
+{
+ if (type() != theOther->type())
+ return false;
+//// const Slvs_Constraint anOtherConstraint =
+//// std::dynamic_pointer_cast<PlaneGCSSolver_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 PlaneGCSSolver_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: PlaneGCSSolver_ConstraintWrapper.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_ConstraintWrapper_H_
+#define PlaneGCSSolver_ConstraintWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_Solver.h>
+#include <SketchSolver_IConstraintWrapper.h>
+
+
+/**
+ * Wrapper providing operations with SovleSpace constraints.
+ */
+class PlaneGCSSolver_ConstraintWrapper : public SketchSolver_IConstraintWrapper
+{
+public:
+ PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
+ const GCSConstraintPtr& theConstraint,
+ const SketchSolver_ConstraintType& theType);
+ PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
+ const std::list<GCSConstraintPtr>& theConstraints,
+ const SketchSolver_ConstraintType& theType);
+
+ /// \brief Return list of constraints
+ const std::list<GCSConstraintPtr>& constraints() const
+ { return myGCSConstraints; }
+//// /// \brief Return SolveSpace constraint to change
+//// GCSConstraintPtr& changeConstraint()
+//// { return myGCSConstraint; }
+
+ /// \brief Return ID of current entity
+ virtual ConstraintID id() const
+ { return myID; }
+
+ /// \brief Change group for the constraint
+ virtual void setGroup(const GroupID& theGroup);
+ /// \brief Return identifier of the group the constraint belongs to
+ virtual GroupID group() const
+ { return myGroup; }
+
+ /// \brief Return type of current entity
+ virtual SketchSolver_ConstraintType type() const
+ { return myType; }
+
+ /// \brief Assign numeric parameter of constraint
+ virtual void setValue(const double& theValue);
+
+ /// \brief Change parameter representing the value of constraint
+ void setValueParameter(const ParameterWrapperPtr& theValue);
+ /// \brief Return parametric representation of constraint value
+ const ParameterWrapperPtr& valueParameter() const
+ { return myValueParam; }
+
+ /// \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:
+ ConstraintID myID;
+ GroupID myGroup;
+ SketchSolver_ConstraintType myType;
+ ParameterWrapperPtr myValueParam;
+ std::list<GCSConstraintPtr> myGCSConstraints;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Defs.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Defs_H_
+#define PlaneGCSSolver_Defs_H_
+
+#include <SketchSolver.h>
+
+#include <Constraints.h>
+#include <Geo.h>
+#include <memory>
+
+typedef std::shared_ptr<GCS::Point> GCSPointPtr;
+typedef std::shared_ptr<GCS::Curve> GCSCurvePtr;
+typedef std::shared_ptr<GCS::Constraint> GCSConstraintPtr;
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_EntityWrapper.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Sketch.h>
+
+PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(
+ const FeaturePtr theFeature, const GCSCurvePtr theEntity)
+ : myEntity(theEntity),
+ myID(EID_UNKNOWN)
+{
+ myBaseFeature = theFeature;
+
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
+ if (aLine) myType = ENTITY_LINE;
+ else {
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(myEntity);
+ if (anArc) myType = ENTITY_ARC;
+ else {
+ std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
+ if (aCircle) myType = ENTITY_CIRCLE;
+ }
+ }
+
+ // empty entity, probably this is a SketchPlugin_Point or SketchPlugin_Sketch
+ if (theFeature->getKind() == SketchPlugin_Point::ID())
+ myType = ENTITY_POINT;
+ else if (theFeature->getKind() == SketchPlugin_Sketch::ID())
+ myType = ENTITY_SKETCH;
+}
+
+void PlaneGCSSolver_EntityWrapper::setGroup(const GroupID& theGroup)
+{
+ myGroup = 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);
+}
+
+bool PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_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 PlaneGCSSolver_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: PlaneGCSSolver_EntityWrapper.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_EntityWrapper_H_
+#define PlaneGCSSolver_EntityWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <SketchSolver_IEntityWrapper.h>
+
+/**
+ * Wrapper providing operations with PlaneGCS entities.
+ */
+class PlaneGCSSolver_EntityWrapper : public SketchSolver_IEntityWrapper
+{
+public:
+ PlaneGCSSolver_EntityWrapper(const FeaturePtr theFeature, const GCSCurvePtr theEntity = GCSCurvePtr());
+
+ /// \brief Return PlaneGCS geometric entity
+ const GCSCurvePtr& entity() const
+ { return myEntity; }
+ /// \brief Return PlaneGCS geometric entity to change
+ GCSCurvePtr& changeEntity()
+ { return myEntity; }
+
+ /// \brief Return ID of current entity
+ virtual EntityID id() const
+ { return myID; }
+ /// \brief Change ID of the entity
+ void setId(EntityID theID)
+ { myID = theID; }
+
+ /// \brief Change group for the entity
+ virtual void setGroup(const GroupID& theGroup);
+ /// \brief Return identifier of the group the entity belongs to
+ virtual GroupID group() const
+ { return myGroup; }
+
+ /// \brief Return type of current entity
+ virtual SketchSolver_EntityType type() const
+ { return myType; }
+
+ /// \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 EntityWrapperPtr& theOther);
+
+private:
+ EntityID myID;
+ GroupID myGroup;
+ SketchSolver_EntityType myType;
+ GCSCurvePtr myEntity;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_ParameterWrapper.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_ParameterWrapper.h>
+
+#include <math.h>
+
+PlaneGCSSolver_ParameterWrapper::PlaneGCSSolver_ParameterWrapper(double *const theParam)
+ : myValue(theParam),
+ myProcessing(false)
+{
+}
+
+PlaneGCSSolver_ParameterWrapper::~PlaneGCSSolver_ParameterWrapper()
+{
+ delete myValue;
+}
+
+void PlaneGCSSolver_ParameterWrapper::setValue(double theValue)
+{
+ *(myValue) = theValue;
+}
+
+double PlaneGCSSolver_ParameterWrapper::value() const
+{
+ return *(myValue);
+}
+
+bool PlaneGCSSolver_ParameterWrapper::isEqual(const ParameterWrapperPtr& theOther)
+{
+ return fabs(value() - theOther->value()) < tolerance;
+}
+
+bool PlaneGCSSolver_ParameterWrapper::update(const ParameterWrapperPtr& theOther)
+{
+ if (fabs(value() - theOther->value()) < tolerance)
+ return false;
+ setValue(theOther->value());
+ myIsParametric = theOther->isParametric();
+ return true;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_ParameterWrapper.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_ParameterWrapper_H_
+#define PlaneGCSSolver_ParameterWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <SketchSolver_IParameterWrapper.h>
+
+/**
+ * Wrapper providing operations with parameters in PlaneGCS.
+ */
+class PlaneGCSSolver_ParameterWrapper : public SketchSolver_IParameterWrapper
+{
+public:
+ PlaneGCSSolver_ParameterWrapper(double *const theParam);
+ virtual ~PlaneGCSSolver_ParameterWrapper();
+
+ /// \brief Return ID of current parameter
+ virtual ParameterID id() const
+ { return myID; }
+
+ double* parameter() const
+ { return myValue; }
+
+ /// \brief Change group for the parameter
+ virtual void setGroup(const GroupID& theGroup)
+ { myGroup = theGroup; }
+
+ /// \brief Return identifier of the group the parameter belongs to
+ virtual GroupID group() const
+ { return myGroup; }
+
+ /// \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 ParameterWrapperPtr& theOther);
+
+ /// \brief Shows the parameter is added to full list of parameters
+ bool isProcessed() const
+ { return myProcessing; }
+ /// \brief Set the flag that parameter is under processing
+ void setProcessed(bool isProc)
+ { myProcessing = isProc; }
+
+protected:
+ ParameterID myID;
+ GroupID myGroup;
+ double* myValue;
+ bool myProcessing; ///< identify that the parameter is already in the list of parameters
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_PointWrapper.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_PointWrapper.h>
+
+PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(
+ const AttributePtr theAttribute, const GCSPointPtr thePoint)
+ : myPoint(thePoint),
+ myID(EID_UNKNOWN)
+{
+ myBaseAttribute = theAttribute;
+}
+
+void PlaneGCSSolver_PointWrapper::setGroup(const GroupID& theGroup)
+{
+ myGroup = 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);
+}
+
+bool PlaneGCSSolver_PointWrapper::isUsed(AttributePtr theAttribute) const
+{
+ return isBase(theAttribute);
+}
+
+bool PlaneGCSSolver_PointWrapper::isEqual(const EntityWrapperPtr& theOther)
+{
+ if (type() != theOther->type())
+ 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 PlaneGCSSolver_PointWrapper::update(const EntityWrapperPtr& theOther)
+{
+ bool isUpdated = false;
+ 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: PlaneGCSSolver_PointWrapper.h
+// Created: 16 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_PointWrapper_H_
+#define PlaneGCSSolver_PointWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <SketchSolver_IEntityWrapper.h>
+
+/**
+ * Wrapper providing operations with PlaneGCS points.
+ */
+class PlaneGCSSolver_PointWrapper : public SketchSolver_IEntityWrapper
+{
+public:
+ PlaneGCSSolver_PointWrapper(const AttributePtr theAttribute, const GCSPointPtr thePoint);
+
+ /// \brief Return PlaneGCS point
+ const GCSPointPtr& point() const
+ { return myPoint; }
+ /// \brief Return PlaneGCS point to change
+ GCSPointPtr& changeEntity()
+ { return myPoint; }
+
+ /// \brief Return ID of current entity
+ virtual EntityID id() const
+ { return myID; }
+ /// \brief Change ID of the entity
+ void setId(EntityID theID)
+ { myID = theID; }
+
+ /// \brief Change group for the entity
+ virtual void setGroup(const GroupID& theGroup);
+ /// \brief Return identifier of the group the entity belongs to
+ virtual GroupID group() const
+ { return myGroup; }
+
+ /// \brief Return type of current entity
+ virtual SketchSolver_EntityType type() const
+ { return ENTITY_POINT; }
+
+ /// \brief Verify the feature is used in the entity
+ virtual bool isUsed(FeaturePtr theFeature) const
+ { return false; }
+ /// \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 EntityWrapperPtr& theOther);
+
+private:
+ EntityID myID;
+ GroupID myGroup;
+ GCSPointPtr myPoint;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_ScalarWrapper.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_ParameterWrapper.h>
+
+
+
+PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(
+ const AttributePtr theAttribute,
+ const ParameterWrapperPtr theParam)
+{
+ myBaseAttribute = theAttribute;
+ myParameters.assign(1, theParam);
+}
+
+void PlaneGCSSolver_ScalarWrapper::setGroup(const GroupID& theGroup)
+{
+ myGroup = theGroup;
+ myParameters.front()->setGroup(theGroup);
+}
+
+double* PlaneGCSSolver_ScalarWrapper::scalar() const
+{
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(myParameters.front());
+ return aParam->parameter();
+}
+
+bool PlaneGCSSolver_ScalarWrapper::isUsed(AttributePtr theAttribute) const
+{
+ return isBase(theAttribute);
+}
+
+bool PlaneGCSSolver_ScalarWrapper::isEqual(const EntityWrapperPtr& theOther)
+{
+ if (type() != theOther->type())
+ 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 PlaneGCSSolver_ScalarWrapper::update(const EntityWrapperPtr& theOther)
+{
+ bool isUpdated = false;
+ 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: PlaneGCSSolver_ScalarWrapper.h
+// Created: 16 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_ScalarWrapper_H_
+#define PlaneGCSSolver_ScalarWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <SketchSolver_IEntityWrapper.h>
+
+/**
+ * Wrapper providing operations with PlaneGCS scalars.
+ */
+class PlaneGCSSolver_ScalarWrapper : public SketchSolver_IEntityWrapper
+{
+public:
+ PlaneGCSSolver_ScalarWrapper(const AttributePtr theAttribute, const ParameterWrapperPtr theParam);
+
+ /// \brief Return PlaneGCS parameter
+ double* scalar() const;
+
+ /// \brief Return ID of current entity
+ virtual EntityID id() const
+ { return myID; }
+ /// \brief Change ID of the entity
+ void setId(EntityID theID)
+ { myID = theID; }
+
+ /// \brief Change group for the entity
+ virtual void setGroup(const GroupID& theGroup);
+ /// \brief Return identifier of the group the entity belongs to
+ virtual GroupID group() const
+ { return myGroup; }
+
+ /// \brief Return type of current entity
+ virtual SketchSolver_EntityType type() const
+ { return ENTITY_SCALAR; }
+
+ /// \brief Verify the feature is used in the entity
+ virtual bool isUsed(FeaturePtr theFeature) const
+ { return false; }
+ /// \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 EntityWrapperPtr& theOther);
+
+private:
+ EntityID myID;
+ GroupID myGroup;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Solver.cpp
+// Created: 14 Dec 2014
+// Author: Artem ZHIDKOV
+
+#include "PlaneGCSSolver_Solver.h"
+#include <Events_LongOp.h>
+
+
+PlaneGCSSolver_Solver::~PlaneGCSSolver_Solver()
+{
+ clear();
+}
+
+void PlaneGCSSolver_Solver::clear()
+{
+ std::set<GCS::Constraint*>::const_iterator anIt = myConstraints.begin();
+ for (; anIt != myConstraints.end(); ++anIt)
+ myEquationSystem.removeConstraint(*anIt);
+ myConstraints.clear();
+ myParameters.clear();
+}
+
+void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
+{
+ GCS::Constraint* aConstraint = theConstraint.get();
+ if (myConstraints.find(aConstraint) != myConstraints.end())
+ return; // constraint already exists, no need to add it again
+
+ myEquationSystem.addConstraint(aConstraint);
+ myConstraints.insert(aConstraint);
+}
+
+void PlaneGCSSolver_Solver::removeConstraint(GCSConstraintPtr theConstraint)
+{
+ GCS::Constraint* aConstraint = theConstraint.get();
+ if (myConstraints.find(aConstraint) == myConstraints.end())
+ return; // no constraint, no need to remove it
+
+ myEquationSystem.removeConstraint(aConstraint);
+ myConstraints.erase(aConstraint);
+}
+
+SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
+{
+ if (myConstraints.empty())
+ return STATUS_EMPTYSET;
+ if (myParameters.empty())
+ return STATUS_INCONSISTENT;
+
+//// myEquationSystem.calculateFaileds = myFindFaileds ? 1 : 0;
+
+ Events_LongOp::start(this);
+ GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
+ Events_LongOp::end(this);
+
+ SketchSolver_SolveStatus aStatus;
+ if (aResult == GCS::Success) {
+ myEquationSystem.applySolution();
+ aStatus = STATUS_OK;
+ } else {
+ myEquationSystem.undoSolution();
+ aStatus = STATUS_FAILED;
+ }
+ return aStatus;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Solver.h
+// Created: 14 Dec 2014
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Solver_H_
+#define PlaneGCSSolver_Solver_H_
+
+#include <SketchSolver_ISolver.h>
+#include <PlaneGCSSolver_Defs.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 <GCS.h>
+
+////#include <vector>
+
+/**
+ * The main class that performs the high-level operations for connection to the PlaneGCS.
+ */
+class PlaneGCSSolver_Solver : public SketchSolver_ISolver
+{
+public:
+ PlaneGCSSolver_Solver() {}
+ ~PlaneGCSSolver_Solver();
+
+ /// \brief Clear system of equations
+ void clear();
+
+ /// \brief Add constraint to the system of equations
+ void addConstraint(GCSConstraintPtr theConstraint);
+
+ /// \brief Remove constraint from the system of equations
+ void removeConstraint(GCSConstraintPtr theConstraint);
+
+ /// \brief Initialize list of unknowns
+ void setParameters(const GCS::VEC_pD& theParams)
+ { myParameters = theParams; }
+
+ /** \brief Solve the set of equations
+ * \return identifier whether solution succeeded
+ */
+ virtual SketchSolver_SolveStatus solve();
+
+private:
+ GCS::VEC_pD myParameters; ///< list of unknowns
+ std::set<GCS::Constraint*> myConstraints; ///< list of constraints already processed by the system
+ GCS::System myEquationSystem; ///< set of equations for solving in FreeGCS
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Storage.cpp
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_Storage.h>
+#include <PlaneGCSSolver_Builder.h>
+#include <PlaneGCSSolver_Solver.h>
+#include <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_ParameterWrapper.h>
+
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+////#include <ModelAPI_AttributeRefAttr.h>
+////#include <ModelAPI_Feature.h>
+////#include <ModelAPI_ResultConstruction.h>
+
+#include <SketchPlugin_Arc.h>
+////#include <SketchPlugin_Circle.h>
+////#include <SketchPlugin_Line.h>
+////#include <SketchPlugin_Point.h>
+////
+////#ifndef OBSOLETE
+////#include <SketchPlugin_ConstraintAngle.h>
+////#endif
+
+#include <cmath>
+
+////#ifdef OBSOLETE
+/////** \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 constriants to be different
+////static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
+////#endif
+
+
+PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup)
+ : SketchSolver_Storage(theGroup),
+ myEntityLastID(EID_SKETCH)
+{
+}
+
+void PlaneGCSSolver_Storage::addConstraint(
+ ConstraintPtr theConstraint,
+ std::list<ConstraintWrapperPtr> theSolverConstraints)
+{
+ SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
+
+ // update point-point coincidence
+ 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 PlaneGCSSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
+{
+ bool isUpdated = false;
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
+
+ // point-Line distance should be positive
+ if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
+ aConstraint->setValue(-aConstraint->value());
+
+ // make value of constraint unchangeable
+ ParameterWrapperPtr aValue = aConstraint->valueParameter();
+ if (aValue)
+ isUpdated = update(aValue) || isUpdated;
+
+ // update constrained entities
+ std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
+ std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
+ for (; anIt != anEntities.end(); ++anIt)
+ isUpdated = update(*anIt) || isUpdated;
+
+ return isUpdated;
+}
+
+/// \brief Update coordinates of the point or scalar using its base attribute
+static bool updateValues(EntityWrapperPtr& theEntity)
+{
+ bool isUpdated = false;
+ AttributePtr anAttr = theEntity->baseAttribute();
+ const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
+
+ double aCoord[2];
+
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ if (aPoint2D) {
+ aCoord[0] = aPoint2D->x();
+ aCoord[1] = aPoint2D->y();
+ } else {
+ AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
+ if (aScalar)
+ aCoord[0] = aScalar->value();
+ }
+
+ std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
+ for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
+ if (fabs((*anIt)->value() - aCoord[i]) > tolerance) {
+ (*anIt)->setValue(aCoord[i]);
+ isUpdated = true;
+ }
+ return isUpdated;
+}
+
+bool PlaneGCSSolver_Storage::update(EntityWrapperPtr& theEntity)
+{
+ if (theEntity->type() == ENTITY_SKETCH)
+ return true; // sketch is not necessary for PlaneGCS, so it is always says true
+
+ bool isUpdated = false;
+
+ if (theEntity->baseAttribute()) {
+ isUpdated = updateValues(theEntity);
+ if (isUpdated)
+ setNeedToResolve(true);
+ }
+
+ // update parameters
+ std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
+ std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
+ for (; aPIt != aParams.end(); ++aPIt)
+ isUpdated = update(*aPIt) || isUpdated;
+
+ // update sub-entities
+ std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
+ std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
+ for (; aSIt != aSubEntities.end(); ++aSIt)
+ isUpdated = update(*aSIt) || isUpdated;
+
+ // additional constraints for the arc processing
+ if (theEntity->type() == ENTITY_ARC)
+ processArc(theEntity);
+
+ // Change entity's ID, if necessary
+ if (theEntity->id() == EID_UNKNOWN) {
+ if (theEntity->type() == ENTITY_POINT) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+ aPoint->setId(++myEntityLastID);
+ } else if (theEntity->type() == ENTITY_SCALAR) {
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
+ aScalar->setId(++myEntityLastID);
+ } else {
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+ aGCSEnt->setId(++myEntityLastID);
+ }
+ }
+ return isUpdated;
+}
+
+bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr& theParameter)
+{
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
+ if (aParam->isProcessed())
+ return false;
+ if (theParameter->group() != myGroupID || theParameter->isParametric())
+ myConst.push_back(aParam->parameter());
+ else
+ myParameters.push_back(aParam->parameter());
+ aParam->setProcessed(true);
+ return true;
+}
+
+
+bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
+{
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
+
+ bool isFullyRemoved = true;
+ const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
+ std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
+ for (; aSIt != aSubs.end(); ++ aSIt)
+ isFullyRemoved = remove(*aSIt) && isFullyRemoved;
+
+ if (aConstraint->valueParameter())
+ isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
+ if (!isFullyRemoved &&
+ (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
+ isFullyRemoved = true;
+ if (isFullyRemoved) {
+ setNeedToResolve(true);
+ myRemovedConstraints.insert(myRemovedConstraints.end(),
+ aConstraint->constraints().begin(), aConstraint->constraints().end());
+ }
+ return isFullyRemoved;
+}
+
+bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
+{
+ if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
+ (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
+ return false;
+
+ bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
+ if (isFullyRemoved && theEntity->id() == myEntityLastID)
+ --myEntityLastID;
+ return isFullyRemoved;
+}
+
+bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
+{
+ std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
+ if (aParam->isProcessed()) {
+ double* aValPtr = aParam->parameter();
+ GCS::VEC_pD::iterator anIt = myParameters.begin();
+ for (; anIt != myParameters.end(); ++anIt)
+ if (*anIt == aValPtr)
+ break;
+ if (anIt != myParameters.end()) {
+ myParameters.erase(anIt);
+ setNeedToResolve(true);
+ }
+ else {
+ for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
+ if (*anIt == aValPtr)
+ break;
+ if (anIt != myConst.end()) {
+ myConst.erase(anIt);
+ setNeedToResolve(true);
+ }
+ }
+ }
+ aParam->setProcessed(false);
+ return true;
+}
+
+
+void PlaneGCSSolver_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 {
+//// std::list<ParameterWrapperPtr> aSlaveParams = theSlave->parameters();
+//// theSlave->setParameters(theMaster->parameters());
+////
+//// // Remove slave's parameters
+//// std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
+//// for (; aParIt != aSlaveParams.end(); ++aParIt)
+//// remove(*aParIt);
+
+ aMasterFound->second.insert(theSlave);
+ }
+}
+
+
+void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
+{
+ theEntity->setGroup(theGroup);
+ if (theGroup == myGroupID)
+ makeVariable(theEntity);
+ else
+ makeConstant(theEntity);
+}
+
+void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
+{
+//// // TODO
+}
+
+void PlaneGCSSolver_Storage::verifyFixed()
+{
+//// // TODO
+}
+
+
+#ifndef OBSOLETE
+////
+////void PlaneGCSSolver_Storage::changeConstraint(
+//// const ConstraintPtr& theConstraint,
+//// const std::vector<GCSConstraintPtr>& theGCSConstraints)
+////{
+//// myConstraintsMap[theConstraint] = theGCSConstraints;
+////}
+
+////void PlaneGCSSolver_Storage::addConstraint(GCSConstraintPtr theConstraint)
+////{
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
+//// aFound = myConstraintsMap.find(ConstraintPtr());
+//// if (aFound != myConstraintsMap.end())
+//// aFound->second.push_back(theConstraint);
+//// else {
+//// std::vector<GCSConstraintPtr> aConstrVec(1, theConstraint);
+//// myConstraintsMap[ConstraintPtr()] = aConstrVec;
+//// }
+////}
+
+////EntityID PlaneGCSSolver_Storage::changeEntity(const FeaturePtr& theEntity)
+////{
+//// if (!theEntity || !theEntity->data() || !theEntity->data()->isValid())
+//// return ENTITY_UNKNOWN;
+////
+//// // Firstly, try to find entity
+//// std::map<FeaturePtr, EntityID>::const_iterator aFound = myFeatureEntityMap.find(theEntity);
+////
+//// EntityID aNewEntID;
+//// if (aFound != myFeatureEntityMap.end())
+//// aNewEntID = aFound->second;
+////
+//// const std::string& aFeatureKind = theEntity->getKind();
+//// // SketchPlugin features
+//// if (aFeatureKind == SketchPlugin_Line::ID())
+//// updateLine(theEntity, aNewEntID);
+//// // Circle
+//// else if (aFeatureKind == SketchPlugin_Circle::ID())
+//// updateCircle(theEntity, aNewEntID);
+//// // Arc
+//// else if (aFeatureKind == SketchPlugin_Arc::ID())
+//// updateArc(theEntity, aNewEntID);
+//// // 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 anAttribute = theEntity->attribute(SketchPlugin_Point::COORD_ID());
+//// if (!anAttribute->isInitialized())
+//// return ENTITY_UNKNOWN;
+//// // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
+//// aNewEntID = changeEntity(anAttribute);
+//// }
+//// else // NOTE: Other types of entities are unsupported
+//// aNewEntID = ENTITY_UNKNOWN;
+////
+//// if (aNewEntID != ENTITY_UNKNOWN)
+//// myFeatureEntityMap[theEntity] = aNewEntID;
+//// return aNewEntID;
+////}
+////
+////EntityID PlaneGCSSolver_Storage::changeEntity(const AttributePtr& theEntity)
+////{
+//// if (!theEntity)
+//// return ENTITY_UNKNOWN;
+////
+//// AttributeRefAttrPtr aRefAttr =
+//// std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theEntity);
+//// if (aRefAttr) {
+//// if (aRefAttr->isObject()) {
+//// ResultConstructionPtr aRC =
+//// std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aRefAttr->object());
+//// if (!aRC)
+//// return ENTITY_UNKNOWN;
+//// return changeEntity(ModelAPI_Feature::feature(aRC));
+//// }
+//// else
+//// return changeEntity(aRefAttr->attr());
+//// }
+////
+//// EntityID aNewEntID = ENTITY_UNKNOWN;
+////
+//// // Firstly, try to find entity
+//// std::map<AttributePtr, EntityID>::const_iterator aFound = myAttributeEntityMap.find(theEntity);
+//// // Check type of attribute and create corresponding entity
+//// std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
+//// if (aPoint2D) {
+//// if (aFound != myAttributeEntityMap.end())
+//// aNewEntID = aFound->second;
+//// updatePoint(aPoint2D, aNewEntID);
+//// } else {
+//// AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
+//// if (aScalar) {
+//// // Check the scalar represents an angular value
+//// bool isAngular = false;
+//// FeaturePtr anOwner = ModelAPI_Feature::feature(aScalar->owner());
+//// if (anOwner && anOwner->getKind() == SketchPlugin_ConstraintAngle::ID())
+//// isAngular = true;
+////
+//// if (aFound != myAttributeEntityMap.end())
+//// aNewEntID = aFound->second;
+//// if (isAngular)
+//// updateAngle(aScalar, aNewEntID);
+//// else
+//// updateScalar(aScalar, aNewEntID);
+//// }
+//// }
+//// // NOTE: Other types of attributes are not supported
+////
+//// // Map attribute and new entity ID
+//// if (aFound == myAttributeEntityMap.end() && aNewEntID != ENTITY_UNKNOWN)
+//// myAttributeEntityMap[theEntity] = aNewEntID;
+//// return aNewEntID;
+////}
+
+
+////bool PlaneGCSSolver_Storage::removeConstraint(const ConstraintPtr& theConstraint)
+////{
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
+//// aFound = myConstraintsMap.find(theConstraint);
+//// if (aFound == myConstraintsMap.end())
+//// return true; // no constraint - nothing to remove
+////
+//// std::vector<GCSConstraintPtr> aConstrList = aFound->second;
+//// myConstraintsMap.erase(aFound);
+//// bool isFullyRemoved = removeEntity(theConstraint->attribute(SketchPlugin_Constraint::VALUE()));
+//// for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind)
+//// isFullyRemoved = removeEntity(theConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)))
+//// && isFullyRemoved;
+////
+//// myRemovedConstraints.insert(myRemovedConstraints.end(), aConstrList.begin(), aConstrList.end());
+////
+//// return isFullyRemoved;
+////}
+
+////bool PlaneGCSSolver_Storage::removeConstraint(GCSConstraintPtr theConstraint)
+////{
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::iterator
+//// aFound = myConstraintsMap.find(ConstraintPtr());
+//// if (aFound != myConstraintsMap.end()) {
+//// std::vector<GCSConstraintPtr>::iterator anIt = aFound->second.begin();
+//// for (; anIt != aFound->second.end(); ++anIt)
+//// if (*anIt == theConstraint) {
+//// aFound->second.erase(anIt);
+//// break;
+//// }
+//// }
+////
+//// myRemovedConstraints.push_back(theConstraint);
+//// return true;
+////}
+////
+////bool PlaneGCSSolver_Storage::removeEntity(const FeaturePtr& theFeature)
+////{
+//// if (!theFeature)
+//// return true;
+//// if (isUsed(theFeature))
+//// return false;
+////
+//// // remove feature and corresponding entity
+//// std::map<FeaturePtr, EntityID>::iterator aFound = myFeatureEntityMap.find(theFeature);
+//// if (aFound != myFeatureEntityMap.end()) {
+//// if (aFound->second.type == ARC) {
+//// // remove additional arc constraints
+//// std::map<EntityID, std::vector<GCSConstraintPtr> >::iterator aFoundArc =
+//// myArcConstraintMap.find(aFound->second);
+//// if (aFoundArc != myArcConstraintMap.end()) {
+//// myRemovedConstraints.insert(myRemovedConstraints.end(),
+//// aFoundArc->second.begin(), aFoundArc->second.end());
+//// myArcConstraintMap.erase(aFoundArc);
+//// }
+//// }
+//// myGCSEntities.erase(aFound->second);
+//// myFeatureEntityMap.erase(aFound);
+//// }
+////
+//// // remove feature's attributes
+//// bool isFullyRemoved = true;
+//// std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+//// std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+//// for (; anAttrIt != anAttributes.end(); ++anAttrIt)
+//// isFullyRemoved = removeEntity(*anAttrIt) && isFullyRemoved;
+//// return isFullyRemoved;
+////}
+////
+////bool PlaneGCSSolver_Storage::removeEntity(const AttributePtr& theAttribute)
+////{
+//// if (!theAttribute)
+//// return true;
+//// if (isUsed(theAttribute))
+//// return false;
+////
+//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+//// if (aRefAttr) {
+//// if (aRefAttr->isObject()) {
+//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+//// return removeEntity(aFeature);
+//// } else
+//// return removeEntity(aRefAttr->attr());
+//// }
+////
+//// // remove attribute and corresponding entity
+//// std::map<AttributePtr, EntityID>::iterator aFound = myAttributeEntityMap.find(theAttribute);
+//// if (aFound == myAttributeEntityMap.end())
+//// return true; // no attribute, nothing to remove
+////
+//// if (aFound->second.type == SCALAR || aFound->second.type == ANGLE) {
+//// std::map<EntityID, double*>::iterator aFoundScalar = myGCSScalars.find(aFound->second);
+//// if (aFoundScalar != myGCSScalars.end()) {
+//// removeParameters(aFoundScalar->second);
+//// myGCSScalars.erase(aFoundScalar);
+//// }
+//// }
+//// else if (aFound->second.type == POINT) {
+//// std::map<EntityID, GCSPointPtr>::iterator aFoundPoint = myGCSPoints.find(aFound->second);
+//// if (aFoundPoint != myGCSPoints.end()) {
+//// removeParameters(aFoundPoint->second->x, aFoundPoint->second->y);
+//// myGCSPoints.erase(aFoundPoint);
+//// }
+//// }
+////
+//// myAttributeEntityMap.erase(aFound);
+//// return true;
+////}
+
+////void PlaneGCSSolver_Storage::removeParameters(double* theParam1, double* theParam2)
+////{
+//// int aNbRemoved = 2;
+//// for (int ind = 0; ind < 2 && aNbRemoved > 0; ++ind) {
+//// GCS::VEC_pD& aList = ind ==0 ? myParameters : myConst;
+////
+//// GCS::VEC_pD::iterator aParIt = aList.begin();
+//// while (aNbRemoved > 0 && aParIt != aList.end()) {
+//// if (*aParIt != theParam1 && *aParIt != theParam2) {
+//// ++aParIt;
+//// continue;
+//// }
+////
+//// myRemovedParameters.push_back(*aParIt);
+//// int aShift = aParIt - aList.begin();
+//// aList.erase(aParIt);
+//// aParIt = aList.begin() + aShift;
+//// --aNbRemoved;
+//// }
+//// }
+////}
+
+
+////double* PlaneGCSSolver_Storage::createScalar(const AttributeDoublePtr& theScalar)
+////{
+//// double* aResult = new double;
+//// if (theScalar)
+//// *aResult = theScalar->value();
+//// myParameters.push_back(aResult);
+//// myNeedToResolve = true;
+//// return aResult;
+////}
+////
+////void PlaneGCSSolver_Storage::updateScalar(const AttributeDoublePtr& theScalar, EntityID& theID)
+////{
+//// std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
+//// if (aFound == myGCSScalars.end()) {
+//// // new scalar
+//// theID = ++myEntityLastID;
+//// theID.type = SCALAR;
+//// myGCSScalars[theID] = createScalar(theScalar);
+//// }
+//// else if (fabs(*(myGCSScalars[theID]) - theScalar->value()) > tolerance) {
+//// *(myGCSScalars[theID]) = theScalar->value();
+//// myNeedToResolve = true;
+//// }
+////}
+////
+////void PlaneGCSSolver_Storage::updateAngle(const AttributeDoublePtr& theAngle, EntityID& theID)
+////{
+//// std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
+//// if (aFound == myGCSScalars.end()) {
+//// // new scalar
+//// theID = ++myEntityLastID;
+//// theID.type = ANGLE;
+//// myGCSScalars[theID] = createScalar(theAngle);
+//// }
+//// else if (fabs(*(myGCSScalars[theID]) - theAngle->value()) > tolerance) {
+//// *(myGCSScalars[theID]) = theAngle->value();
+//// myNeedToResolve = true;
+//// }
+//// // Convert degrees to radians
+//// *(myGCSScalars[theID]) *= M_PI / 180.0;
+////}
+////
+////GCS::Point PlaneGCSSolver_Storage::createPoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint)
+////{
+//// GCS::Point aResult;
+//// aResult.x = new double(thePoint->x());
+//// aResult.y = new double(thePoint->y());
+////
+//// myParameters.push_back(aResult.x);
+//// myParameters.push_back(aResult.y);
+////
+//// myNeedToResolve = true;
+//// return aResult;
+////}
+////
+////void PlaneGCSSolver_Storage::updatePoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint,
+//// EntityID& theID)
+////{
+//// std::map<EntityID, GCSPointPtr>::iterator aFound = myGCSPoints.find(theID);
+//// if (aFound == myGCSPoints.end()) {
+//// // new point
+//// theID = ++myEntityLastID;
+//// theID.type = POINT;
+//// myGCSPoints[theID] = GCSPointPtr(new GCS::Point(createPoint(thePoint)));
+//// }
+//// else if (fabs(*(aFound->second->x) - thePoint->x()) > tolerance ||
+//// fabs(*(aFound->second->y) - thePoint->y()) > tolerance) {
+//// // update point
+//// *(aFound->second->x) = thePoint->x();
+//// *(aFound->second->y) = thePoint->y();
+//// myNeedToResolve = true;
+//// }
+////}
+////
+////void PlaneGCSSolver_Storage::updateLine(const FeaturePtr& theLine, EntityID& theID)
+////{
+//// std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theLine->attribute(SketchPlugin_Line::START_ID()));
+//// std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theLine->attribute(SketchPlugin_Line::END_ID()));
+//// if (!aStartAttr->isInitialized() || !aEndAttr->isInitialized()) {
+//// theID = ENTITY_UNKNOWN;
+//// return;
+//// }
+////
+//// std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end()) {
+//////// // new line
+//////// theID = ++myEntityLastID;
+//////// theID.type = LINE;
+////////
+//////// EntityID aStartID = changeEntity(aStartAttr);
+//////// EntityID aEndID = changeEntity(aEndAttr);
+//////// GCS::Point* aStart = getPoint(aStartID);
+//////// GCS::Point* aEnd = getPoint(aEndID);
+////////
+//////// std::shared_ptr<GCS::Line> aLine(new GCS::Line);
+//////// aLine->p1 = *aStart;
+//////// aLine->p2 = *aEnd;
+//////// myGCSEntities[theID] = aLine;
+//// }
+//// else {
+//// // update line parameters
+//// std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aStartAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aStartAttr, aFoundAttr->second);
+//// aFoundAttr = myAttributeEntityMap.find(aEndAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aEndAttr, aFoundAttr->second);
+//// }
+////}
+////
+////void PlaneGCSSolver_Storage::updateCircle(const FeaturePtr& theCircle, EntityID& theID)
+////{
+//// std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theCircle->attribute(SketchPlugin_Circle::CENTER_ID()));
+//// AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+//// theCircle->attribute(SketchPlugin_Circle::RADIUS_ID()));
+//// if (!aCenterAttr->isInitialized() || !aRadiusAttr->isInitialized()) {
+//// theID = ENTITY_UNKNOWN;
+//// return;
+//// }
+////
+//// std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end()) {
+//////// // new circle
+//////// theID = ++myEntityLastID;
+//////// theID.type = CIRCLE;
+////////
+//////// EntityID aCenterID = changeEntity(aCenterAttr);
+//////// EntityID aRadiusID = changeEntity(aRadiusAttr);
+//////// GCS::Point* aCenter = getPoint(aCenterID);
+//////// double* aRadius = getScalar(aRadiusID);
+////////
+//////// std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
+//////// aCircle->center = *aCenter;
+//////// aCircle->rad = aRadius;
+//////// myGCSEntities[theID] = aCircle;
+//// }
+//// else {
+//// // update circle parameters
+//// std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aCenterAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aCenterAttr, aFoundAttr->second);
+//// aFoundAttr = myAttributeEntityMap.find(aRadiusAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updateScalar(aRadiusAttr, aFoundAttr->second);
+//// }
+////}
+////
+////void PlaneGCSSolver_Storage::updateArc(const FeaturePtr& theArc, EntityID& theID)
+////{
+//// std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theArc->attribute(SketchPlugin_Arc::CENTER_ID()));
+//// std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theArc->attribute(SketchPlugin_Arc::START_ID()));
+//// std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+//// theArc->attribute(SketchPlugin_Arc::END_ID()));
+//// if (!aCenterAttr->isInitialized() ||
+//// !aStartAttr->isInitialized() ||
+//// !aEndAttr->isInitialized()) {
+//// theID = ENTITY_UNKNOWN;
+//// return;
+//// }
+////
+//// std::shared_ptr<GCS::Arc> anArc;
+//// std::map<EntityID, GCSCurvePtr>::iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end()) {
+//// // new arc
+//// theID = ++myEntityLastID;
+//// theID.type = ARC;
+////
+//// EntityID aCenterID = changeEntity(aCenterAttr);
+//// EntityID aStartID = changeEntity(aStartAttr);
+//// EntityID aEndID = changeEntity(aEndAttr);
+//// GCS::Point* aCenter = getPoint(aCenterID);
+//// GCS::Point* aStart = getPoint(aStartID);
+//// GCS::Point* aEnd = getPoint(aEndID);
+////
+//// anArc = std::shared_ptr<GCS::Arc>(new GCS::Arc);
+//// anArc->center = *aCenter;
+//// anArc->start = *aStart;
+//// anArc->end = *aEnd;
+//// anArc->startAngle = createScalar();
+//// anArc->endAngle = createScalar();
+//// anArc->rad = createScalar();
+//// myGCSEntities[theID] = anArc;
+////
+//// // Additional constraints for new arc
+//// processArc(theID);
+//// }
+//// else {
+//// // update arc parameters
+//// anArc = std::dynamic_pointer_cast<GCS::Arc>(aFound->second);
+//// std::map<AttributePtr, EntityID>::iterator aFoundAttr = myAttributeEntityMap.find(aCenterAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aCenterAttr, aFoundAttr->second);
+//// aFoundAttr = myAttributeEntityMap.find(aStartAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aStartAttr, aFoundAttr->second);
+//// aFoundAttr = myAttributeEntityMap.find(aEndAttr);
+//// if (aFoundAttr != myAttributeEntityMap.end())
+//// updatePoint(aEndAttr, aFoundAttr->second);
+//// }
+////
+//// // Calculate additional parameters necessary for FreeGCS
+//// std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
+//// std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
+//// std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
+////
+//// *(anArc->rad) = aCenterPnt->distance(aStartPnt);
+//// std::shared_ptr<GeomAPI_Edge> anArcEdge =
+//// std::dynamic_pointer_cast<GeomAPI_Edge>(theArc->lastResult()->shape());
+//// if (!anArcEdge) {
+//// theID = ENTITY_UNKNOWN;
+//// return;
+//// }
+//// anArcEdge->getRange(*(anArc->startAngle), *(anArc->endAngle));
+////}
+
+
+////double* PlaneGCSSolver_Storage::getScalar(const EntityID& theID) const
+////{
+//// std::map<EntityID, double*>::const_iterator aFound = myGCSScalars.find(theID);
+//// if (aFound == myGCSScalars.end())
+//// return 0;
+//// return aFound->second;
+////}
+////
+////GCS::Point* PlaneGCSSolver_Storage::getPoint(const EntityID& theID) const
+////{
+//// std::map<EntityID, GCSPointPtr>::const_iterator aFound = myGCSPoints.find(theID);
+//// if (aFound == myGCSPoints.end())
+//// return 0;
+//// return aFound->second.get();
+////}
+////
+////GCS::Line* PlaneGCSSolver_Storage::getLine(const EntityID& theID) const
+////{
+//// std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end())
+//// return 0;
+//// std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(aFound->second);
+//// if (!aLine)
+//// return 0;
+//// return aLine.get();
+////}
+////
+////GCS::Circle* PlaneGCSSolver_Storage::getCircle(const EntityID& theID) const
+////{
+//// std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end())
+//// return 0;
+//// std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(aFound->second);
+//// if (!aCircle)
+//// return 0;
+//// return aCircle.get();
+////}
+////
+////GCS::Arc* PlaneGCSSolver_Storage::getArc(const EntityID& theID) const
+////{
+//// std::map<EntityID, GCSCurvePtr>::const_iterator aFound = myGCSEntities.find(theID);
+//// if (aFound == myGCSEntities.end())
+//// return 0;
+//// std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(aFound->second);
+//// if (!anArc)
+//// return 0;
+//// return anArc.get();
+////}
+
+void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
+{
+ // Calculate additional parameters necessary for PlaneGCS
+ const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
+ std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
+ while ((*aSubIt)->type() == ENTITY_POINT) // search scalar entities
+ ++aSubIt;
+ double* aStartAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
+ double* aEndAngle = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
+ double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
+
+ FeaturePtr anArcFeature = theArc->baseFeature();
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
+
+ *aRadius = aCenterPnt->distance(aStartPnt);
+ if (!anArcFeature->lastResult())
+ return;
+ std::shared_ptr<GeomAPI_Edge> anArcEdge =
+ std::dynamic_pointer_cast<GeomAPI_Edge>(anArcFeature->lastResult()->shape());
+ if (!anArcEdge)
+ return;
+ anArcEdge->getRange(*aStartAngle, *aEndAngle);
+
+ // No need to add constraints if they are already exist
+ std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
+ aFound = myArcConstraintMap.find(theArc);
+ if (aFound != myArcConstraintMap.end())
+ return;
+
+ // Prepare additional constraints to produce the arc
+ std::vector<GCSConstraintPtr> anArcConstraints;
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
+ // Distances from center till start and end points are equal to radius
+ anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anArc->center, anArc->start, anArc->rad)));
+ anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anArc->center, anArc->end, anArc->rad)));
+ // Angles of start and end points should be equal to given angles
+ anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+ anArc->center, anArc->start, anArc->startAngle)));
+ anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+ anArc->center, anArc->end, anArc->endAngle)));
+
+ myArcConstraintMap[theArc] = anArcConstraints;
+}
+
+////const std::vector<GCSConstraintPtr>& PlaneGCSSolver_Storage::getConstraint(
+//// const ConstraintPtr& theConstraint) const
+////{
+//// static const std::vector<GCSConstraintPtr> aDummy;
+////
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
+//// aFound = myConstraintsMap.find(theConstraint);
+//// if (aFound == myConstraintsMap.end())
+//// return aDummy;
+//// return aFound->second;
+////}
+
+
+void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
+{
+ toggleEntity(theEntity, myParameters, myConst);
+}
+
+void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
+{
+ toggleEntity(theEntity, myConst, myParameters);
+}
+
+static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
+{
+ const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
+ std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
+ for (; aPIt != aParams.end(); ++aPIt)
+ theParamList.insert(
+ std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
+
+ const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
+ std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
+ for (; aSIt != aSubs.end(); ++aSIt)
+ getParametersToMove(*aSIt, theParamList);
+}
+
+void PlaneGCSSolver_Storage::toggleEntity(
+ const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
+{
+ std::set<double*> aParamsToMove;
+ getParametersToMove(theEntity, aParamsToMove);
+
+ GCS::VEC_pD::iterator anIt = theFrom.begin();
+ while (anIt != theFrom.end()) {
+ if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
+ ++anIt;
+ continue;
+ }
+
+ theTo.push_back(*anIt);
+ int aShift = anIt - theFrom.begin();
+ theFrom.erase(anIt);
+ anIt = theFrom.begin() + aShift;
+ }
+}
+
+
+void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
+{
+ std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
+
+ // initialize constraints
+ std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+ aCIt = myConstraintMap.begin();
+ for (; aCIt != myConstraintMap.end(); ++aCIt) {
+ std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
+ for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
+ std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
+ for (; anIt != aGCS->constraints().end(); ++anIt)
+ aSolver->addConstraint(*anIt);
+ }
+ }
+ // additional constraints for arcs
+ std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
+ anArcIt = myArcConstraintMap.begin();
+ for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
+ std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
+ for (; anIt != anArcIt->second.end(); ++anIt)
+ aSolver->addConstraint(*anIt);
+ }
+ // removed waste constraints
+ std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
+ for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
+ aSolver->removeConstraint(*aRemIt);
+ myRemovedConstraints.clear();
+//// // remove waste parameters
+//// std::list<double*>::const_iterator aRemParIt = myRemovedParameters.begin();
+//// for (; aRemParIt != myRemovedParameters.end(); ++aRemParIt)
+//// delete *aRemParIt;
+//// myRemovedParameters.clear();
+ // initialize unknowns
+ aSolver->setParameters(myParameters);
+}
+
+void PlaneGCSSolver_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) {
+ // the external feature always should keep the up to date values, so,
+ // refresh from the solver is never needed
+ if (anIt->first.get()) {
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
+ if (aSketchFeature.get() && aSketchFeature->isExternal())
+ continue;
+ }
+
+ // 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) {
+ if (!theFixedOnly || (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
+ aCoords[i] = (*aParIt)->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]);
+ // Find points coincident with this one (probably not in GID_OUTOFGROUP)
+ std::map<AttributePtr, EntityWrapperPtr>::const_iterator aLocIt =
+ theFixedOnly ? myAttributeMap.begin() : anIt;
+ for (++aLocIt; aLocIt != myAttributeMap.end(); ++aLocIt)
+ if (anIt->second->id() == aLocIt->second->id()) {
+ aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLocIt->first);
+ if (aPoint2D)
+ 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;
+ }
+ }
+
+ //blockEvents(false);
+}
+
+EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
+ EntityWrapperPtr theBase, double theCoeff)
+{
+ std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_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;
+ aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
+ aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
+ // Create entity (parameters are not filled)
+ GCSPointPtr aPnt(new GCS::Point);
+ aPnt->x = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
+ aPnt->y = std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
+
+ EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
+ aResult->setGroup(myGroupID);
+ aResult->setParameters(aParameters);
+
+ update(aResult);
+ return aResult;
+}
+
+////bool PlaneGCSSolver_Storage::isInteract(AttributePtr theAttribute) const
+////{
+//// std::map<AttributePtr, EntityID>::const_iterator aFound = myAttributeEntityMap.find(theAttribute);
+//// if (aFound != myAttributeEntityMap.end())
+//// return true;
+////
+//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+//// if (!aRefAttr)
+//// return false;
+//// if (aRefAttr->isObject()) {
+//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+//// if (!aFeature)
+//// return false;
+//// return isInteract(aFeature);
+//// }
+////
+//// return isInteract(aRefAttr->attr());
+////}
+////
+////bool PlaneGCSSolver_Storage::isInteract(FeaturePtr theFeature) const
+////{
+//// if (myFeatureEntityMap.find(theFeature) != myFeatureEntityMap.end())
+//// return true;
+//// std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+//// std::list<AttributePtr>::iterator anIt = anAttributes.begin();
+//// for (; anIt != anAttributes.end(); ++anIt)
+//// if (isInteract(*anIt))
+//// return true;
+//// return false;
+////}
+
+
+////bool PlaneGCSSolver_Storage::isUsed(const FeaturePtr& theFeature) const
+////{
+//// // There is checked only the feature itself, not its attributes.
+//// // The attributes should be checked separately.
+////
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
+//// aCIt = myConstraintsMap.begin();
+//// for (; aCIt != myConstraintsMap.end(); ++aCIt) {
+//// if (!aCIt->first)
+//// continue;
+//// for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind) {
+//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+//// aCIt->first->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)));
+//// if (aRefAttr && aRefAttr->isObject()) {
+//// FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
+//// if (aFeat == theFeature)
+//// return true;
+//// }
+//// }
+//// }
+//// return false;
+////}
+////
+////bool PlaneGCSSolver_Storage::isUsed(const AttributePtr& theAttribute) const
+////{
+//// // Check whether the attribute is used by constraints
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >::const_iterator
+//// aCIt = myConstraintsMap.begin();
+//// for (; aCIt != myConstraintsMap.end(); ++aCIt) {
+//// if (!aCIt->first)
+//// continue;
+//// if (aCIt->first->attribute(SketchPlugin_Constraint::VALUE()) == theAttribute)
+//// return true;
+//// for (int ind = 0; ind < CONSTRAINT_ATTR_SIZE; ++ind) {
+//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+//// aCIt->first->attribute(SketchPlugin_Constraint::ATTRIBUTE(ind)));
+//// if (!aRefAttr)
+//// continue;
+//// if (aRefAttr == theAttribute ||
+//// (!aRefAttr->isObject() && aRefAttr->attr() == theAttribute))
+//// return true;
+//// }
+//// }
+////
+//// // Check whether the attribute is used by features
+//// std::map<FeaturePtr, EntityID>::const_iterator aFIt = myFeatureEntityMap.begin();
+//// for (; aFIt != myFeatureEntityMap.end(); ++aFIt) {
+//// std::list<AttributePtr> anAttrs =
+//// aFIt->first->data()->attributes(GeomDataAPI_Point2D::typeId());
+//// std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
+//// for (; anIt != anAttrs.end(); ++anIt)
+//// if (*anIt == theAttribute)
+//// return true;
+//// }
+////
+//// return false;
+////}
+
+
+////void PlaneGCSSolver_Storage::blockEvents(bool isBlocked)
+////{
+//// std::map<FeaturePtr, EntityID>::iterator aFIt = myFeatureEntityMap.begin();
+//// for (; aFIt != myFeatureEntityMap.end(); ++aFIt)
+//// if (aFIt->first->data() && aFIt->first->data()->isValid())
+//// aFIt->first->data()->blockSendAttributeUpdated(isBlocked);
+////
+//// std::map<AttributePtr, EntityID>::iterator anAIt = myAttributeEntityMap.begin();
+//// for (; anAIt != myAttributeEntityMap.end(); ++anAIt)
+//// if (anAIt->first->owner() && anAIt->first->owner()->data() &&
+//// anAIt->first->owner()->data()->isValid())
+//// anAIt->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+////}
+
+
+#else
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Storage.h
+// Created: 14 Dec 2015
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Storage_H_
+#define PlaneGCSSolver_Storage_H_
+
+#include <PlaneGCSSolver_Defs.h>
+
+#include <SketchSolver.h>
+#include <SketchSolver_Storage.h>
+#include <SketchSolver_ISolver.h>
+
+////#include <GeomDataAPI_Point2D.h>
+////#include <ModelAPI_Attribute.h>
+////#include <ModelAPI_AttributeDouble.h>
+////#include <ModelAPI_Feature.h>
+////#include <SketchPlugin_Constraint.h>
+////
+////#include <Geo.h>
+////#include <Util.h>
+////
+////#include <list>
+////#include <memory>
+////#include <set>
+////#include <vector>
+
+////#ifndef OBSOLETE
+////#include <Constraints.h>
+////
+////typedef std::shared_ptr<GCS::Point> GCSPointPtr;
+////typedef std::shared_ptr<GCS::Curve> GCSCurvePtr;
+////typedef GCS::Constraint* GCSConstraintPtr;
+////#endif
+
+/** \class PlaneGCSSolver_Storage
+ * \ingroup Plugins
+ * \brief Contains all necessary data in PlaneGCS format to solve a single group of constraints
+ */
+class PlaneGCSSolver_Storage : public SketchSolver_Storage
+{
+public:
+ PlaneGCSSolver_Storage(const GroupID& theGroup);
+
+// ============= Inherited from SketchSolver_Storage =============
+
+ /// \brief Change mapping between constraint from SketchPlugin and
+ /// the list of constraints applicable for corresponding solver.
+ /// Derived here to update point-point coincidence.
+ /// \param theConstraint [in] original SketchPlugin constraint
+ /// \param theSolverConstraints [in] list of solver's constraints
+ virtual void addConstraint(ConstraintPtr theConstraint,
+ std::list<ConstraintWrapperPtr> theSolverConstraints);
+
+ /// \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 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 Shows the storage has the same constraint twice
+ virtual bool hasDuplicatedConstraint() const
+ { return false; }
+
+ /// \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);
+
+ /// \brief Initialize solver by constraints, entities and parameters
+ virtual void initializeSolver(SolverPtr theSolver);
+
+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 =============
+
+
+
+#ifndef OBSOLETE
+
+//// /** \brief Add or change constraint and corresponding GCS constraints to the storage
+//// * \param theConstraint [in] base SketchPlugin constraint
+//// * \param theGCSConstraints [in] list of GCS constraints created by SketchSolver constraint
+//// */
+//// void changeConstraint(const ConstraintPtr& theConstraint,
+//// const std::vector<GCSConstraintPtr>& theGCSConstraints);
+
+//// /** \brief Add GCS constraint not related to any SketchPlugin constraint.
+//// * For example, it may be related to the moved feature.
+//// * \param theConstraint [in] GCS constraint
+//// */
+//// void addConstraint(GCSConstraintPtr theConstraint);
+
+//// /** \brief Convert SketchPlugin_Feature to the corresponding entity in FreeGCS
+//// * \param theEntity [in] feature to convert
+//// * \return ID of created or updated entity
+//// */
+//// EntityID changeEntity(const FeaturePtr& theEntity);
+//// /** \brief Convert ModelAPI_Attribute to the corresponding entity in FreeGCS
+//// * \param theEntity [in] attribute to convert
+//// * \return ID of created or updated entity
+//// */
+//// EntityID changeEntity(const AttributePtr& theEntity);
+
+//// /** \brief Remove constraint and corresponding GCS constraints
+//// * \param theConstraint [in] constraint to remove
+//// * \return \c true, if the constraint is fully removed,
+//// * \c false, if there are available entities used by other constraints
+//// */
+//// bool removeConstraint(const ConstraintPtr& theConstraint);
+//// /** \brief Remove GCS constraint
+//// * \param theConstraint [in] constraint to remove
+//// * \return \c true, if the constraint is fully removed
+//// */
+//// bool removeConstraint(GCSConstraintPtr theConstraint);
+//// /** \brief Remove feature and corresponding GCS entities
+//// * \param theFeature [in] feature to remove
+//// * \return \c true, if the feature is fully removed,
+//// * \c false, if there are available entities used by other constraints or features
+//// */
+//// bool removeEntity(const FeaturePtr& theFeature);
+//// /** \brief Remove attribute and corresponding GCS entities
+//// * \param theAttribute [in] attribute to remove
+//// * \return \c true, if the attribute is removed,
+//// * \c false, if it is used by existent features or constraints
+//// */
+//// bool removeEntity(const AttributePtr& theAttribute);
+
+ /// \brief Move parameters of the entity to the constants
+ void makeConstant(const EntityWrapperPtr& theEntity);
+ /// \brief Move parameters of the entity to the variables
+ void makeVariable(const EntityWrapperPtr& theEntity);
+
+//// /// \brief Return scalar by its ID or null pointer
+//// double* getScalar(const EntityID& theID) const;
+//// /// \brief Return point by its ID or null pointer
+//// GCS::Point* getPoint(const EntityID& theID) const;
+//// /// \brief Return line by its ID or null pointer
+//// GCS::Line* getLine(const EntityID& theID) const;
+//// /// \brief Return circle by its ID or null pointer
+//// GCS::Circle* getCircle(const EntityID& theID) const;
+//// /// \brief Return arc by its ID or null pointer
+//// GCS::Arc* getArc(const EntityID& theID) const;
+////
+//// /// \brief Return list of GCS constraints corresponding to the given
+//// const std::vector<GCSConstraintPtr>& getConstraint(const ConstraintPtr& theConstraint) const;
+
+//// /// \brief Verifies, the attribute is available in current storage
+//// bool isInteract(AttributePtr theAttribute) const;
+//// /// \brief Verifies, the feature is available in current storage
+//// bool isInteract(FeaturePtr theFeature) const;
+
+private:
+//// /** \brief Creates scalar parameter in the list of parameters
+//// * \param theScalar [in] value to be converted
+//// * \return pointer to new scalar
+//// */
+//// double* createScalar(const AttributeDoublePtr& theScalar = AttributeDoublePtr());
+//// /** \brief Creates two parameters in the list of parameters to store point coordinates
+//// * \param thePoint [in] point to be converted
+//// * \return FreeGCS point
+//// */
+//// GCS::Point createPoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint);
+//// /** \brief Creates or updates a scalar value
+//// * \param theScalar [in] attribute to update scalar value
+//// * \param theID [in] ID of scalar to be updated
+//// */
+//// void updateScalar(const AttributeDoublePtr& theScalar, EntityID& theID);
+//// /** \brief Creates or updates an angular value
+//// * \param theAngle [in] attribute to update scalar value
+//// * \param theID [in] ID of scalar to be updated
+//// */
+//// void updateAngle(const AttributeDoublePtr& theAngle, EntityID& theID);
+//// /** \brief Creates or updates parameters of the point
+//// * \param thePoint [in] point used to update parameters
+//// * \param theID [in] ID of FreeGCS entity to be updated
+//// */
+//// void updatePoint(const std::shared_ptr<GeomDataAPI_Point2D>& thePoint,
+//// EntityID& theID);
+//// /** \brief Creates or updates parameters of the line
+//// * \param theLine [in] line used to update parameters
+//// * \param theID [in/out] ID of FreeGCS entity to be updated (cleared if problems)
+//// */
+//// void updateLine(const FeaturePtr& theLine, EntityID& theID);
+//// /** \brief Creates or updates parameters of the circle
+//// * \param theLine [in] circle used to update parameters
+//// * \param theID [in/out] ID of FreeGCS entity to be updated (cleared if problems)
+//// */
+//// void updateCircle(const FeaturePtr& theCircle, EntityID& theID);
+//// /** \brief Creates or updates parameters of the arc
+//// * \param theLine [in] arc used to update parameters
+//// * \param theID [in/out] ID of FreeGCS entity to be updated (cleared if problems)
+//// */
+//// void updateArc(const FeaturePtr& theArc, EntityID& theID);
+
+//// /// \brief Check the feature is used by constraints
+//// bool isUsed(const FeaturePtr& theFeature) const;
+//// /// \brief Check the attribute is used by constraints or features
+//// bool isUsed(const AttributePtr& theAttribute) const;
+
+//// /// \brief Remove given parameter from the lists of parameters and constants
+//// void removeParameters(double* theParam1, double* theParam2 = 0);
+
+ /// \brief Move parameters of the entity from the list of variables to the list of constants
+ /// and vice versa
+ /// \param theEntity [in] entity to be changed
+ /// \param theFrom [out] source list
+ /// \param theTo [out] destination list
+ void toggleEntity(const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo);
+
+ /// \brief Create additional constraints for correct processing of arcs
+ /// \param theArc [in] updated arc
+ void processArc(const EntityWrapperPtr& theArc);
+
+private:
+ GCS::VEC_pD myParameters; ///< list of parameters
+ GCS::VEC_pD myConst; ///< list of constants
+ EntityID myEntityLastID; ///< identifier of last added entity
+
+//// std::map<ConstraintPtr, std::vector<GCSConstraintPtr> >
+//// myConstraintsMap; ///< map SketchPlugin constraints to corresponding GCS constraints
+////
+//// std::map<AttributePtr, EntityID> myAttributeEntityMap; ///< map attributes to corresponding entities
+//// std::map<FeaturePtr, EntityID> myFeatureEntityMap; ///< map features to corresponding entities
+////
+//// std::map<EntityID, double*> myGCSScalars; ///< list of scalar values and their IDs
+//// std::map<EntityID, GCSPointPtr> myGCSPoints; ///< list of points and their IDs
+//// std::map<EntityID, GCSCurvePtr> myGCSEntities; ///< list of lines, circles and arcs and their IDs
+
+ std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >
+ myArcConstraintMap; ///< additional constraints for correct processing of the arcs
+
+//// std::list<double*> myRemovedParameters; ///< list of removed parameters
+ std::list<GCSConstraintPtr> myRemovedConstraints; ///< list of removed constraints to notify solver
+
+#else
+
+// ================================================================================================
+// =================== OBSOLETE ===========================================================
+public:
+ PlaneGCSSolver_Storage();
+
+ /** \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 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 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
+ 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 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 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);
+
+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)
+
+ 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)
+#endif
+};
+
+#endif
const ParameterID PID_UNKNOWN = 0;
const EntityID EID_UNKNOWN = 0;
+const EntityID EID_SKETCH = 1;
const ConstraintID CID_UNKNOWN = 0;
#endif
enum SketchSolver_EntityType {
ENTITY_UNKNOWN = 0,
ENTITY_SCALAR,
+ ENTITY_ANGLE,
ENTITY_POINT,
ENTITY_NORMAL,
ENTITY_LINE,
/// the list of constraints applicable for corresponding solver.
/// \param theConstraint [in] original SketchPlugin constraint
/// \param theSolverConstraints [in] list of solver's constraints
- SKETCHSOLVER_EXPORT
+ SKETCHSOLVER_EXPORT virtual
void addConstraint(ConstraintPtr theConstraint,
std::list<ConstraintWrapperPtr> theSolverConstraints);
/// \brief Update the group for the given parameter
virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup) = 0;
+ /// \brief Verify the feature or any its attribute is used by constraint
+ SKETCHSOLVER_EXPORT bool isUsed(FeaturePtr theFeature) const;
+ /// \brief Verify the attribute is used by constraint
+ SKETCHSOLVER_EXPORT bool isUsed(AttributePtr theAttirubute) const;
+
private:
/// \brief Find the normal of the sketch
EntityWrapperPtr getNormal() 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 theAttirubute) const;
-
protected:
GroupID myGroupID; ///< identifier of the group, this storage belongs to
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved