Implementation of elliptical arc and processing its modification in 3D viewer.
#include <Geom_Ellipse.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <GeomLib_Tool.hxx>
#include <gp_Elips.hxx>
#define MY_ELIPS implPtr<gp_Elips>()
}
return aResult;
}
+
+const bool GeomAPI_Ellipse::parameter(const std::shared_ptr<GeomAPI_Pnt> thePoint,
+ const double theTolerance,
+ double& theParameter) const
+{
+ Handle(Geom_Ellipse) aCurve = new Geom_Ellipse(*MY_ELIPS);
+ return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt>(),
+ theTolerance, theParameter) == Standard_True;
+}
/// Project point on ellipse
GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt> project(
const std::shared_ptr<GeomAPI_Pnt>& thePoint) const;
+
+ /** \brief Computes the parameter of a given point on an ellipse. The point must be
+ * located either on the circle itself or relatively to the latter
+ * at a distance less than the tolerance value. Return FALSE if the point
+ * is beyond the tolerance limit or if computation fails.
+ * Max Tolerance value is currently limited to 1.e-4
+ * \param[in] thePoint point of origin.
+ * \param[in] theTolerance tolerance of computation.
+ * \param[out] theParameter resulting parameter.
+ */
+ GEOMAPI_EXPORT const bool parameter(const std::shared_ptr<GeomAPI_Pnt> thePoint,
+ const double theTolerance,
+ double& theParameter) const;
};
//! Pointer on the object
#include <Extrema_ExtElC2d.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>
+#include <GeomLib_Tool.hxx>
#include <gp_Ax22d.hxx>
#include <gp_Elips2d.hxx>
#include <Precision.hxx>
delete anExtema;
return aDistance;
}
+
+const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::project(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const
+{
+ std::shared_ptr<GeomAPI_Pnt2d> aResult;
+ if (!MY_ELLIPSE)
+ return aResult;
+
+ Handle(Geom2d_Ellipse) aEllipse = new Geom2d_Ellipse(*MY_ELLIPSE);
+
+ const gp_Pnt2d& aPoint = thePoint->impl<gp_Pnt2d>();
+
+ Geom2dAPI_ProjectPointOnCurve aProj(aPoint, aEllipse);
+ Standard_Integer aNbPoint = aProj.NbPoints();
+ if (aNbPoint > 0) {
+ gp_Pnt2d aNearest = aProj.NearestPoint();
+ aResult.reset(new GeomAPI_Pnt2d(aNearest.X(), aNearest.Y()));
+ }
+ return aResult;
+}
+
+const bool GeomAPI_Ellipse2d::parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+ const double theTolerance,
+ double& theParameter) const
+{
+ Handle(Geom2d_Ellipse) aCurve = new Geom2d_Ellipse(*MY_ELLIPSE);
+ return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt2d>(),
+ theTolerance, theParameter) == Standard_True;
+}
/// Returns major radius of the ellipse
GEOMAPI_EXPORT double majorRadius() const;
+ /// Project point on ellipse
+ GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt2d> project(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const;
+
+ /** \brief Computes the parameter of a given point on an ellipse. The point must be
+ * located either on the circle itself or relatively to the latter
+ * at a distance less than the tolerance value. Return FALSE if the point
+ * is beyond the tolerance limit or if computation fails.
+ * Max Tolerance value is currently limited to 1.e-4
+ * \param[in] thePoint point of origin.
+ * \param[in] theTolerance tolerance of computation.
+ * \param[out] theParameter resulting parameter.
+ */
+ GEOMAPI_EXPORT const bool parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+ const double theTolerance,
+ double& theParameter) const;
+
/// Calculate minimal distance between the ellipse and a line.
/// Return corresponding points on the ellipse and on the line.
GEOMAPI_EXPORT double distance(const std::shared_ptr<GeomAPI_Lin2d>& theLine,
//
#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Ax2.h>
+#include <GeomAPI_Ellipse.h>
+
#include <gp_Pln.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Edge.hxx>
aRes->setImpl(new TopoDS_Shape(anEdge));
return aRes;
}
+
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::ellipticArc(
+ const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius,
+ const std::shared_ptr<GeomAPI_Pnt>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt>& theEnd)
+{
+ std::shared_ptr<GeomAPI_Ax2> anAx2(new GeomAPI_Ax2(theCenter, theNormal, theMajorAxis));
+ GeomAPI_Ellipse anEllipse(anAx2, theMajorRadius, theMinorRadius);
+
+ GeomPointPtr aStartPnt = anEllipse.project(theStart);
+ GeomPointPtr aEndPnt = anEllipse.project(theEnd);
+
+ double aStartParam, aEndParam;
+ anEllipse.parameter(aStartPnt, Precision::Confusion(), aStartParam);
+ anEllipse.parameter(aEndPnt, Precision::Confusion(), aEndParam);
+
+ BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse.impl<gp_Elips>(), aStartParam, aEndParam);
+ GeomEdgePtr aRes(new GeomAPI_Edge);
+ TopoDS_Edge anEdge = anEdgeBuilder.Edge();
+ aRes->setImpl(new TopoDS_Shape(anEdge));
+ return aRes;
+}
const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
const double theMajorRadius,
const double theMinorRadius);
+
+
+ /// Creates elliptic edge
+ static std::shared_ptr<GeomAPI_Edge> ellipticArc(
+ const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius,
+ const std::shared_ptr<GeomAPI_Pnt>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt>& theEnd);
};
#endif
SketchPlugin_ConstraintTangent.h
SketchPlugin_ConstraintVertical.h
SketchPlugin_Ellipse.h
+ SketchPlugin_EllipticArc.h
SketchPlugin_ExternalValidator.h
SketchPlugin_Feature.h
SketchPlugin_IntersectionPoint.h
SketchPlugin_MacroArcReentrantMessage.h
SketchPlugin_MacroCircle.h
SketchPlugin_MacroEllipse.h
+ SketchPlugin_MacroEllipticArc.h
SketchPlugin_MultiRotation.h
SketchPlugin_MultiTranslation.h
SketchPlugin_Plugin.h
SketchPlugin_ConstraintTangent.cpp
SketchPlugin_ConstraintVertical.cpp
SketchPlugin_Ellipse.cpp
+ SketchPlugin_EllipticArc.cpp
SketchPlugin_ExternalValidator.cpp
SketchPlugin_Feature.cpp
SketchPlugin_IntersectionPoint.cpp
SketchPlugin_MacroArc.cpp
SketchPlugin_MacroCircle.cpp
SketchPlugin_MacroEllipse.cpp
+ SketchPlugin_MacroEllipticArc.cpp
SketchPlugin_MultiRotation.cpp
SketchPlugin_MultiTranslation.cpp
SketchPlugin_Plugin.cpp
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <SketchPlugin_EllipticArc.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt2d.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <cmath>
+
+static const double tolerance = 1e-7;
+
+
+SketchPlugin_EllipticArc::SketchPlugin_EllipticArc()
+: SketchPlugin_SketchEntity()
+{
+}
+
+void SketchPlugin_EllipticArc::initDerivedClassAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+
+ data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_FOCUS_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_RADIUS_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_RADIUS_ID());
+
+ data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+}
+
+void SketchPlugin_EllipticArc::execute()
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if(!aSketch) {
+ return;
+ }
+
+ // Calculate all characteristics of the ellipse.
+ fillCharacteristicPoints();
+
+ // Make a visible ellipse.
+ createEllipticArc(aSketch);
+}
+
+bool SketchPlugin_EllipticArc::isFixed() {
+ return data()->selection(EXTERNAL_ID())->context().get() != NULL;
+}
+
+void SketchPlugin_EllipticArc::attributeChanged(const std::string& theID) {
+ // the second condition for unability to move external segments anywhere
+ if (theID == EXTERNAL_ID() || isFixed()) {
+ std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+ if (!aSelection) {
+ // empty shape in selection shows that the shape is equal to context
+ ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+ if (anExtRes)
+ aSelection = anExtRes->shape();
+ }
+ // update arguments due to the selection value
+ if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+ std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
+ std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
+ aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
+ aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(START_POINT_ID()));
+ aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(END_POINT_ID()));
+ aEndAttr->setValue(sketch()->to2D(anEdge->lastPoint()));
+
+ real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
+ real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius());
+ }
+ }
+}
+
+bool SketchPlugin_EllipticArc::fillCharacteristicPoints()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+ if (!aCenterAttr->isInitialized() ||
+ !aFocusAttr->isInitialized() ||
+ !aMinorRadiusAttr->isInitialized()) {
+ return false;
+ }
+
+ double aMinorRadius = aMinorRadiusAttr->value();
+ if (aMinorRadius < tolerance) {
+ return false;
+ }
+
+ data()->blockSendAttributeUpdated(true);
+ GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+ GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+ GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+ aFocus2d->y() - aCenter2d->y()));
+ GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ double aFocalDist = aCenter2d->distance(aFocus2d);
+ double aMajorRadius = sqrt(aFocalDist * aFocalDist + aMinorRadius * aMinorRadius);
+ aMajorRadiusAttr->setValue(aMajorRadius);
+
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+ ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+ data()->blockSendAttributeUpdated(false);
+
+ return true;
+}
+
+void SketchPlugin_EllipticArc::createEllipticArc(SketchPlugin_Sketch* theSketch)
+{
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+ double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+ GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+ if (aFocus->distance(aCenter) > tolerance) {
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_POINT_ID()));
+
+ GeomPointPtr aStartPnt(theSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+ GeomPointPtr aEndPnt(theSketch->to3D(aEndAttr->x(), aEndAttr->y()));
+
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::ellipticArc(aCenter, aNormal, aMajorAxis,
+ aMajorRadius, aMinorRadius, aStartPnt, aEndPnt);
+ }
+ else {
+ // build circle instead of ellipse
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+ }
+
+ ResultConstructionPtr aResult = document()->createConstruction(data());
+ aResult->setShape(anEllipseShape);
+ aResult->setIsInHistory(false);
+ setResult(aResult);
+}
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SketchPlugin_EllipticArc_H_
+#define SketchPlugin_EllipticArc_H_
+
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+
+/**\class SketchPlugin_EllipticArc
+ * \ingroup Plugins
+ * \brief Feature for creation of the new elliptical arc in Sketch.
+ */
+class SketchPlugin_EllipticArc: public SketchPlugin_SketchEntity
+{
+ public:
+ /// Ellipse feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchEllipticArc");
+ return ID;
+ }
+
+ /// 2D point - center of the ellipse
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string ID("ellipse_center");
+ return ID;
+ }
+
+ /// 2D point - start point of elliptic arc
+ inline static const std::string& START_POINT_ID()
+ {
+ static const std::string ID("start_point");
+ return ID;
+ }
+ /// 2D point - end point of elliptic arc
+ inline static const std::string& END_POINT_ID()
+ {
+ static const std::string ID("end_point");
+ return ID;
+ }
+
+ /// 2D point - focus of the ellipse
+ inline static const std::string& FIRST_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_first_focus");
+ return ID;
+ }
+ /// 2D point - second focus of the ellipse
+ inline static const std::string& SECOND_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_second_focus");
+ return ID;
+ }
+
+ /// 2D point - start point of major axis
+ inline static const std::string& MAJOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_major_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of major axis
+ inline static const std::string& MAJOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_major_axis_end_point");
+ return ID;
+ }
+
+ /// 2D point - start point of minor axis
+ inline static const std::string& MINOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of minor axis
+ inline static const std::string& MINOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_end_point");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_minor_radius");
+ return ID;
+ }
+
+ /// Flag the arc is reversed
+ inline static const std::string& REVERSED_ID()
+ {
+ static const std::string ID("reversed");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_EllipticArc::ID();
+ return MY_KIND;
+ }
+
+ /// Returns true is sketch element is under the rigid constraint
+ SKETCHPLUGIN_EXPORT virtual bool isFixed();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Use plugin manager for features creation
+ SketchPlugin_EllipticArc();
+
+protected:
+ /// \brief Initializes attributes of derived class.
+ virtual void initDerivedClassAttributes();
+
+private:
+ bool fillCharacteristicPoints();
+
+ void createEllipticArc(SketchPlugin_Sketch* theSketch);
+};
+
+#endif
aEllipseFeature->execute();
// create auxiliary points
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::CENTER_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::FIRST_FOCUS_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::SECOND_FOCUS_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
- createAuxiliaryPoint(aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::CENTER_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::FIRST_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::SECOND_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
// create auxiliary axes
- createAuxiliaryAxis(aEllipseFeature,
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
- createAuxiliaryAxis(aEllipseFeature,
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
return aEllipseFeature;
}
-void SketchPlugin_MacroEllipse::createAuxiliaryPoint(const FeaturePtr& theEllipseFeature,
- const std::string& theEllipsePoint)
-{
- FeaturePtr aPointFeature = sketch()->addFeature(SketchPlugin_Point::ID());
- aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
- aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
-
- AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theEllipseFeature->attribute(theEllipsePoint));
-
- AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
- aCoord->setValue(anElPoint->x(), anElPoint->y());
-
- aPointFeature->execute();
- std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
- aPointFeature->data()->setName(aName);
- aPointFeature->lastResult()->data()->setName(aName);
-
- createInternalConstraint(anElPoint, aCoord);
-}
-
-void SketchPlugin_MacroEllipse::createAuxiliaryAxis(const FeaturePtr& theEllipseFeature,
- const std::string& theStartPoint,
- const std::string& theEndPoint)
-{
- FeaturePtr aLineFeature = sketch()->addFeature(SketchPlugin_Line::ID());
- aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
- aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
-
- AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theEllipseFeature->attribute(theStartPoint));
- AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theEllipseFeature->attribute(theEndPoint));
-
- AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineFeature->attribute(SketchPlugin_Line::START_ID()));
- aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
-
- AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineFeature->attribute(SketchPlugin_Line::END_ID()));
- aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
-
- aLineFeature->execute();
- std::string aName = theEllipseFeature->name() + "_" +
- (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
- aLineFeature->data()->setName(aName);
- aLineFeature->lastResult()->data()->setName(aName);
-
- createInternalConstraint(aStartPoint, aLineStart);
- createInternalConstraint(aEndPoint, aLineEnd);
-}
-
-void SketchPlugin_MacroEllipse::createInternalConstraint(const AttributePtr& thePoint1,
- const AttributePtr& thePoint2)
-{
- SketchPlugin_Tools::createConstraintAttrAttr(
- sketch(), SketchPlugin_ConstraintCoincidenceInternal::ID(), thePoint1, thePoint2);
-}
-
AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
{
SketchPlugin_Sketch* aSketch = sketch();
FeaturePtr createEllipseFeature();
- void createAuxiliaryPoint(const FeaturePtr& theEllipseFeature,
- const std::string& theEllipsePoint);
- void createAuxiliaryAxis(const FeaturePtr& theEllipseFeature,
- const std::string& theStartPoint,
- const std::string& theEndPoint);
-
- void createInternalConstraint(const AttributePtr& thePoint1, const AttributePtr& thePoint2);
-
private:
std::shared_ptr<GeomAPI_Pnt2d> myCenter;
std::shared_ptr<GeomAPI_Pnt2d> myFocus;
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <SketchPlugin_MacroEllipticArc.h>
+
+////#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_EllipticArc.h>
+////#include <SketchPlugin_Line.h>
+#include <SketchPlugin_MacroArcReentrantMessage.h>
+////#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Tools.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Events.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Vertex.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+
+
+const double paramTolerance = 1.e-4;
+const double PI = 3.141592653589793238463;
+
+
+SketchPlugin_MacroEllipticArc::SketchPlugin_MacroEllipticArc()
+ : SketchPlugin_SketchEntity(),
+ myMajorRadius(0.0),
+ myMinorRadius(0.0),
+ myParamDelta(0.0)
+{
+}
+
+void SketchPlugin_MacroEllipticArc::initAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(START_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+
+ data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
+ data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ boolean(REVERSED_ID())->setValue(false);
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID());
+ ModelAPI_Session::get()->validators()
+ ->registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID());
+}
+
+void SketchPlugin_MacroEllipticArc::execute()
+{
+ FeaturePtr anEllipse = createEllipticArcFeature();
+
+ // message to init reentrant operation
+ static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+ <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
+ aMessage->setCreatedFeature(anEllipse);
+ Events_Loop::loop()->send(aMessage);
+}
+
+void SketchPlugin_MacroEllipticArc::attributeChanged(const std::string& theID)
+{
+ static const int NB_POINTS = 4;
+ std::string aPointAttrName[NB_POINTS] = { CENTER_ID(),
+ MAJOR_AXIS_POINT_ID(),
+ START_POINT_ID(),
+ END_POINT_ID() };
+ std::string aPointRefName[NB_POINTS] = { CENTER_REF_ID(),
+ MAJOR_AXIS_POINT_REF_ID(),
+ START_POINT_REF_ID(),
+ END_POINT_REF_ID() };
+
+ int aNbInitialized = 0;
+ GeomPnt2dPtr anEllipsePoints[NB_POINTS];
+
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+ if (!aPointAttr->isInitialized())
+ continue;
+
+ AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+ // calculate ellipse parameters
+ GeomPnt2dPtr aPassedPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointAttr)->pnt();
+ GeomShapePtr aTangentCurve;
+ SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+ aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+
+ anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ }
+
+ if (aNbInitialized <= 1)
+ return; // too few points for the ellipse
+
+ myCenter = anEllipsePoints[0];
+ myMajorAxis = anEllipsePoints[1];
+ myStartPnt = anEllipsePoints[2];
+ myEndPnt = anEllipsePoints[3];
+
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+ if (aNbInitialized == 2) {
+ GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+ anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+ double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+ }
+ else if (aNbInitialized >= 3) {
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
+ }
+
+ if (!anEllipse || anEllipse->implPtr<void>() == 0)
+ return;
+
+ myMajorRadius = anEllipse->majorRadius();
+ myMinorRadius = anEllipse->minorRadius();
+
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ real(MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+ real(MINOR_RADIUS_ID())->setValue(myMinorRadius);
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+
+ // update the REVERSED flag
+ if (myEndPnt) {
+ double aParameterEnd = 0.0;
+ GeomPnt2dPtr aEnd = anEllipse->project(myEndPnt);
+ if (anEllipse->parameter(aEnd, paramTolerance, aParameterEnd)) {
+ double aParamStart = 0.0;
+ anEllipse->parameter(myStartPnt, paramTolerance, aParamStart);
+ aParameterEnd -= aParamStart;
+
+ if (myParamDelta > 0.0 && myParamDelta <= PI * 0.5 &&
+ aParameterEnd < 0 && aParameterEnd >= -PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(true);
+ }
+ else if (myParamDelta < 0.0 && myParamDelta >= -PI * 0.5 &&
+ aParameterEnd > 0.0 && aParameterEnd <= PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(false);
+ }
+ }
+ myParamDelta = aParameterEnd;
+ }
+}
+
+// LCOV_EXCL_START
+std::string SketchPlugin_MacroEllipticArc::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ std::string aFilledAttributeName;
+
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+ std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
+ if (aReentrantMessage) {
+ FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+
+ ObjectPtr anObject = aReentrantMessage->selectedObject();
+ AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+ std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+
+ if (aClickedPoint && (anObject || anAttribute)) {
+ aFilledAttributeName = CENTER_ID();
+ std::string aReferenceAttributeName = CENTER_REF_ID();
+
+ // fill 2d point attribute
+ AttributePoint2DPtr aPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(aFilledAttributeName));
+ aPointAttr->setValue(aClickedPoint);
+
+ // fill reference attribute
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
+ if (anAttribute) {
+ if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
+ if (aCreatedFeature && anAttribute->id() == CENTER_ID())
+ anAttribute = aCreatedFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID());
+ }
+ aRefAttr->setAttr(anAttribute);
+ }
+ else if (anObject.get()) {
+ // if attribute is NULL, only object is defined, it should be processed outside
+ // the feature because it might be an external feature, that will be
+ // removed/created again after restart operation
+ // #2468 - Crash when sketching circles successively on a repetition
+ aFilledAttributeName = "";
+ }
+ }
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ }
+ return aFilledAttributeName;
+}
+// LCOV_EXCL_STOP
+
+////void SketchPlugin_MacroEllipticArc::constraintsForEllipseByCenterAxisAndPassed(
+//// FeaturePtr theEllipseFeature)
+////{
+//// // tangency on-the-fly is not applicable for ellipses
+//// static const bool isTangencyApplicable = false;
+//// // Create constraints.
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, FIRST_POINT_REF_ID(),
+//// theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+//// ObjectPtr(), isTangencyApplicable);
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, SECOND_POINT_REF_ID(),
+//// theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+//// ObjectPtr(), isTangencyApplicable);
+//// // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+//// if (!refattr(PASSED_POINT_REF_ID())->isObject()) {
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, PASSED_POINT_REF_ID(), AttributePtr(),
+//// theEllipseFeature->lastResult(), isTangencyApplicable);
+//// }
+////}
+////
+////void SketchPlugin_MacroEllipticArc::constraintsForEllipseByMajoxAxisAndPassed(
+//// FeaturePtr theEllipseFeature)
+////{
+//// // tangency on-the-fly is not applicable for ellipses
+//// static const bool isTangencyApplicable = false;
+//// // Create constraints.
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, FIRST_POINT_REF_ID(),
+//// theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+//// ObjectPtr(), isTangencyApplicable);
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, SECOND_POINT_REF_ID(),
+//// theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+//// ObjectPtr(), isTangencyApplicable);
+//// // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+//// if (!refattr(PASSED_POINT_REF_ID())->isObject()) {
+//// SketchPlugin_Tools::createCoincidenceOrTangency(
+//// this, PASSED_POINT_REF_ID(), AttributePtr(),
+//// theEllipseFeature->lastResult(), isTangencyApplicable);
+//// }
+////}
+
+FeaturePtr SketchPlugin_MacroEllipticArc::createEllipticArcFeature()
+{
+ GeomShapePtr anArc = getArcShape();
+ GeomEllipsePtr anEllipse;
+ GeomPointPtr aStartPoint, aEndPoint;
+ if (anArc->isEdge()) {
+ GeomEdgePtr anArcEdge = anArc->edge();
+ aStartPoint = anArcEdge->firstPoint();
+ aEndPoint = anArcEdge->lastPoint();
+
+ if (anArcEdge->isEllipse())
+ anEllipse = anArcEdge->ellipse();
+ }
+
+ if (!anEllipse)
+ return FeaturePtr();
+
+ // Create and fill new EllipticArc feature
+ SketchPlugin_Sketch* aSketch = sketch();
+ FeaturePtr aEllipseFeature = aSketch->addFeature(SketchPlugin_EllipticArc::ID());
+
+ AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+ aCenterAttr->setValue(aSketch->to2D(anEllipse->center()));
+
+ AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()));
+ aFocusAttr->setValue(aSketch->to2D(anEllipse->firstFocus()));
+
+ AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ aStartAttr->setValue(aSketch->to2D(aStartPoint));
+
+ AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ aEndAttr->setValue(aSketch->to2D(aEndPoint));
+
+ aEllipseFeature->real(SketchPlugin_EllipticArc::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+ aEllipseFeature->real(SketchPlugin_EllipticArc::MINOR_RADIUS_ID())->setValue(myMinorRadius);
+
+ aEllipseFeature->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(
+ boolean(REVERSED_ID())->value());
+
+ aEllipseFeature->boolean(SketchPlugin_EllipticArc::AUXILIARY_ID())->setValue(
+ boolean(AUXILIARY_ID())->value());
+
+ aEllipseFeature->execute();
+
+ // create auxiliary points
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::CENTER_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::FIRST_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::SECOND_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MINOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MINOR_AXIS_END_ID());
+ // create auxiliary axes
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MINOR_AXIS_END_ID());
+
+ return aEllipseFeature;
+}
+
+AISObjectPtr SketchPlugin_MacroEllipticArc::getAISObject(AISObjectPtr thePrevious)
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch || !myCenter || !myMajorAxis)
+ return AISObjectPtr();
+
+ // Compute a elliptic arc in 3D view.
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
+ GeomShapePtr anArcShape = getArcShape();
+ if (!anArcShape.get() || !aCenterPointShape.get())
+ return AISObjectPtr();
+
+ std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+ aShapes.push_back(anArcShape);
+ aShapes.push_back(aCenterPointShape);
+
+ std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+ AISObjectPtr anAIS = thePrevious;
+ if (!anAIS)
+ anAIS.reset(new GeomAPI_AISObject());
+ anAIS->createShape(aCompound);
+ return anAIS;
+}
+
+GeomShapePtr SketchPlugin_MacroEllipticArc::getArcShape()
+{
+ if (!myCenter.get() || !myMajorAxis.get())
+ return GeomShapePtr();
+
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch)
+ return GeomShapePtr();
+
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomPointPtr aMajorAxisPnt(aSketch->to3D(myMajorAxis->x(), myMajorAxis->y()));
+ GeomDirPtr aMajorAxisDir(new GeomAPI_Dir(aMajorAxisPnt->x() - aCenter->x(),
+ aMajorAxisPnt->y() - aCenter->y(),
+ aMajorAxisPnt->z() - aCenter->z()));
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+ GeomDirPtr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
+
+ GeomPointPtr aStart, anEnd;
+ if (myStartPnt)
+ aStart = aSketch->to3D(myStartPnt->x(), myStartPnt->y());
+ if (myEndPnt)
+ anEnd = aSketch->to3D(myEndPnt->x(), myEndPnt->y());
+
+ GeomShapePtr anArcShape;
+ if (anEnd) {
+ if (boolean(REVERSED_ID())->value())
+ std::swap(aStart, anEnd);
+
+ anArcShape = GeomAlgoAPI_EdgeBuilder::ellipticArc(aCenter, aNormal, aMajorAxisDir,
+ myMajorRadius, myMinorRadius, aStart, anEnd);
+ }
+ else {
+ anArcShape = GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxisDir,
+ myMajorRadius, myMinorRadius);
+ }
+
+ return anArcShape;
+}
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SketchPlugin_MacroEllipticArc_H_
+#define SketchPlugin_MacroEllipticArc_H_
+
+#include <ModelAPI_IReentrant.h>
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+#include <GeomAPI_IPresentable.h>
+
+class GeomAPI_Pnt2d;
+class GeomAPI_Shape;
+
+/**\class SketchPlugin_MacroEllipticArc
+ * \ingroup Plugins
+ * \brief Feature for creation of the new elliptical arc in Sketch.
+ */
+class SketchPlugin_MacroEllipticArc: public SketchPlugin_SketchEntity,
+ public GeomAPI_IPresentable,
+ public ModelAPI_IReentrant
+{
+ public:
+ /// Elliptical arc feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchMacroEllipticArc");
+ return ID;
+ }
+
+ /// Attribute for the central point selected during elliptic arc creation.
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string ID("center");
+ return ID;
+ }
+
+ /// Reference to the first selected point (center of ellipse).
+ inline static const std::string& CENTER_REF_ID()
+ {
+ static const std::string ID("center_ref");
+ return ID;
+ }
+
+ /// Attribute for the point on major semi-axis selected during elliptic arc creation.
+ inline static const std::string& MAJOR_AXIS_POINT_ID()
+ {
+ static const std::string ID("major_axis_point");
+ return ID;
+ }
+
+ /// Reference to the second selected point (major semi-axis of the ellipse).
+ inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+ {
+ static const std::string ID("major_axis_point_ref");
+ return ID;
+ }
+
+ /// Attribute for the start point of the elliptic arc selected during creation.
+ inline static const std::string& START_POINT_ID()
+ {
+ static const std::string ID("start_point");
+ return ID;
+ }
+
+ /// Reference for the start point selection.
+ inline static const std::string& START_POINT_REF_ID()
+ {
+ static const std::string ID("start_point_ref");
+ return ID;
+ }
+
+ /// Attribute for the end point of the elliptic arc selected during creation.
+ inline static const std::string& END_POINT_ID()
+ {
+ static const std::string ID("end_point");
+ return ID;
+ }
+
+ /// Reference for the end point selection.
+ inline static const std::string& END_POINT_REF_ID()
+ {
+ static const std::string ID("end_point_ref");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("minor_radius");
+ return ID;
+ }
+
+ /// Flag the arc is reversed
+ inline static const std::string& REVERSED_ID()
+ {
+ static const std::string ID("reversed");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_MacroEllipticArc::ID();
+ return MY_KIND;
+ }
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes.
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Returns the AIS preview
+ virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Reimplemented from ModelAPI_Feature::isMacro().
+ /// \returns true
+ SKETCHPLUGIN_EXPORT virtual bool isMacro() const
+ {return true;}
+
+ SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const
+ {return false;}
+
+ /// Apply information of the message to current object. It fills reference object,
+ /// tangent type and tangent point refence in case of tangent arc
+ virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ /// Use plugin manager for features creation
+ SketchPlugin_MacroEllipticArc();
+
+private:
+ std::shared_ptr<GeomAPI_Shape> getArcShape();
+
+//// void constraintsForEllipseByCenterAxisAndPassed(FeaturePtr theEllipseFeature);
+//// void constraintsForEllipseByMajoxAxisAndPassed(FeaturePtr theEllipseFeature);
+
+ FeaturePtr createEllipticArcFeature();
+
+private:
+ std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+ std::shared_ptr<GeomAPI_Pnt2d> myMajorAxis;
+ std::shared_ptr<GeomAPI_Pnt2d> myStartPnt;
+ std::shared_ptr<GeomAPI_Pnt2d> myEndPnt;
+ double myMajorRadius;
+ double myMinorRadius;
+ double myParamDelta;
+};
+
+#endif
#include <SketchPlugin_ExternalValidator.h>
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_MacroEllipse.h>
+#include <SketchPlugin_EllipticArc.h>
+#include <SketchPlugin_MacroEllipticArc.h>
#include <SketchPlugin_SketchDrawer.h>
#include <SketcherPrs_Tools.h>
return FeaturePtr(new SketchPlugin_Ellipse);
} else if (theFeatureID == SketchPlugin_MacroEllipse::ID()) {
return FeaturePtr(new SketchPlugin_MacroEllipse);
+ } else if (theFeatureID == SketchPlugin_EllipticArc::ID()) {
+ return FeaturePtr(new SketchPlugin_EllipticArc);
+ } else if (theFeatureID == SketchPlugin_MacroEllipticArc::ID()) {
+ return FeaturePtr(new SketchPlugin_MacroEllipticArc);
} else if (theFeatureID == SketchPlugin_SketchDrawer::ID()) {
return FeaturePtr(new SketchPlugin_SketchDrawer);
}
aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Ellipse::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_EllipticArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Projection::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCoincidence::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCoincidenceInternal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_MacroEllipticArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane);
// SketchRectangle is a python feature, so its ID is passed just as a string
#include "SketchPlugin_Tools.h"
#include "SketchPlugin_ConstraintCoincidence.h"
+#include "SketchPlugin_ConstraintCoincidenceInternal.h"
#include "SketchPlugin_ConstraintLength.h"
#include "SketchPlugin_ConstraintTangent.h"
+#include "SketchPlugin_Ellipse.h"
#include "SketchPlugin_Line.h"
#include "SketchPlugin_Point.h"
#include "SketchPlugin_SketchEntity.h"
return aConstraint;
}
+void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theEllipsePoint)
+{
+ SketchPlugin_Sketch* aSketch =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
+
+ FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
+ aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+ aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
+
+ AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theEllipsePoint));
+
+ AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
+ aCoord->setValue(anElPoint->x(), anElPoint->y());
+
+ aPointFeature->execute();
+ std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
+ aPointFeature->data()->setName(aName);
+ aPointFeature->lastResult()->data()->setName(aName);
+
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
+}
+
+void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theStartPoint,
+ const std::string& theEndPoint)
+{
+ SketchPlugin_Sketch* aSketch =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
+
+ FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
+ aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+ aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
+
+ AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theStartPoint));
+ AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theEndPoint));
+
+ AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::START_ID()));
+ aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
+
+ AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::END_ID()));
+ aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
+
+ aLineFeature->execute();
+ std::string aName = theEllipseFeature->name() + "_" +
+ (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
+ aLineFeature->data()->setName(aName);
+ aLineFeature->lastResult()->data()->setName(aName);
+
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
+}
+
GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
{
// currently process Length constraints only
const ObjectPtr theObject,
const bool theIsCanBeTangent);
+/// Creates auxiliary point for ellipse and corresponding internal constraint.
+/// \param[in] theEllipse base ellipse feature
+/// \param[in] theAttrName name of the attribute of the ellipse,
+/// the new point should be constrained
+void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theAttrName);
+
+/// Creates auxiliary axis for ellipse and corresponding internal constraints.
+/// \param[in] theEllipse base ellipse feature
+/// \param[in] theStartAttr name of the attribute of the ellipse, the line is started
+/// \param[in] theEndAttr name of the attribute of the ellipse, the line is ended
+void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theStartAttr,
+ const std::string& theEndAttr);
+
/// Creates passing point or tangent curve basing on the given attributes are initialized.
/// \param[in] theRefAttr prefered attribute to be converted
/// \param[in] theDefaultAttr default attribute if theRefAttr is not initialized
return aValid;
}
- theError = "Error: Selected object is not line, circle or arc.";
+ theError = "Error: Selected object is not supported for projection.";
return false;
}
id="Sketch"
nested="SketchPoint SketchIntersectionPoint SketchLine
SketchCircle SketchMacroCircle SketchArc SketchMacroArc
- SketchEllipse SketchMacroEllipse
+ SketchEllipse SketchMacroEllipse SketchEllipticArc SketchMacroEllipticArc
SketchRectangle
SketchProjection
SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
<validator id="GeomValidators_Different" parameters="StartPoint,EndPoint"/>
</feature>
</group>
- <group id="Circular geometry">
+ <group id="Conical geometry">
<!-- SketchCircle is a hidden feature. It is created inside SketchMacroCircle. -->
<feature id="SketchCircle"
title="Circle"
</sketch_shape_selector>
<!--<validator id="PartSet_FilletSelection"/>-->
</feature>
- <!-- SketchSplit -->
- <feature id="SketchSplit" title="Split"
- tooltip="Cut selected segment arc or circle on existing coincident points"
- icon="icons/Sketch/split.png"
- helpfile="splitFeature.html">
- <sketch_feature_point_selector
- id="SelectedObject"
- selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
- label="Segment"
- tooltip="Select segment for split"
- shape_types="edge"
- use_external="false">
- <validator id="SketchPlugin_SplitValidator"/>
- </sketch_feature_point_selector>
- <validator id="PartSet_SplitSelection"/>
- </feature>
- <!-- SketchTrim -->
- <feature id="SketchTrim" title="Trim"
- tooltip="Trim selected segment arc or circle on intersection points nearest to the graphic selection"
- icon="icons/Sketch/trim.png"
- helpfile="trimFeature.html">
- <sketch_feature_point_selector
- id="SelectedObject"
- selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
- label="Segment"
- tooltip="Select segment for trim"
- shape_types="edge"
- use_external="false">
- <validator id="SketchPlugin_TrimValidator"/>
- </sketch_feature_point_selector>
- <validator id="PartSet_SplitSelection"/>
- </feature>
- </group>
- <group id="Elliptic geometry">
<!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
<feature id="SketchEllipse"
title="Ellipse"
title="Passed point"
tooltip="Passed point coordinates"
accept_expressions="0"
- enable_value="enable_by_preferences">
- <!-- <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
- </sketch-2dpoint_selector>
+ enable_value="enable_by_preferences"/>
</box>
<box id="by_major_axis_and_point"
icon="icons/Sketch/ellipse_axes_32x32.png"
enable_value="enable_by_preferences"/>
</box>
</toolbox>
-<!-- <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
<labelvalue id="major_radius"
icon="icons/Sketch/radius_major.png"
label="Major radius"
default="false"
obligatory="0"/>
</feature>
+
+ <!-- SketchEllipticArc is a hidden feature. It is created inside SketchMacroEllipse. -->
+ <feature id="SketchEllipticArc"
+ title="Elliptic Arc"
+ tooltip="Create elliptic arc"
+ icon="icons/Sketch/elliptic_arc.png"
+ internal="1">
+ <sketch-2dpoint_selector id="ellipse_center"
+ title="Center"
+ tooltip="Center coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_first_focus"
+ title="First focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_second_focus"
+ title="Second focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_start_point"
+ title="Major axis start"
+ tooltip="Coordinates of point on negative direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_end_point"
+ title="Major axis end"
+ tooltip="Coordinates of point on positive direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_start_point"
+ title="Minor axis start"
+ tooltip="Coordinates of point on negative direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_end_point"
+ title="Minor axis end"
+ tooltip="Coordinates of point on positive direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="start_point"
+ title="Start point"
+ tooltip="Arc start point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="end_point"
+ title="End point"
+ tooltip="Arc end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <labelvalue id="ellipse_major_radius"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <labelvalue id="ellipse_minor_radius"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ </feature>
+ <!-- SketchMacroEllipticArc -->
+ <feature id="SketchMacroEllipticArc"
+ icon="icons/Sketch/elliptic_arc.png"
+ title="Elliptical arc"
+ tooltip="Create elliptical arc"
+ helpfile="ellipseFeature.html">
+ <sketch-2dpoint_selector id="center"
+ reference_attribute="center_ref"
+ title="Center point"
+ tooltip="Center point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="major_axis_point"
+ reference_attribute="major_axis_point_ref"
+ title="Major axis point"
+ tooltip="Major axis point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="start_point"
+ reference_attribute="start_point_ref"
+ title="Start point"
+ tooltip="Arc start point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="end_point"
+ reference_attribute="end_point_ref"
+ title="End point"
+ tooltip="Arc end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <labelvalue id="major_radius"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ <validator id="GeomValidators_Positive"/>
+ </labelvalue>
+ <labelvalue id="minor_radius"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ <validator id="GeomValidators_Positive"/>
+ </labelvalue>
+ <boolvalue id="Auxiliary"
+ tooltip="Construction element"
+ label="Auxiliary"
+ default="false"
+ obligatory="0"/>
+ </feature>
+ </group>
+
+ <group id="Segmentation">
+ <!-- SketchSplit -->
+ <feature id="SketchSplit" title="Split"
+ tooltip="Cut selected segment arc or circle on existing coincident points"
+ icon="icons/Sketch/split.png"
+ helpfile="splitFeature.html">
+ <sketch_feature_point_selector
+ id="SelectedObject"
+ selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
+ label="Segment"
+ tooltip="Select segment for split"
+ shape_types="edge"
+ use_external="false">
+ <validator id="SketchPlugin_SplitValidator"/>
+ </sketch_feature_point_selector>
+ <validator id="PartSet_SplitSelection"/>
+ </feature>
+ <!-- SketchTrim -->
+ <feature id="SketchTrim" title="Trim"
+ tooltip="Trim selected segment arc or circle on intersection points nearest to the graphic selection"
+ icon="icons/Sketch/trim.png"
+ helpfile="trimFeature.html">
+ <sketch_feature_point_selector
+ id="SelectedObject"
+ selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
+ label="Segment"
+ tooltip="Select segment for trim"
+ shape_types="edge"
+ use_external="false">
+ <validator id="SketchPlugin_TrimValidator"/>
+ </sketch_feature_point_selector>
+ <validator id="PartSet_SplitSelection"/>
+ </feature>
</group>
<group id="Projection">
#include <PlaneGCSSolver_EdgeWrapper.h>
#include <cmath>
+static bool isLine(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Line>(theEntity).get();
+}
+
+static bool isCircle(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Circle>(theEntity).get();
+}
+
+static bool isArc(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Arc>(theEntity).get();
+}
+
+static bool isEllipse(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Ellipse>(theEntity).get();
+}
+
+static bool isEllipticArc(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEntity).get();
+}
+
+
PlaneGCSSolver_EdgeWrapper::PlaneGCSSolver_EdgeWrapper(const GCSCurvePtr theEntity)
: myEntity(theEntity)
{
- 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;
- else {
- std::shared_ptr<GCS::Ellipse> anEllipse =
- std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
- if (anEllipse) myType = ENTITY_ELLIPSE;
- }
- }
- }
+ if (isLine(myEntity))
+ myType = ENTITY_LINE;
+ else if (isArc(myEntity))
+ myType = ENTITY_ARC;
+ else if (isCircle(myEntity))
+ myType = ENTITY_CIRCLE;
+ else if (isEllipticArc(myEntity))
+ myType = ENTITY_ELLIPTICAL_ARC;
+ else if (isEllipse(myEntity))
+ myType = ENTITY_ELLIPSE;
}
static double squareDistance(const GCS::Point& theP1, const GCS::Point& theP2)
bool PlaneGCSSolver_EdgeWrapper::isDegenerated() const
{
- static const double aSqTol = tolerance * 1e-2;
- static const double aMaxRadius = 1e8;
+ static const double THE_SQ_TOL = tolerance * 1e-2;
+ static const double THE_ANGLE_TOL = 1.e-5;
+ static const double THE_MAX_RADIUS = 1e8;
+ static const double THE_SQ_MAX_RADIUS = THE_MAX_RADIUS * THE_MAX_RADIUS;
+
if (myType == ENTITY_LINE) {
std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
- return squareDistance(aLine->p1, aLine->p2) < aSqTol;
+ return squareDistance(aLine->p1, aLine->p2) < THE_SQ_TOL;
}
else if (myType == ENTITY_CIRCLE) {
std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
- return *aCircle->rad < tolerance || *aCircle->rad > aMaxRadius;
+ return *aCircle->rad < tolerance || *aCircle->rad > THE_MAX_RADIUS;
}
else if (myType == ENTITY_ARC) {
- static const double anAngleTol = 1.e-5;
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(myEntity);
double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
double aSqRadius = squareDistance(anArc->center, anArc->start);
- return aSqRadius < aSqTol || aSqRadius > aMaxRadius * aMaxRadius || // <- arc radius
- anAngleDiff < anAngleTol || fabs(anAngleDiff - 2*PI) < anAngleTol; // <- arc angle
+ return aSqRadius < THE_SQ_TOL || aSqRadius > THE_SQ_MAX_RADIUS || // <- arc radius
+ anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
}
else if (myType == ENTITY_ELLIPSE) {
std::shared_ptr<GCS::Ellipse> anEllipse = std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
- return *anEllipse->radmin < tolerance;
+ return *anEllipse->radmin < tolerance || anEllipse->getRadMaj() > THE_MAX_RADIUS;
+ }
+ else if (myType == ENTITY_ELLIPTICAL_ARC) {
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(myEntity);
+ double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
+ return *anArc->radmin < THE_SQ_TOL || anArc->getRadMaj() > THE_SQ_MAX_RADIUS || // <- arc radius
+ anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
}
return false;
}
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
#include <PlaneGCSSolver_BooleanWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
PlaneGCSSolver_Storage* theStorage);
static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage);
PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
// Ellipse
else if (aFeatureKind == SketchPlugin_Ellipse::ID())
aResult = createEllipse(myAttributes);
+ // Arc of ellipse
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+ aResult = createEllipticArc(myAttributes, myStorage);
// Point (it has low probability to be an attribute of constraint, so it is checked at the end)
else if (aFeatureKind == SketchPlugin_Point::ID() ||
aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
}
}
- // Additional atrtributes of arc necessary for PlaneGCS solver
+ // Additional attributes of arc necessary for PlaneGCS solver
// (start and end angles, radius)
aNewArc->startAngle = createParameter(theStorage);
aNewArc->endAngle = createParameter(theStorage);
aNewArc->rad = createParameter(theStorage);
- static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Pnt2d> aCenter(
- new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
- std::shared_ptr<GeomAPI_Pnt2d> aStart(
- new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
-
- *aNewArc->rad = aStart->distance(aCenter);
-
- std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
- *aNewArc->startAngle = OX->angle(aDir);
-
- aDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
- *aNewArc->endAngle = OX->angle(aDir);
-
EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
anArcWrapper->setReversed(isReversed);
+ PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
+
return anArcWrapper;
}
return anEllipseWrapper;
}
+EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage)
+{
+ std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
+
+ BooleanWrapperPtr isReversed;
+ std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
+
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (aPoint) {
+ if (anIt->first->id() == SketchPlugin_EllipticArc::CENTER_ID())
+ aNewArc->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::FIRST_FOCUS_ID())
+ aNewArc->focus1 = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::START_POINT_ID())
+ aNewArc->start = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::END_POINT_ID())
+ aNewArc->end = *(aPoint->point());
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::MINOR_RADIUS_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewArc->radmin = aScalar->scalar();
+ }
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
+ isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+
+ // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
+ aNewArc->startAngle = createParameter(theStorage);
+ aNewArc->endAngle = createParameter(theStorage);
+
+ EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+ anEllipseWrapper->setReversed(isReversed);
+ anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+ PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
+
+ return anEllipseWrapper;
+}
+
bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
{
if (theOwnerName == SketchPlugin_Arc::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();
+ }
// suppose that all remaining features are points
return theAttrName == SketchPlugin_Point::COORD_ID();
notify(theFeature);
// update arc
- if (aRelated && aRelated->type() == ENTITY_ARC) {
- /// TODO: this code should be shared with FeatureBuilder somehow
-
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
- std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aRelated);
- std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
-
- static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Pnt2d> aCenter(
- new GeomAPI_Pnt2d(*anArc->center.x, *anArc->center.y));
- std::shared_ptr<GeomAPI_Pnt2d> aStart(
- new GeomAPI_Pnt2d(*anArc->start.x, *anArc->start.y));
-
- *anArc->rad = aStart->distance(aCenter);
-
- std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
- *anArc->startAngle = OX->angle(aDir);
-
- aDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*anArc->end.x) - aCenter->x(), (*anArc->end.y) - aCenter->y()));
- *anArc->endAngle = OX->angle(aDir);
- }
+ if (aRelated)
+ PlaneGCSSolver_Tools::recalculateArcParameters(aRelated);
return isUpdated;
}
ConstraintWrapperPtr aWrapper(
new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
aWrapper->setId(theConstraintID);
- constraintsToSolver(aWrapper, theSolver);
+ if (theSolver)
+ constraintsToSolver(aWrapper, theSolver);
theConstraints[theEllipse] = aWrapper;
}
+static void createEllipticArcConstraints(
+ const EntityWrapperPtr& theEllipticArc,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
+{
+ // create base constraints for the ellipse without adding them to solver
+ createEllipseConstraints(theEllipticArc, SolverPtr(), theConstraintID, theConstraints);
+
+ ConstraintWrapperPtr& aConstraint = theConstraints[theEllipticArc];
+ std::list<GCSConstraintPtr> anEllArcConstraints = aConstraint->constraints();
+
+ // constrain extremities of the elliptic arc
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipticArc);
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+
+ aConstraint->setConstraints(anEllArcConstraints);
+ constraintsToSolver(aConstraint, theSolver);
+}
+
void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
{
if (!theEntity || theEntity->isExternal())
createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
else if (theEntity->type() == ENTITY_ELLIPSE)
createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+ else if (theEntity->type() == ENTITY_ELLIPTICAL_ARC) {
+ createEllipticArcConstraints(theEntity, mySketchSolver,
+ ++myConstraintLastID, myAuxConstraintMap);
+ }
}
void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
}
}
+template <typename ARCTYPE>
+void adjustArcParametrization(ARCTYPE& theArc, bool theReversed)
+{
+ // tune start angle of the arc to be in [0, 2PI]
+ while (*theArc.startAngle < -PI)
+ *theArc.startAngle += 2.0 * PI;
+ while (*theArc.startAngle >= PI)
+ *theArc.startAngle -= 2.0 * PI;
+ // adjust end angle of the arc
+ if (theReversed) {
+ while (*theArc.endAngle > *theArc.startAngle)
+ *theArc.endAngle -= 2.0 * PI;
+ while (*theArc.endAngle + 2 * PI < *theArc.startAngle)
+ *theArc.endAngle += 2.0 * PI;
+ }
+ else {
+ while (*theArc.endAngle < *theArc.startAngle)
+ *theArc.endAngle += 2.0 * PI;
+ while (*theArc.endAngle > *theArc.startAngle + 2 * PI)
+ *theArc.endAngle -= 2.0 * PI;
+ }
+}
+
void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
{
std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
for (; anIt != myAuxConstraintMap.end(); ++anIt) {
EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
- if (!anArc)
- continue;
- // tune start angle of the arc to be in [0, 2PI]
- while (*anArc->startAngle < -PI)
- *anArc->startAngle += 2.0 * PI;
- while (*anArc->startAngle >= PI)
- *anArc->startAngle -= 2.0 * PI;
- // adjust end angle of the arc
- if (anEdge->isReversed()) {
- while (*anArc->endAngle > *anArc->startAngle)
- *anArc->endAngle -= 2.0 * PI;
- while (*anArc->endAngle + 2 * PI < *anArc->startAngle)
- *anArc->endAngle += 2.0 * PI;
- } else {
- while (*anArc->endAngle < *anArc->startAngle)
- *anArc->endAngle += 2.0 * PI;
- while (*anArc->endAngle > *anArc->startAngle + 2 * PI)
- *anArc->endAngle -= 2.0 * PI;
+ if (anArc)
+ adjustArcParametrization(*anArc, anEdge->isReversed());
+ else {
+//// std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+//// std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+//// if (aEllArc)
+//// adjustArcParametrization(*aEllArc, anEdge->isReversed());
}
}
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);
new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
}
+void PlaneGCSSolver_Tools::recalculateArcParameters(EntityWrapperPtr theArc)
+{
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEdge =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
+ if (!anEdge)
+ return;
+
+ GCS::Point aCenter, aStartPnt, aEndPnt;
+ double *aStartAngle, *aEndAngle;
+ GeomDir2dPtr OX;
+
+ if (anEdge->type() == ENTITY_ARC) {
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
+
+ aCenter = anArc->center;
+ aStartPnt = anArc->start;
+ aEndPnt = anArc->end;
+
+ *anArc->rad = distance(aCenter, aStartPnt);
+
+ aStartAngle = anArc->startAngle;
+ aEndAngle = anArc->endAngle;
+
+ OX.reset(new GeomAPI_Dir2d(1.0, 0.0));
+ }
+ else if (anEdge->type() == ENTITY_ELLIPTICAL_ARC) {
+ std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+
+ aCenter = aEllArc->center;
+ aStartPnt = aEllArc->start;
+ aEndPnt = aEllArc->end;
+
+ aStartAngle = aEllArc->startAngle;
+ aEndAngle = aEllArc->endAngle;
+
+ OX.reset(new GeomAPI_Dir2d(*aEllArc->focus1.x - *aCenter.x, *aEllArc->focus1.y - *aCenter.y));
+ }
+ else // skip other type of entities
+ return;
+
+ GeomDir2dPtr aDir(new GeomAPI_Dir2d(*aStartPnt.x - *aCenter.x, *aStartPnt.y - *aCenter.y));
+ *aStartAngle = OX->angle(aDir);
+
+ aDir.reset(new GeomAPI_Dir2d(*aEndPnt.x - *aCenter.x, *aEndPnt.y - *aCenter.y));
+ *aEndAngle = OX->angle(aDir);
+}
+
GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
return arcParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_ELLIPSE:
return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_ELLIPTICAL_ARC:
+ return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
default: break;
}
return GCS::SET_pD();
aConstrList.push_back(GCSConstraintPtr(
new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
// update value of intermediate parameter
- double x = *aLine1->p1.x - *aLine1->p2.x;
- double y = *aLine1->p1.y - *aLine1->p2.y;
- double aLen = sqrt(x*x + y*y);
- theIntermed->setValue(aLen);
+ theIntermed->setValue(distance(aLine1->p1, aLine1->p2));
} else {
std::shared_ptr<GCS::Circle> aCirc1 =
std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
{
- GCS::SET_pD aParams;
+ GCS::SET_pD aParams = circleParameters(theArc);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theArc->entity());
- aParams.insert(anArc->center.x);
- aParams.insert(anArc->center.y);
aParams.insert(anArc->start.x);
aParams.insert(anArc->start.y);
aParams.insert(anArc->end.x);
aParams.insert(anArc->end.y);
aParams.insert(anArc->startAngle);
aParams.insert(anArc->endAngle);
- aParams.insert(anArc->rad);
return aParams;
}
aParams.insert(anEllipse->radmin);
return aParams;
}
+
+GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc)
+{
+ GCS::SET_pD aParams = ellipseParameters(theEllipticArc);
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEllipticArc->entity());
+ aParams.insert(anArc->start.x);
+ aParams.insert(anArc->start.y);
+ aParams.insert(anArc->end.x);
+ aParams.insert(anArc->end.y);
+ aParams.insert(anArc->startAngle);
+ aParams.insert(anArc->endAngle);
+ return aParams;
+}
+
+double 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);
+}
/// \return empty pointer if the entity is not a line
std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature);
+ /// \brief Update start and end parameters of circular and elliptic arcs
+ /// respectively to start and end points on the arc.
+ /// For the circular arc, the radius is calculated too.
+ void recalculateArcParameters(EntityWrapperPtr theArc);
+
/// brief Return list of parameters for the given entity
GCS::SET_pD parameters(const EntityWrapperPtr& theEntity);
};
aParameters.push_back(anEllipse->radmin);
break;
}
+ case ENTITY_ELLIPTICAL_ARC: {
+ std::shared_ptr<GCS::ArcOfEllipse> anEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEntity->entity());
+ aParameters.push_back(anEllArc->center.x);
+ aParameters.push_back(anEllArc->center.y);
+ aParameters.push_back(anEllArc->focus1.x);
+ aParameters.push_back(anEllArc->focus1.y);
+ aParameters.push_back(anEllArc->radmin);
+ aParameters.push_back(anEllArc->startAngle);
+ aParameters.push_back(anEllArc->endAngle);
+ break;
+ }
default:
break;
}
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
if (theMovedFeature->getKind() == SketchPlugin_Circle::ID() ||
theMovedFeature->getKind() == SketchPlugin_Ellipse::ID())
isSimple = (theDraggedPoint.get() != 0);
- else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
+ else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID() ||
+ theMovedFeature->getKind() == SketchPlugin_EllipticArc::ID()) {
isSimple = (theDraggedPoint.get() != 0 &&
- theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID());
+ (theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID() ||
+ theDraggedPoint->id() == SketchPlugin_EllipticArc::CENTER_ID()));
}
#endif
return isSimple;
myStorage->entity(myMovedFeature));
std::shared_ptr<GCS::Arc> anArc =
std::dynamic_pointer_cast<GCS::Arc>(aCircularEntity->entity());
+ std::shared_ptr<GCS::ArcOfEllipse> anEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(aCircularEntity->entity());
PointWrapperPtr aPoint =
std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theArcExtremity);
- double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y,
- anArc->center.x, anArc->center.y };
+ double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y, 0, 0 };
+ if (anArc) {
+ aParams[2] = anArc->center.x;
+ aParams[3] = anArc->center.y;
+ }
+ else if (anEllArc) {
+ aParams[2] = anEllArc->center.x;
+ aParams[3] = anEllArc->center.y;
+ }
std::list<GCSConstraintPtr> aConstraints;
for (int i = 0; i < nbParams; ++i) {