* Projection of ellipse.
* Update tests according to new behavior of projection (circle can be projected to ellipse now).
GeomAlgoAPI_Offset.h
GeomAlgoAPI_SolidClassifier.h
GeomAlgoAPI_MapShapesAndAncestors.h
+ GeomAlgoAPI_Projection.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_Offset.cpp
GeomAlgoAPI_SolidClassifier.cpp
GeomAlgoAPI_MapShapesAndAncestors.cpp
+ GeomAlgoAPI_Projection.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 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 <GeomAlgoAPI_Projection.h>
+
+#include <GeomAPI_Curve.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Pln.h>
+
+#include <Geom_Curve.hxx>
+#include <Geom_Plane.hxx>
+#include <GeomProjLib.hxx>
+
+GeomAlgoAPI_Projection::GeomAlgoAPI_Projection(const GeomPlanePtr& thePlane)
+ : myPlane(thePlane)
+{
+}
+
+GeomCurvePtr GeomAlgoAPI_Projection::project(const GeomCurvePtr& theCurve)
+{
+ Handle(Geom_Curve) aCurve = theCurve->impl<Handle_Geom_Curve>();
+ Handle(Geom_Plane) aPlane = new Geom_Plane(myPlane->impl<gp_Ax3>());
+
+ Handle(Geom_Curve) aProj = GeomProjLib::Project(aCurve, aPlane);
+
+ GeomCurvePtr aProjCurve(new GeomAPI_Curve);
+ aProjCurve->setImpl(new Handle_Geom_Curve(aProj));
+ return aProjCurve;
+}
+
+GeomCurvePtr GeomAlgoAPI_Projection::project(const GeomEdgePtr& theEdge)
+{
+ GeomCurvePtr aCurve(new GeomAPI_Curve(theEdge));
+ return project(aCurve);
+}
--- /dev/null
+// Copyright (C) 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 GeomAlgoAPI_Projection_H_
+#define GeomAlgoAPI_Projection_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <GeomAPI_Pln.h>
+
+#include <memory>
+
+class GeomAPI_Curve;
+class GeomAPI_Edge;
+
+/**\class GeomAlgoAPI_Projection
+ * \ingroup DataAlgo
+ * \brief Project curve onto a plane
+ */
+class GEOMALGOAPI_EXPORT GeomAlgoAPI_Projection
+{
+public:
+ GeomAlgoAPI_Projection(const std::shared_ptr<GeomAPI_Pln>& thePlane);
+
+ /// Project curve to the plane
+ std::shared_ptr<GeomAPI_Curve> project(const std::shared_ptr<GeomAPI_Curve>& theCurve);
+ /// Project edge to the plane
+ std::shared_ptr<GeomAPI_Curve> project(const std::shared_ptr<GeomAPI_Edge>& theEdge);
+
+private:
+ std::shared_ptr<GeomAPI_Pln> myPlane;
+};
+
+#endif
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Point.h>
-#include <SketchAPI_Line.h>
-#include <SketchAPI_Circle.h>
#include <SketchAPI_Arc.h>
+#include <SketchAPI_Circle.h>
+#include <SketchAPI_Ellipse.h>
+#include <SketchAPI_Line.h>
#include <SketchAPI_Point.h>
#include <ModelHighAPI_Dumper.h>
anEntity.reset(new SketchAPI_Circle(aProjectedFeature));
else if (aProjectedFeature->getKind() == SketchPlugin_Arc::ID())
anEntity.reset(new SketchAPI_Arc(aProjectedFeature));
+ else if (aProjectedFeature->getKind() == SketchPlugin_Ellipse::ID())
+ anEntity.reset(new SketchAPI_Ellipse(aProjectedFeature));
else if (aProjectedFeature->getKind() == SketchPlugin_Point::ID())
anEntity.reset(new SketchAPI_Point(aProjectedFeature));
TestMultiTranslation.py
TestPresentation.py
TestProjection.py
+ TestProjectionEllipse.py
TestProjectionIntoResult.py
TestProjectionUpdate.py
TestRectangle.py
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Sketch.h>
#include <GeomAPI_Circ.h>
#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_Vertex.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_Projection.h>
#include <GeomDataAPI_Point2D.h>
#include <cmath>
}
}
-static bool isValidProjectionType(FeaturePtr theProjection,
- GeomEdgePtr theEdge,
- GeomVertexPtr theVertex)
+static const std::string& projectionType(GeomEdgePtr theEdge,
+ GeomVertexPtr theVertex)
{
- if (theVertex && theProjection->getKind() == SketchPlugin_Point::ID())
- return true;
+ if (theVertex)
+ return SketchPlugin_Point::ID();
if (theEdge) {
- if (theEdge->isLine() && theProjection->getKind() == SketchPlugin_Line::ID())
- return true;
- else if (theEdge->isCircle() && theProjection->getKind() == SketchPlugin_Circle::ID())
- return true;
- else if (theEdge->isArc() && theProjection->getKind() == SketchPlugin_Arc::ID())
- return true;
+ if (theEdge->isLine())
+ return SketchPlugin_Line::ID();
+ else if (theEdge->isCircle())
+ return SketchPlugin_Circle::ID();
+ else if (theEdge->isArc())
+ return SketchPlugin_Arc::ID();
+ else if (theEdge->isEllipse())
+ return SketchPlugin_Ellipse::ID();
}
- return false;
+ static const std::string DUMMY;
+ return DUMMY;
}
void SketchPlugin_Projection::computeProjection(const std::string& theID)
if (!anEdge && !aVertex)
return;
+ const std::string& aProjType = projectionType(anEdge, aVertex);
+
AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
FeaturePtr aProjection;
if (aRefAttr && aRefAttr->isInitialized())
aProjection = ModelAPI_Feature::feature(aRefAttr->object());
// if the type of feature differs with already selected, remove it and create once again
- bool hasPrevProj = aProjection.get() != 0;
- if (hasPrevProj && !isValidProjectionType(aProjection, anEdge, aVertex)) {
- DocumentPtr aDoc = sketch()->document();
-
- aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection
- std::set<FeaturePtr> aFeaturesToBeRemoved;
- aFeaturesToBeRemoved.insert(aProjection);
- ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
- aProjection = FeaturePtr();
- aRefAttr->setObject(aProjection);
- hasPrevProj = false;
- }
+ bool isRebuild = rebuildProjectedFeature(aProjection, aProjType, true);
std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
ResultConstructionPtr aResult =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(lastResult());
- if (aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
+ if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
aResult->setShape(std::shared_ptr<GeomAPI_Edge>());
if (aProjection)
aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
std::shared_ptr<GeomAPI_Pnt> aPrjPnt = aSketchPlane->project(aVertex->point());
std::shared_ptr<GeomAPI_Pnt2d> aPntInSketch = sketch()->to2D(aPrjPnt);
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Point::ID());
+ rebuildProjectedFeature(aProjection, SketchPlugin_Point::ID());
// update coordinates of projection
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
if (aFirstInSketch->distance(aLastInSketch) < tolerance)
return; // line is semi-orthogonal to the sketch plane
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Line::ID());
+ rebuildProjectedFeature(aProjection, SketchPlugin_Line::ID());
// update attributes of projection
std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aStartPnt->setValue(aFirstInSketch);
aEndPnt->setValue(aLastInSketch);
}
- else if (anEdge->isCircle()) {
- std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
- double aRadius = aCircle->radius();
-
- double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction());
- if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
- return; // circle is not in the plane, parallel to the sketch plane
-
- std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
- std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
-
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Circle::ID());
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
- aCenterPnt->setValue(aCenterInSketch);
- aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aRadius);
+ else if (anEdge->isCircle() || anEdge->isEllipse()) {
+ GeomAlgoAPI_Projection aProjAlgo(aSketchPlane);
+ GeomCurvePtr aProjectedCurve = aProjAlgo.project(anEdge);
+
+ if (aProjectedCurve->isCircle()) {
+ rebuildProjectedFeature(aProjection, SketchPlugin_Circle::ID());
+
+ GeomAPI_Circ aCircle(aProjectedCurve);
+ std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle.center());
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius());
+ }
+ else if (aProjectedCurve->isEllipse()) {
+ rebuildProjectedFeature(aProjection, SketchPlugin_Ellipse::ID());
+
+ GeomAPI_Ellipse anEllipse(aProjectedCurve);
+ std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(anEllipse.center());
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
+ std::shared_ptr<GeomAPI_Pnt> aFocus = aSketchPlane->project(anEllipse.firstFocus());
+ std::shared_ptr<GeomAPI_Pnt2d> aFocusInSketch = sketch()->to2D(aFocus);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Ellipse::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
+ aFocusPnt->setValue(aFocusInSketch);
+ aProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(
+ anEllipse.minorRadius());
+ }
+ else
+ return;
}
else if (anEdge->isArc()) {
std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
bool isInversed = aNormalsDot < 0.;
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
+ rebuildProjectedFeature(aProjection, SketchPlugin_Arc::ID());
bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
}
}
}
+
+bool SketchPlugin_Projection::rebuildProjectedFeature(FeaturePtr& theProjection,
+ const std::string& theResultType,
+ bool theRemoveOnly)
+{
+ bool isRebuild = false;
+ if (theProjection && theProjection->getKind() != theResultType) {
+ DocumentPtr aDoc = sketch()->document();
+
+ AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
+ aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection
+ std::set<FeaturePtr> aFeaturesToBeRemoved;
+ aFeaturesToBeRemoved.insert(theProjection);
+ ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
+ theProjection = FeaturePtr();
+ aRefAttr->setObject(theProjection);
+ isRebuild = true;
+ }
+
+ if (!theProjection && !theRemoveOnly)
+ theProjection = sketch()->addFeature(theResultType);
+ return isRebuild;
+}
/// \brief Find projection of a feature onto sketch plane
void computeProjection(const std::string& theID);
+ /// \brief Delete already calculated projected feature
+ /// if the selection of the projection is changed
+ bool rebuildProjectedFeature(FeaturePtr& theProjection,
+ const std::string& theResultType,
+ bool theRemoveOnly = false);
+
bool myIsComputing;
};
#include <GeomAPI_Circ.h>
#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Ellipse.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Vertex.h>
double aDot = fabs(aNormal->dot(aLineDir));
bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance;
if (!aValid)
- theError = "Error: Edge is already in the sketch plane.";
+ theError = "Error: Line is orthogonal to the sketch plane.";
return aValid;
}
else if (anEdge->isCircle() || anEdge->isArc()) {
std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
std::shared_ptr<GeomAPI_Dir> aCircNormal = aCircle->normal();
double aDot = fabs(aNormal->dot(aCircNormal));
- bool aValid = fabs(aDot - 1.0) < tolerance * tolerance;
+ bool aValid = aDot >= tolerance * tolerance;
if (!aValid)
- theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane."
- : "Error: Arc is already in the sketch plane.");
+ theError.arg(anEdge->isCircle() ? "Error: Circle is orthogonal to the sketch plane."
+ : "Error: Arc is orthogonal to the sketch plane.");
+ return aValid;
+ }
+ else if (anEdge->isEllipse()) {
+ std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+ std::shared_ptr<GeomAPI_Dir> anEllipseNormal = anEllipse->normal();
+ double aDot = fabs(aNormal->dot(anEllipseNormal));
+ bool aValid = aDot >= tolerance * tolerance;
+ if (!aValid)
+ theError.arg(anEdge->isEllipse() ? "Error: Ellipse is orthogonal to the sketch plane."
+ : "Error: Elliptic Arc is orthogonal to the sketch plane.");
return aValid;
}
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(0, -100, 20)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchAPI_Line(SketchLine_1).startPoint(), 100, True)
+model.do()
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), model.selection("EDGE", "PartSet/OX"), 30)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), True)
+SketchCircle_2 = SketchProjection_2.createdFeature()
+model.do()
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_3 = Sketch_3.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face]"), True)
+SketchEllipse_1 = SketchProjection_3.createdFeature()
+SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), True)
+SketchEllipse_2 = SketchProjection_4.createdFeature()
+model.do()
+model.end()
+
+from GeomAPI import *
+
+circle2 = SketchCircle_2.results()[-1].resultSubShapePair()[0].shape()
+assert(circle2.isEdge() and circle2.edge().isCircle())
+ellipse1 = SketchEllipse_1.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse1.isEdge() and ellipse1.edge().isEllipse())
+ellipse2 = SketchEllipse_2.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse2.isEdge() and ellipse2.edge().isEllipse())
+
+assert(model.checkPythonDump())
# Test projection to slope side face of the prism
Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_2/SketchLine_2"))
-aFailedIDs = set([0, 1])
+aFailedIDs = set([1])
testProjections(Part_1_doc, Sketch_8, aProjectedList, aFailedIDs)
model.end()