-// Copyright (C) 2014-2019 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointArrayWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarArrayWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
#include <PlaneGCSSolver_ConstraintWrapper.h>
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintMiddle.h>
#include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_ConstraintPerpendicular.h>
#include <SketchSolver_ConstraintTangent.h>
#include <SketchSolver_ConstraintMultiRotation.h>
#include <SketchSolver_ConstraintMultiTranslation.h>
+#include <SketchSolver_ConstraintOffset.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.h>
+#include <SketchPlugin_Circle.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintMiddle.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
+#include <SketchPlugin_Offset.h>
+#include <SketchPlugin_Point.h>
+#include <GeomAPI_BSpline2d.h>
#include <GeomAPI_Circ2d.h>
#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Ellipse2d.h>
#include <GeomAPI_Lin2d.h>
#include <GeomAPI_Pnt2d.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeIntArray.h>
+
#include <cmath>
static ConstraintWrapperPtr
createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue);
static ConstraintWrapperPtr
createConstraintPointsCollinear(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters);
+static ConstraintWrapperPtr
+ createConstraintAngleBetweenCurves(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar);
+static GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray);
static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint);
+static GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray);
static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
static GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc);
-
-static double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2);
-
+static GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge);
return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_Offset::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintOffset(theConstraint));
}
// All other types of constraints
return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
new SketchSolver_ConstraintMovement(theMovedAttribute));
}
+std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
+ const std::pair<AttributePtr, int>& theMovedPointInArray)
+{
+ return std::shared_ptr<SketchSolver_ConstraintMovement>(
+ new SketchSolver_ConstraintMovement(theMovedPointInArray.first, theMovedPointInArray.second));
+}
+
ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint(
aResult = createConstraintCoincidence(aPoint1, aPoint2);
break;
case CONSTRAINT_PT_ON_CURVE:
- aResult = anEntity1 ? createConstraintPointOnEntity(theType, aPoint1, anEntity1):
- createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
+ aResult = anEntity1 ?
+ createConstraintPointOnEntity(theType, aPoint1, anEntity1, GCS_SCALAR_WRAPPER(theValue)) :
+ createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
break;
case CONSTRAINT_MIDDLE_POINT:
aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
case CONSTRAINT_PERPENDICULAR:
aResult = createConstraintPerpendicular(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
+ case CONSTRAINT_PERPENDICULAR_CURVES:
+ aResult = createConstraintAngleBetweenCurves(GCS_SCALAR_WRAPPER(theValue),
+ aPoint1, anEntity1, GCS_EDGE_WRAPPER(theEntity2));
+ break;
case CONSTRAINT_EQUAL_LINES:
case CONSTRAINT_EQUAL_ELLIPSES:
anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
}
+std::shared_ptr<GeomAPI_BSpline2d> PlaneGCSSolver_Tools::bspline(EntityWrapperPtr theEntity)
+{
+ if (theEntity->type() != ENTITY_BSPLINE)
+ return std::shared_ptr<GeomAPI_BSpline2d>();
+
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
+ std::shared_ptr<GCS::BSpline> aSpline =
+ std::dynamic_pointer_cast<GCS::BSpline>(anEntity->entity());
+
+ std::list<GeomPnt2dPtr> aPoles;
+ for (GCS::VEC_P::iterator anIt = aSpline->poles.begin(); anIt != aSpline->poles.end(); ++anIt)
+ aPoles.push_back(GeomPnt2dPtr(new GeomAPI_Pnt2d(*anIt->x, *anIt->y)));
+
+ std::list<double> aWeights;
+ for (GCS::VEC_pD::iterator anIt = aSpline->weights.begin();
+ anIt != aSpline->weights.end(); ++anIt)
+ aWeights.push_back(**anIt);
+
+ std::list<double> aKnots;
+ for (GCS::VEC_pD::iterator anIt = aSpline->knots.begin(); anIt != aSpline->knots.end(); ++anIt)
+ aKnots.push_back(**anIt);
+
+ std::list<int> aMultiplicities;
+ aMultiplicities.assign(aSpline->mult.begin(), aSpline->mult.end());
+
+ return std::shared_ptr<GeomAPI_BSpline2d>(
+ new GeomAPI_BSpline2d(aSpline->degree, aPoles, aWeights,
+ aKnots, aMultiplicities, aSpline->periodic));
+}
+
void PlaneGCSSolver_Tools::recalculateArcParameters(EntityWrapperPtr theArc)
{
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEdge =
case ENTITY_SCALAR:
case ENTITY_ANGLE:
return scalarParameters(GCS_SCALAR_WRAPPER(theEntity));
+ case ENTITY_SCALAR_ARRAY:
+ return scalarArrayParameters(theEntity);
case ENTITY_POINT:
return pointParameters(GCS_POINT_WRAPPER(theEntity));
+ case ENTITY_POINT_ARRAY:
+ return pointArrayParameters(theEntity);
case ENTITY_LINE:
return lineParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_CIRCLE:
return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_ELLIPTIC_ARC:
return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_BSPLINE:
+ return bsplineParameters(GCS_EDGE_WRAPPER(theEntity));
default: break;
}
return GCS::SET_pD();
}
+bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName,
+ const std::string& theOwnerName)
+{
+ if (theOwnerName == SketchPlugin_Arc::ID()) {
+ return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
+ theAttrName == SketchPlugin_Arc::START_ID() ||
+ theAttrName == SketchPlugin_Arc::END_ID() ||
+ theAttrName == SketchPlugin_Arc::REVERSED_ID();
+ }
+ else if (theOwnerName == SketchPlugin_Circle::ID()) {
+ return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
+ theAttrName == SketchPlugin_Circle::RADIUS_ID();
+ }
+ else if (theOwnerName == SketchPlugin_Line::ID()) {
+ return theAttrName == SketchPlugin_Line::START_ID() ||
+ theAttrName == SketchPlugin_Line::END_ID();
+ }
+ else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
+ return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
+ theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
+ }
+ else if (theOwnerName == SketchPlugin_EllipticArc::ID()) {
+ return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::REVERSED_ID();
+ }
+ else if (theOwnerName == SketchPlugin_BSpline::ID()) {
+ return theAttrName == SketchPlugin_BSpline::POLES_ID() ||
+ theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() ||
+ theAttrName == SketchPlugin_BSpline::KNOTS_ID() ||
+ theAttrName == SketchPlugin_BSpline::MULTS_ID() ||
+ theAttrName == SketchPlugin_BSpline::DEGREE_ID() ||
+ theAttrName == SketchPlugin_BSpline::START_ID() ||
+ theAttrName == SketchPlugin_BSpline::END_ID();
+ }
+ else if (theOwnerName == SketchPlugin_BSplinePeriodic::ID()) {
+ return theAttrName == SketchPlugin_BSplinePeriodic::POLES_ID() ||
+ theAttrName == SketchPlugin_BSplinePeriodic::WEIGHTS_ID() ||
+ theAttrName == SketchPlugin_BSplinePeriodic::KNOTS_ID() ||
+ theAttrName == SketchPlugin_BSplinePeriodic::MULTS_ID() ||
+ theAttrName == SketchPlugin_BSplinePeriodic::DEGREE_ID();
+ }
+
+ // suppose that all remaining features are points
+ return theAttrName == SketchPlugin_Point::COORD_ID();
+}
+
+/// \brief Update value
+bool PlaneGCSSolver_Tools::updateValue(const double& theSource, double& theDest,
+ const double theTolerance)
+{
+ bool isUpdated = fabs(theSource - theDest) > theTolerance;
+ if (isUpdated)
+ theDest = theSource;
+ return isUpdated;
+}
+
+
+double PlaneGCSSolver_Tools::distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
+{
+ double x = *thePnt1.x - *thePnt2.x;
+ double y = *thePnt1.y - *thePnt2.y;
+ return sqrt(x*x + y*y);
+}
+
+
+
+
+// ================ AttributeArray methods ==========================
+PlaneGCSSolver_Tools::AttributeArray::AttributeArray(AttributePtr theAttribute)
+{
+ myDouble = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
+ myInteger = std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(theAttribute);
+}
+
+bool PlaneGCSSolver_Tools::AttributeArray::isInitialized() const
+{
+ return (myDouble && myDouble->isInitialized()) || (myInteger && myInteger->isInitialized());
+}
+
+int PlaneGCSSolver_Tools::AttributeArray::size() const
+{
+ return myDouble.get() ? myDouble->size() : myInteger->size();
+}
+
+double PlaneGCSSolver_Tools::AttributeArray::value(const int theIndex) const
+{
+ return myDouble.get() ? myDouble->value(theIndex) : myInteger->value(theIndex);
+}
+
ConstraintWrapperPtr createConstraintPointOnEntity(
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue)
{
GCSConstraintPtr aNewConstr;
new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
break;
}
+ case ENTITY_BSPLINE: {
+ std::list<GCSConstraintPtr> aConstraints;
+ aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
+ *thePoint->point(), thePoint->point()->x, *theEntity->entity(), theValue->scalar())));
+ aConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
+ *thePoint->point(), thePoint->point()->y, *theEntity->entity(), theValue->scalar())));
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aConstraints, theType));
+ }
default:
return ConstraintWrapperPtr();
}
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
{
std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
- bool isLine1Rev = theConstraint->boolean(
- SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
- GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
- GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
-
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
- bool isLine2Rev = theConstraint->boolean(
- SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
- GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
- GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
- aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
+ aLine1->p1, aLine1->p2, aLine2->p1, aLine2->p2, theValue->scalar()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
}
+ConstraintWrapperPtr createConstraintAngleBetweenCurves(
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
+{
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintAngleViaPoint(
+ *theEntity1->entity(), *theEntity2->entity(), *thePoint->point(), theValue->scalar()));
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR_CURVES));
+}
+
ConstraintWrapperPtr createConstraintEqual(
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
aConstrList.push_back(GCSConstraintPtr(
new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
// update value of intermediate parameter
- theIntermed->setValue(distance(aLine1->p1, aLine1->p2));
+ theIntermed->setValue(PlaneGCSSolver_Tools::distance(aLine1->p1, aLine1->p2));
}
else if (theType == CONSTRAINT_EQUAL_ELLIPSES) {
std::shared_ptr<GCS::Ellipse> anEllipse1 =
aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
anEllipse2->center, anEllipse2->focus1, theIntermed->scalar())));
// update value of intermediate parameter
- theIntermed->setValue(distance(anEllipse1->center, anEllipse1->focus1));
+ theIntermed->setValue(PlaneGCSSolver_Tools::distance(anEllipse1->center, anEllipse1->focus1));
}
else {
std::shared_ptr<GCS::Circle> aCirc1 =
return aParams;
}
+GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray)
+{
+ ScalarArrayWrapperPtr anArray =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theArray);
+ return GCS::SET_pD(anArray->array().begin(), anArray->array().end());
+}
+
GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint)
{
GCS::SET_pD aParams;
return aParams;
}
+GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray)
+{
+ GCS::SET_pD aParams;
+ PointArrayWrapperPtr aPoints =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theArray);
+ for (std::vector<PointWrapperPtr>::const_iterator anIt = aPoints->array().begin();
+ anIt != aPoints->array().end(); ++anIt) {
+ GCS::SET_pD aPointParams = PlaneGCSSolver_Tools::parameters(*anIt);
+ aParams.insert(aPointParams.begin(), aPointParams.end());
+ }
+ return aParams;
+}
+
GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine)
{
GCS::SET_pD aParams;
return aParams;
}
-double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
+GCS::SET_pD bsplineParameters(const EdgeWrapperPtr& theEdge)
{
- double x = *thePnt1.x - *thePnt2.x;
- double y = *thePnt1.y - *thePnt2.y;
- return sqrt(x*x + y*y);
+ GCS::SET_pD aParams;
+
+ std::shared_ptr<GCS::BSpline> aBSpline =
+ std::dynamic_pointer_cast<GCS::BSpline>(theEdge->entity());
+
+ for (GCS::VEC_P::iterator it = aBSpline->poles.begin(); it != aBSpline->poles.end(); ++it) {
+ aParams.insert(it->x);
+ aParams.insert(it->y);
+ }
+ for (GCS::VEC_pD::iterator it = aBSpline->weights.begin(); it != aBSpline->weights.end(); ++it)
+ aParams.insert(*it);
+
+ return aParams;
}