X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchAPI%2FSketchAPI_Sketch.cpp;h=823897f5a6e2213e98c2a0e07d3fa8fd79e7f0ec;hb=fc72d43b677baa05ae7fd317346fd8b723b799ed;hp=d9fff77cebdb054398ca78d6a3ba6589f84605ea;hpb=d561e62cb53549341f3ea66993f9cbe8d0022c77;p=modules%2Fshaper.git diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index d9fff77ce..823897f5a 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -1,11 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -// Name : SketchAPI_Sketch.cpp -// Purpose: +// Copyright (C) 2014-2023 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 // -// History: -// 07/06/16 - Sergey POKHODENKO - Creation of the file -//-------------------------------------------------------------------------------------- #include "SketchAPI_Sketch.h" //-------------------------------------------------------------------------------------- #include @@ -13,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -23,12 +36,17 @@ #include #include #include -#include +#include #include +#include #include #include +#include +#include +#include #include //-------------------------------------------------------------------------------------- +#include #include #include #include @@ -39,16 +57,34 @@ #include //-------------------------------------------------------------------------------------- #include "SketchAPI_Arc.h" +#include "SketchAPI_BSpline.h" #include "SketchAPI_Circle.h" +#include "SketchAPI_Ellipse.h" +#include "SketchAPI_EllipticArc.h" #include "SketchAPI_IntersectionPoint.h" #include "SketchAPI_Line.h" +#include "SketchAPI_MacroArc.h" +#include "SketchAPI_MacroCircle.h" +#include "SketchAPI_MacroEllipse.h" +#include "SketchAPI_MacroEllipticArc.h" #include "SketchAPI_Mirror.h" +#include "SketchAPI_Offset.h" #include "SketchAPI_Point.h" #include "SketchAPI_Projection.h" #include "SketchAPI_Rectangle.h" #include "SketchAPI_Rotation.h" #include "SketchAPI_Translation.h" //-------------------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include +#include +//-------------------------------------------------------------------------------------- SketchAPI_Sketch::SketchAPI_Sketch( const std::shared_ptr & theFeature) : ModelHighAPI_Interface(theFeature) @@ -107,6 +143,25 @@ void SketchAPI_Sketch::setPlane(const std::shared_ptr & thePlane) execute(); } +void SketchAPI_Sketch::setPlane(const ModelHighAPI_Selection & thePlane, + bool theRemoveExternalDependency) +{ + FeaturePtr aSketch = feature(); + + DocumentPtr aDoc = aSketch->document(); + bool useVisible = false; + FeaturePtr aCurFeatureBefore = aDoc->currentFeature(useVisible); + aDoc->setCurrentFeature(aSketch, useVisible); + + if (theRemoveExternalDependency) + aSketch->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL()); + + setExternal(thePlane); + + aDoc->setCurrentFeature(aCurFeatureBefore, useVisible); +} + +//-------------------------------------------------------------------------------------- void SketchAPI_Sketch::setExternal(const ModelHighAPI_Selection & theExternal) { fillAttribute(theExternal, myexternal); @@ -168,7 +223,7 @@ SketchPtr addSketch(const std::shared_ptr & thePart, } SketchPtr addSketch(const std::shared_ptr & thePart, - const std::string & theExternalName) + const std::wstring & theExternalName) { std::shared_ptr aFeature = thePart->addFeature(SketchAPI_Sketch::ID()); return SketchPtr( @@ -182,6 +237,95 @@ SketchPtr addSketch(const std::shared_ptr & thePart, return SketchPtr(new SketchAPI_Sketch(aFeature, thePlaneObject)); } +//-------------------------------------------------------------------------------------- +SketchPtr copySketch(const std::shared_ptr & thePart, + const SketchPtr & theSketch) +{ + FeaturePtr aCopyer = thePart->addFeature(SketchPlugin_SketchCopy::ID()); + aCopyer->reference(SketchPlugin_SketchCopy::BASE_ID())->setValue(theSketch->feature()); + aCopyer->execute(); + + FeaturePtr aNewSketch = thePart->nextFeature(aCopyer); + + // perform removing the macro-feature + thePart->removeFeature(aCopyer); + apply(); + + return SketchPtr(new SketchAPI_Sketch(aNewSketch)); +} + + +//-------------------------------------------------------------------------------------- +std::list< std::shared_ptr > SketchAPI_Sketch::getFreePoints() +{ + std::list< std::shared_ptr > aFreePoints; + std::list aPoints = SketcherPrs_Tools::getFreePoints(compositeFeature()); + for (std::list::iterator anIt = aPoints.begin(); anIt != aPoints.end(); ++anIt) { + FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt); + PointPtr aPoint(new SketchAPI_Point(aFeature)); + aFreePoints.push_back(aPoint); + } + return aFreePoints; +} + +//-------------------------------------------------------------------------------------- +static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape) +{ + GeomCurvePtr aCurve(new GeomAPI_Curve(theShape)); + if (aCurve->isTrimmed()) + aCurve = aCurve->basisCurve(); + return aCurve; +} + +void SketchAPI_Sketch::changeFacesOrder( + const std::list >& theFaces) +{ + // collect faces of the sketch + ResultConstructionPtr aSketchResult = + std::dynamic_pointer_cast(feature()->lastResult()); + if (!aSketchResult) { + // sketch is nested to a boolean operation, thus, it has no result yet. + feature()->execute(); + aSketchResult = + std::dynamic_pointer_cast(feature()->lastResult()); + } + std::list aFaces; + int aFacesNum = aSketchResult->facesNum(); + for (int i = 0; i < aFacesNum; ++i) + aFaces.push_back(aSketchResult->face(i)); + // find new faces order according to the given lists of edges + std::list aNewFacesOrder; + std::list >::const_iterator anIt = theFaces.begin(); + for (; anIt != theFaces.end(); ++anIt) { + // find the appropriate face + std::list::iterator aFIt = aFaces.begin(); + for (; aFIt != aFaces.end(); ++aFIt) { + std::list::const_iterator aEdgeIt = anIt->begin(); + GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE); + for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) { + ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first; + if (!aCurRes) + break; + GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape()); + GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current()); + if (!aCurve1->isEqual(aCurve2)) + break; + } + + if (aEdgeIt == anIt->end() && !aFExp.more()) { + // face is found + aNewFacesOrder.push_back(*aFIt); + aFaces.erase(aFIt); + break; + } + } + } + // place the rest faces at the end of new faces list + if (!aFaces.empty()) + aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end()); + // update the result of the sketch with the new order of faces + aSketchResult->setFacesOrder(aNewFacesOrder); +} //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addPoint( @@ -205,7 +349,7 @@ std::shared_ptr compositeFeature()->addFeature(SketchPlugin_Point::ID()); return PointPtr(new SketchAPI_Point(aFeature, theExternal)); } -std::shared_ptr SketchAPI_Sketch::addPoint(const std::string & theExternalName) +std::shared_ptr SketchAPI_Sketch::addPoint(const std::wstring & theExternalName) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Point::ID()); @@ -214,18 +358,24 @@ std::shared_ptr SketchAPI_Sketch::addPoint(const std::string & //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addIntersectionPoint( - const ModelHighAPI_Selection & theExternal) + const ModelHighAPI_Selection & theExternal, + bool theKeepResult) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID()); - return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternal)); + IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternal)); + anIntersection->setIncludeToResult(theKeepResult); + return anIntersection; } std::shared_ptr SketchAPI_Sketch::addIntersectionPoint( - const std::string & theExternalName) + const std::wstring & theExternalName, + bool theKeepResult) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID()); - return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternalName)); + IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternalName)); + anIntersection->setIncludeToResult(theKeepResult); + return anIntersection; } //-------------------------------------------------------------------------------------- @@ -251,7 +401,7 @@ std::shared_ptr compositeFeature()->addFeature(SketchPlugin_Line::ID()); return LinePtr(new SketchAPI_Line(aFeature, theExternal)); } -std::shared_ptr SketchAPI_Sketch::addLine(const std::string & theExternalName) +std::shared_ptr SketchAPI_Sketch::addLine(const std::wstring & theExternalName) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Line::ID()); @@ -275,6 +425,49 @@ std::shared_ptr SketchAPI_Sketch::addRectangle( return RectanglePtr(new SketchAPI_Rectangle(aFeature, theStartPoint, theEndPoint)); } +static std::shared_ptr pointCoordinates( + const std::pair, ModelHighAPI_RefAttr> & thePoint) +{ + if (thePoint.first) + return thePoint.first; + + AttributePtr anAttr = thePoint.second.attr(); + if (thePoint.second.object()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(thePoint.second.object()); + if (aFeature) + anAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID()); + } + + std::shared_ptr aPntAttr = + std::dynamic_pointer_cast(anAttr); + if (aPntAttr) + return aPntAttr->pnt(); + return std::shared_ptr(); +} + +std::shared_ptr SketchAPI_Sketch::addRectangleCentered( + const std::pair, ModelHighAPI_RefAttr> & theCenter, + const std::pair, ModelHighAPI_RefAttr> & theCorner) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchAPI_Rectangle::ID()); + RectanglePtr aRect(new SketchAPI_Rectangle(aFeature)); + fillAttribute("RectangleTypeCentered", aRect->type()); + if (!theCenter.second.isEmpty()) + fillAttribute(theCenter.second, aRect->centerPointRef()); + fillAttribute(pointCoordinates(theCenter), aRect->centerPoint()); + fillAttribute(pointCoordinates(theCorner), aRect->cornerPoint()); + aRect->execute(); + + if (!theCorner.second.isEmpty() && aRect->linesList()->size() > 1) { + // get start point of the last line in rectangle and apply coindidence constraint + FeaturePtr aLine = ModelAPI_Feature::feature(aRect->linesList()->object(3)); + AttributePtr aEndPnt = aLine->attribute(SketchPlugin_Line::START_ID()); + setCoincident(ModelHighAPI_RefAttr(aEndPnt), theCorner.second); + } + return aRect; +} + //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addCircle(double theCenterX, double theCenterY, @@ -294,23 +487,45 @@ std::shared_ptr SketchAPI_Sketch::addCircle( return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius)); } -std::shared_ptr SketchAPI_Sketch::addCircle(double theX1, double theY1, - double theX2, double theY2, - double theX3, double theY3) +std::shared_ptr SketchAPI_Sketch::addCircle(double theCenterX, + double theCenterY, + double thePassedX, + double thePassedY) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Circle::ID()); - return CirclePtr(new SketchAPI_Circle(aFeature, theX1, theY1, theX2, theY2, theX3, theY3)); + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY, + thePassedX, thePassedY)); } -std::shared_ptr SketchAPI_Sketch::addCircle( - const std::shared_ptr& thePoint1, - const std::shared_ptr& thePoint2, - const std::shared_ptr& thePoint3) +std::shared_ptr SketchAPI_Sketch::addCircle( + const std::shared_ptr& theCenterPoint, + const std::shared_ptr& thePassedPoint) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Circle::ID()); - return CirclePtr(new SketchAPI_Circle(aFeature, thePoint1, thePoint2, thePoint3)); + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint)); +} + +std::shared_ptr SketchAPI_Sketch::addCircle(double theX1, double theY1, + double theX2, double theY2, + double theX3, double theY3) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1, + theX2, theY2, + theX3, theY3)); +} + +std::shared_ptr SketchAPI_Sketch::addCircle( + const std::shared_ptr& thePoint1, + const std::shared_ptr& thePoint2, + const std::shared_ptr& thePoint3) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3)); } std::shared_ptr @@ -321,9 +536,8 @@ std::shared_ptr return CirclePtr(new SketchAPI_Circle(aFeature, theExternal)); } -std::shared_ptr SketchAPI_Sketch::addCircle(const std::string & theExternalName) +std::shared_ptr SketchAPI_Sketch::addCircle(const std::wstring & theExternalName) { - // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary? std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Circle::ID()); return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName)); @@ -355,46 +569,58 @@ std::shared_ptr SketchAPI_Sketch::addArc( return ArcPtr(new SketchAPI_Arc(aFeature, theCenter, theStart, theEnd, theInversed)); } -std::shared_ptr SketchAPI_Sketch::addArc(double theStartX, double theStartY, +std::shared_ptr SketchAPI_Sketch::addArc(double theStartX, double theStartY, double theEndX, double theEndY, double thePassedX, double thePassedY) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Arc::ID()); - return ArcPtr(new SketchAPI_Arc(aFeature, - theStartX, theStartY, - theEndX, theEndY, - thePassedX, thePassedY)); + compositeFeature()->addFeature(SketchPlugin_MacroArc::ID()); + return MacroArcPtr(new SketchAPI_MacroArc(aFeature, + theStartX, theStartY, + theEndX, theEndY, + thePassedX, thePassedY)); } -std::shared_ptr SketchAPI_Sketch::addArc( +std::shared_ptr SketchAPI_Sketch::addArc( const std::shared_ptr& theStart, const std::shared_ptr& theEnd, const std::shared_ptr& thePassed) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Arc::ID()); - return ArcPtr(new SketchAPI_Arc(aFeature, theStart, theEnd, thePassed)); + compositeFeature()->addFeature(SketchPlugin_MacroArc::ID()); + return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theStart, theEnd, thePassed)); } -std::shared_ptr SketchAPI_Sketch::addArc( +std::shared_ptr SketchAPI_Sketch::addArc( const ModelHighAPI_RefAttr& theTangentPoint, double theEndX, double theEndY, - bool theInversed) + bool theInversed, + bool theTransversal) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Arc::ID()); - return ArcPtr(new SketchAPI_Arc(aFeature, theTangentPoint, theEndX, theEndY, theInversed)); + compositeFeature()->addFeature(SketchPlugin_MacroArc::ID()); + MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature)); + if (theTransversal) + aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed); + else + aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed); + return aMacroArc; } -std::shared_ptr SketchAPI_Sketch::addArc( +std::shared_ptr SketchAPI_Sketch::addArc( const ModelHighAPI_RefAttr& theTangentPoint, const std::shared_ptr& theEnd, - bool theInversed) + bool theInversed, + bool theTransversal) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Arc::ID()); - return ArcPtr(new SketchAPI_Arc(aFeature, theTangentPoint, theEnd, theInversed)); + compositeFeature()->addFeature(SketchPlugin_MacroArc::ID()); + MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature)); + if (theTransversal) + aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed); + else + aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed); + return aMacroArc; } std::shared_ptr SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal) @@ -404,29 +630,290 @@ std::shared_ptr SketchAPI_Sketch::addArc(const ModelHighAPI_Selec return ArcPtr(new SketchAPI_Arc(aFeature, theExternal)); } -std::shared_ptr SketchAPI_Sketch::addArc(const std::string & theExternalName) +std::shared_ptr SketchAPI_Sketch::addArc(const std::wstring & theExternalName) { - // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary? std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Arc::ID()); return ArcPtr(new SketchAPI_Arc(aFeature, theExternalName)); } //-------------------------------------------------------------------------------------- -std::shared_ptr SketchAPI_Sketch::addProjection( - const ModelHighAPI_Selection & theExternalFeature) +std::shared_ptr SketchAPI_Sketch::addEllipse( + double theCenterX, double theCenterY, + double theFocusX, double theFocusY, + double theMinorRadius) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_Projection::ID()); - return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalFeature)); + compositeFeature()->addFeature(SketchPlugin_Ellipse::ID()); + return EllipsePtr(new SketchAPI_Ellipse(aFeature, + theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipse( + const std::shared_ptr& theCenter, + const std::shared_ptr& theFocus, + double theMinorRadius) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Ellipse::ID()); + return EllipsePtr(new SketchAPI_Ellipse(aFeature, theCenter, theFocus, theMinorRadius)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipse( + double thePoint1X, double thePoint1Y, + double thePoint2X, double thePoint2Y, + double thePassedX, double thePassedY, + bool isPoint1Center) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID()); + return MacroEllipsePtr(new SketchAPI_MacroEllipse(aFeature, + thePoint1X, thePoint1Y, thePoint2X, thePoint2Y, thePassedX, thePassedY, isPoint1Center)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipse( + const PointOrReference& thePoint1, + const PointOrReference& thePoint2, + const PointOrReference& thePassedPoint, + bool isPoint1Center) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID()); + MacroEllipsePtr anEllipse; + if (thePoint1.second.isEmpty() && + thePoint2.second.isEmpty() && + thePassedPoint.second.isEmpty()) { + anEllipse.reset(new SketchAPI_MacroEllipse(aFeature, + thePoint1.first, thePoint2.first, thePassedPoint.first, isPoint1Center)); + } + else { + anEllipse.reset(new SketchAPI_MacroEllipse(aFeature, + thePoint1.first, thePoint1.second, + thePoint2.first, thePoint2.second, + thePassedPoint.first, thePassedPoint.second, + isPoint1Center)); + } + return anEllipse; +} + +std::shared_ptr SketchAPI_Sketch::addEllipse( + const ModelHighAPI_Selection & theExternal) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Ellipse::ID()); + return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternal)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipse( + const std::wstring & theExternalName) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Ellipse::ID()); + return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternalName)); +} + +//-------------------------------------------------------------------------------------- +std::shared_ptr SketchAPI_Sketch::addEllipticArc( + double theCenterX, double theCenterY, + double theFocusX, double theFocusY, + double theStartX, double theStartY, + double theEndX, double theEndY, + bool theInversed) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID()); + return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, + theCenterX, theCenterY, + theFocusX, theFocusY, + theStartX, theStartY, + theEndX, theEndY, + theInversed)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipticArc( + const PointOrReference& theCenter, + const PointOrReference& theMajorAxisPoint, + const PointOrReference& theStartPoint, + const PointOrReference& theEndPoint, + bool theInversed) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroEllipticArc::ID()); + return MacroEllipticArcPtr(new SketchAPI_MacroEllipticArc(aFeature, + theCenter.first, theCenter.second, + theMajorAxisPoint.first, theMajorAxisPoint.second, + theStartPoint.first, theStartPoint.second, + theEndPoint.first, theEndPoint.second, + theInversed)); } +std::shared_ptr SketchAPI_Sketch::addEllipticArc( + const ModelHighAPI_Selection & theExternal) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID()); + return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternal)); +} + +std::shared_ptr SketchAPI_Sketch::addEllipticArc( + const std::wstring & theExternalName) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID()); + return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternalName)); +} + +//-------------------------------------------------------------------------------------- + +std::shared_ptr SketchAPI_Sketch::addSpline( + const ModelHighAPI_Selection & external, + const int degree, + const std::list& poles, + const std::list& weights, + const std::list& knots, + const std::list& multiplicities, + const bool periodic) +{ + // split poles and references to other shapes + bool hasReference = false; + std::list aPoints; + std::list aReferences; + for (std::list::const_iterator it = poles.begin(); it != poles.end(); ++it) { + aPoints.push_back(it->first); + aReferences.push_back(it->second); + if (!it->second.isEmpty()) + hasReference = true; + } + + BSplinePtr aBSpline; + CompositeFeaturePtr aSketch = compositeFeature(); + if (hasReference) { + // use macro-feature to create coincidences to referred features + FeaturePtr aMacroFeature = aSketch->addFeature( + periodic ? SketchPlugin_MacroBSplinePeriodic::ID() : SketchPlugin_MacroBSpline::ID()); + AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast( + aMacroFeature->attribute(SketchPlugin_MacroBSpline::POLES_ID())); + AttributeDoubleArrayPtr aWeightsAttr = + aMacroFeature->data()->realArray(SketchPlugin_MacroBSpline::WEIGHTS_ID()); + AttributeRefAttrListPtr aPolesRefAttr = + aMacroFeature->data()->refattrlist(SketchPlugin_MacroBSpline::REF_POLES_ID()); + // always generate a control polygon to apply coincidences correctly + aMacroFeature->boolean(SketchPlugin_MacroBSpline::CONTROL_POLYGON_ID())->setValue(true); + // initialize B-spline attributes + fillAttribute(aPoints, aPolesAttr); + if (weights.empty()) + fillAttribute(std::list(poles.size(), 1.0), aWeightsAttr); + else + fillAttribute(weights, aWeightsAttr); + fillAttribute(aReferences, aPolesRefAttr); + apply(); // to kill macro-feature + + // find created B-spline feature + const std::string& aKindToFind = + periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID(); + int aNbSubs = aSketch->numberOfSubs(); + for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) { + FeaturePtr aFeature = aSketch->subFeature(anIndex); + if (aFeature->getKind() == aKindToFind) { + aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature) + : new SketchAPI_BSpline(aFeature)); + aBSpline->execute(); + break; + } + } + } + else { + // compute B-spline by parameters + FeaturePtr aFeature = aSketch->addFeature( + periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID()); + + aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature) + : new SketchAPI_BSpline(aFeature)); + if (external.variantType() != ModelHighAPI_Selection::VT_Empty) + aBSpline->setByExternal(external); + else if (knots.empty() || multiplicities.empty()) + aBSpline->setByDegreePolesAndWeights(degree, aPoints, weights); + else + aBSpline->setByParameters(degree, aPoints, weights, knots, multiplicities); + } + return aBSpline; +} + +//-------------------------------------------------------------------------------------- +static std::shared_ptr buildInterpolation( + const CompositeFeaturePtr& theSketch, + const FeaturePtr& theCurveFittingFeature, + const std::list& points, + const bool periodic, + const bool closed) +{ + AttributeBooleanPtr aPeriodicAttr = + theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::PERIODIC_ID()); + fillAttribute(periodic, aPeriodicAttr); + AttributeBooleanPtr aClosedAttr = + theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::CLOSED_ID()); + fillAttribute(closed, aClosedAttr); + AttributeRefAttrListPtr aPointsAttr = + theCurveFittingFeature->refattrlist(SketchPlugin_CurveFitting::POINTS_ID()); + fillAttribute(points, aPointsAttr); + apply(); // to execute and kill the macro-feature + + // find created B-spline feature + BSplinePtr aBSpline; + const std::string& aKindToFind = + periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID(); + int aNbSubs = theSketch->numberOfSubs(); + for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) { + FeaturePtr aFeature = theSketch->subFeature(anIndex); + if (aFeature->getKind() == aKindToFind) { + aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature) + : new SketchAPI_BSpline(aFeature)); + aBSpline->execute(); + break; + } + } + return aBSpline; +} + +std::shared_ptr SketchAPI_Sketch::addInterpolation( + const std::list& points, + const bool periodic, + const bool closed) +{ + CompositeFeaturePtr aSketch = compositeFeature(); + FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID()); + anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID()) + ->setValue(SketchPlugin_CurveFitting::TYPE_INTERPOLATION_ID()); + return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed); +} + +std::shared_ptr SketchAPI_Sketch::addApproximation( + const std::list& points, + const ModelHighAPI_Double& precision, + const bool periodic, + const bool closed) +{ + CompositeFeaturePtr aSketch = compositeFeature(); + FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID()); + anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID()) + ->setValue(SketchPlugin_CurveFitting::TYPE_APPROXIMATION_ID()); + fillAttribute(precision, anInterpFeature->real(SketchPlugin_CurveFitting::PRECISION_ID())); + return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed); +} + +//-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addProjection( - const std::string & theExternalName) + const ModelHighAPI_Selection & theExternalFeature, + bool keepResult, + bool keepRefToOriginal) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Projection::ID()); - return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalName)); + ProjectionPtr aProjection(new SketchAPI_Projection(aFeature)); + aProjection->setIncludeToResult(keepResult); + aProjection->setKeepReferenceToOriginal(keepRefToOriginal); + aProjection->setExternalFeature(theExternalFeature); + return aProjection; } //-------------------------------------------------------------------------------------- @@ -439,6 +926,18 @@ std::shared_ptr SketchAPI_Sketch::addMirror( return MirrorPtr(new SketchAPI_Mirror(aFeature, theMirrorLine, theObjects)); } +//-------------------------------------------------------------------------------------- +std::shared_ptr SketchAPI_Sketch::addOffset( + const std::list > & theObjects, + const ModelHighAPI_Double & theValue, + const bool theReversed, + const std::string & theJointType) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Offset::ID()); + return OffsetPtr(new SketchAPI_Offset(aFeature, theObjects, theValue, theReversed, theJointType)); +} + //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addTranslation( const std::list > & theObjects, @@ -459,27 +958,31 @@ std::shared_ptr SketchAPI_Sketch::addRotation( const ModelHighAPI_RefAttr & theCenter, const ModelHighAPI_Double & theAngle, const ModelHighAPI_Integer & theNumberOfObjects, - bool theFullValue) + bool theFullValue, + bool theReversed) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MultiRotation::ID()); return RotationPtr( new SketchAPI_Rotation(aFeature, theObjects, theCenter, - theAngle, theNumberOfObjects, theFullValue)); + theAngle, theNumberOfObjects, theFullValue, theReversed)); } //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addSplit( - const ModelHighAPI_Reference& theFeature, - const ModelHighAPI_RefAttr& thePoint1, - const ModelHighAPI_RefAttr& thePoint2) + const ModelHighAPI_Reference& theFeature, + const std::shared_ptr& thePositionPoint) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchPlugin_ConstraintSplit::ID()); - fillAttribute(theFeature, aFeature->reference(SketchPlugin_Constraint::VALUE())); - fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); - fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); - //aFeature->execute(); + compositeFeature()->addFeature(SketchPlugin_Split::ID()); + fillAttribute(theFeature, aFeature->reference(SketchPlugin_Split::SELECTED_OBJECT())); + + AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Split::SELECTED_POINT()); + if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(anAttribute); + fillAttribute(thePositionPoint, aPointAttr); + } + return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } @@ -490,9 +993,9 @@ std::shared_ptr SketchAPI_Sketch::addTrim( { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Trim::ID()); - fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::BASE_OBJECT())); + fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::SELECTED_OBJECT())); - AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::ENTITY_POINT()); + AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::SELECTED_POINT()); if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) { AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(anAttribute); fillAttribute(thePositionPoint, aPointAttr); @@ -505,16 +1008,39 @@ std::shared_ptr SketchAPI_Sketch::addTrim( std::shared_ptr SketchAPI_Sketch::setAngle( const ModelHighAPI_RefAttr & theLine1, const ModelHighAPI_RefAttr & theLine2, - const ModelHighAPI_Double & theValue) + const ModelHighAPI_Double & theValue, + const std::string& theType) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID()); - fillAttribute(SketcherPrs_Tools::ANGLE_DIRECT, - aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID())); - // fill the value before llines to avoid calculation of angle value by the Angle feature - fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID())); + + const int aVersion = theType.empty() ? SketchPlugin_ConstraintAngle::THE_VERSION_0 + : SketchPlugin_ConstraintAngle::THE_VERSION_1; + fillAttribute(aVersion, aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID())); + + int aType = (int)SketcherPrs_Tools::ANGLE_DIRECT; + fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::PREV_TYPE_ID())); + fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID())); + + if (aVersion == SketchPlugin_ConstraintAngle::THE_VERSION_0) + fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID())); + fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); + + if (aVersion == SketchPlugin_ConstraintAngle::THE_VERSION_1) { + std::string aTypeLC = theType; + std::transform(aTypeLC.begin(), aTypeLC.end(), aTypeLC.begin(), + [](char c) { return static_cast(::tolower(c)); }); + if (aTypeLC == "supplementary") + aType = (int)SketcherPrs_Tools::ANGLE_COMPLEMENTARY; + else if (aTypeLC == "backward") + aType = (int)SketcherPrs_Tools::ANGLE_BACKWARD; + + fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID())); + fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID())); + } + aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } @@ -526,12 +1052,13 @@ std::shared_ptr SketchAPI_Sketch::setAngleComplementary( { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID()); + fillAttribute(SketchPlugin_ConstraintAngle::THE_VERSION_0, + aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID())); fillAttribute(SketcherPrs_Tools::ANGLE_COMPLEMENTARY, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID())); fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID())); fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); -// fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE())); aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } @@ -543,12 +1070,13 @@ std::shared_ptr SketchAPI_Sketch::setAngleBackward( { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID()); + fillAttribute(SketchPlugin_ConstraintAngle::THE_VERSION_0, + aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID())); fillAttribute(SketcherPrs_Tools::ANGLE_BACKWARD, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID())); fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID())); fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); -// fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE())); aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } @@ -580,13 +1108,61 @@ std::shared_ptr SketchAPI_Sketch::setCollinear( std::shared_ptr SketchAPI_Sketch::setDistance( const ModelHighAPI_RefAttr & thePoint, const ModelHighAPI_RefAttr & thePointOrLine, - const ModelHighAPI_Double & theValue) + const ModelHighAPI_Double & theValue, + bool isSigned) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintDistance::ID()); fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(thePointOrLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE())); + fillAttribute(isSigned, aFeature->boolean(SketchPlugin_ConstraintDistance::SIGNED())); + aFeature->execute(); + return InterfacePtr(new ModelHighAPI_Interface(aFeature)); +} + +std::shared_ptr SketchAPI_Sketch::setSignedDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue) +{ + return setDistance(thePoint, thePointOrLine, theValue, true); +} + +std::shared_ptr SketchAPI_Sketch::setUnsignedDistance( + const ModelHighAPI_RefAttr & thePoint, + const ModelHighAPI_RefAttr & thePointOrLine, + const ModelHighAPI_Double & theValue) +{ + return setDistance(thePoint, thePointOrLine, theValue, false); +} + +std::shared_ptr SketchAPI_Sketch::setHorizontalDistance( + const ModelHighAPI_RefAttr & thePoint1, + const ModelHighAPI_RefAttr & thePoint2, + const ModelHighAPI_Double & theValue) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID()); + fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); + fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); + fillAttribute(theValue, + aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID())); + aFeature->execute(); + return InterfacePtr(new ModelHighAPI_Interface(aFeature)); +} + +std::shared_ptr SketchAPI_Sketch::setVerticalDistance( + const ModelHighAPI_RefAttr & thePoint1, + const ModelHighAPI_RefAttr & thePoint2, + const ModelHighAPI_Double & theValue) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceVertical::ID()); + fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); + fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); + fillAttribute(theValue, + aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID())); aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } @@ -735,6 +1311,261 @@ std::shared_ptr SketchAPI_Sketch::setVertical( //-------------------------------------------------------------------------------------- +static std::shared_ptr pointCoordinates(const AttributePtr& thePoint) +{ + AttributePoint2DPtr aPnt = std::dynamic_pointer_cast(thePoint); + return aPnt ? aPnt->pnt() : std::shared_ptr(); +} + +static std::shared_ptr middlePointOnLine(const FeaturePtr& theFeature) +{ + AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::START_ID())); + AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::END_ID())); + + if (!aStartAttr || !aEndAttr) + return std::shared_ptr(); + + std::shared_ptr aStartPoint = aStartAttr->pnt()->xy(); + std::shared_ptr aEndPoint = aEndAttr->pnt()->xy(); + return std::shared_ptr( + new GeomAPI_Pnt2d(aStartPoint->added(aEndPoint)->multiplied(0.5))); +} + +static std::shared_ptr pointOnCircle(const FeaturePtr& theFeature) +{ + AttributePoint2DPtr aCenter = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Circle::CENTER_ID())); + AttributeDoublePtr aRadius = theFeature->real(SketchPlugin_Circle::RADIUS_ID()); + + if (!aCenter || !aRadius) + return std::shared_ptr(); + + return std::shared_ptr( + new GeomAPI_Pnt2d(aCenter->x() + aRadius->value(), aCenter->y())); +} + +static std::shared_ptr middlePointOnArc(const FeaturePtr& theFeature) +{ + static const double PI = 3.141592653589793238463; + + AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::CENTER_ID())); + AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::START_ID())); + AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::END_ID())); + + if (!aCenterAttr || !aStartAttr || !aEndAttr) + return std::shared_ptr(); + + std::shared_ptr aStartDir(new GeomAPI_Dir2d( + aStartAttr->x() - aCenterAttr->x(), aStartAttr->y() - aCenterAttr->y())); + std::shared_ptr aEndDir(new GeomAPI_Dir2d( + aEndAttr->x() - aCenterAttr->x(), aEndAttr->y() - aCenterAttr->y())); + + double anAngle = aStartDir->angle(aEndDir); + bool isReversed = theFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value(); + if (isReversed && anAngle > 0.) + anAngle -= 2.0 * PI; + else if (!isReversed && anAngle <= 0.) + anAngle += 2.0 * PI; + + double cosA = cos(anAngle); + double sinA = sin(anAngle); + + // rotate start dir to find middle point on arc + double aRadius = aStartAttr->pnt()->distance(aCenterAttr->pnt()); + double x = aCenterAttr->x() + aRadius * (aStartDir->x() * cosA - aStartDir->y() * sinA); + double y = aCenterAttr->y() + aRadius * (aStartDir->x() * sinA + aStartDir->y() * cosA); + + return std::shared_ptr(new GeomAPI_Pnt2d(x, y)); +} + +static std::shared_ptr pointOnEllipse(const FeaturePtr& theFeature, + bool isEllipse = true) +{ + const std::string& anAttrName = isEllipse ? SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() : + SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID(); + AttributePoint2DPtr aMajorAxisEnd = std::dynamic_pointer_cast( + theFeature->attribute(anAttrName)); + return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr(); +} + +static std::shared_ptr middlePointOnBSpline(const FeaturePtr& theFeature, + SketchAPI_Sketch* theSketch) +{ + GeomAPI_Edge anEdge(theFeature->lastResult()->shape()); + GeomPointPtr aMiddle = anEdge.middlePoint(); + return theSketch->to2D(aMiddle); +} + +static std::shared_ptr middlePoint(const ObjectPtr& theObject, + SketchAPI_Sketch* theSketch) +{ + std::shared_ptr aMiddlePoint; + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature) { + // move only features of the following types + const std::string& aFeatureKind = aFeature->getKind(); + if (aFeatureKind == SketchPlugin_Point::ID()) + aMiddlePoint = pointCoordinates(aFeature->attribute(SketchPlugin_Point::COORD_ID())); + else if (aFeatureKind == SketchPlugin_Line::ID()) + aMiddlePoint = middlePointOnLine(aFeature); + else if (aFeatureKind == SketchPlugin_Circle::ID()) + aMiddlePoint = pointOnCircle(aFeature); + else if (aFeatureKind == SketchPlugin_Arc::ID()) + aMiddlePoint = middlePointOnArc(aFeature); + else if (aFeatureKind == SketchPlugin_Ellipse::ID()) + aMiddlePoint = pointOnEllipse(aFeature); + else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) + aMiddlePoint = pointOnEllipse(aFeature, false); + else if (aFeatureKind == SketchPlugin_BSpline::ID() || + aFeatureKind == SketchPlugin_BSplinePeriodic::ID()) + aMiddlePoint = middlePointOnBSpline(aFeature, theSketch); + } + return aMiddlePoint; +} + +void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity, + const std::shared_ptr& theTargetPoint) +{ + std::shared_ptr aMessage(new ModelAPI_ObjectMovedMessage); + theMovedEntity.fillMessage(aMessage); + + std::shared_ptr anOriginalPosition; + if (aMessage->movedAttribute()) + anOriginalPosition = pointCoordinates(aMessage->movedAttribute()); + else + anOriginalPosition = middlePoint(aMessage->movedObject(), this); + + if (!anOriginalPosition) + return; // something has gone wrong, do not process movement + + aMessage->setOriginalPosition(anOriginalPosition); + aMessage->setCurrentPosition(theTargetPoint); + Events_Loop::loop()->send(aMessage); +} + +void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity, + double theTargetX, double theTargetY) +{ + std::shared_ptr aTargetPoint(new GeomAPI_Pnt2d(theTargetX, theTargetY)); + move(theMovedEntity, aTargetPoint); +} + +//-------------------------------------------------------------------------------------- + +std::shared_ptr SketchAPI_Sketch::to2D(const std::shared_ptr& thePoint) +{ + FeaturePtr aBase = feature(); + std::shared_ptr aC = std::dynamic_pointer_cast( + aBase->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + std::shared_ptr aNorm = std::dynamic_pointer_cast( + aBase->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aX = std::dynamic_pointer_cast( + aBase->attribute(SketchPlugin_Sketch::DIRX_ID())); + std::shared_ptr aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir()))); + + return thePoint->to2D(aC->pnt(), aX->dir(), aY); +} + +//-------------------------------------------------------------------------------------- + +static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2) +{ + // collect edges of the first face + std::list anEdges1; + for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) + anEdges1.push_back(anExp.current()); + // compare edges of faces + for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { + GeomShapePtr aCurrent = anExp.current(); + bool isFound = false; + std::list::iterator anIt1 = anEdges1.begin(); + for (; anIt1 != anEdges1.end(); ++anIt1) + if (aCurrent->isSameGeometry(*anIt1)) { + isFound = true; + anEdges1.erase(anIt1); + break; + } + if (!isFound) + return true; + } + return !anEdges1.empty(); +} + +static bool isCustomFacesOrder(CompositeFeaturePtr theSketch) +{ + ResultConstructionPtr aSketchResult = + std::dynamic_pointer_cast(theSketch->lastResult()); + if (!aSketchResult) + return false; + + std::shared_ptr aWires = + std::dynamic_pointer_cast(aSketchResult->shape()); + if (!aWires) + return false; + + // collect faces constructed by SketchBuilder algorithm + GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(), + aWires->norm(), aWires); + const ListOfShape& aFaces = aSketchBuilder.faces(); + + // compare faces stored in sketch with faces generated by SketchBuilder + int aNbSketchFaces = aSketchResult->facesNum(); + int aFaceIndex = 0; + for (ListOfShape::const_iterator aFIt = aFaces.begin(); + aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces; + ++aFIt, ++aFaceIndex) { + GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex); + GeomFacePtr aCurFace = (*aFIt)->face(); + if (isDifferent(aSketchFace, aCurFace)) + return true; + } + return false; +} + +static void edgesOfSketchFaces(CompositeFeaturePtr theSketch, + std::list >& theEdges) +{ + ResultConstructionPtr aSketchResult = + std::dynamic_pointer_cast(theSketch->lastResult()); + if (!aSketchResult) + return; + + // collect curves of the sketch + std::map aCurves; + int aSubNum = theSketch->numberOfSubs(); + for (int a = 0; a < aSubNum; ++a) { + FeaturePtr aSub = theSketch->subFeature(a); + const std::list& aResults = aSub->results(); + std::list::const_iterator aRes = aResults.cbegin(); + for (; aRes != aResults.cend(); aRes++) { + GeomShapePtr aCurShape = (*aRes)->shape(); + if (aCurShape && aCurShape->isEdge()) + aCurves[untrimmedCurve(aCurShape)] = *aRes; + } + } + + // convert each face to the list of results of its edges + int aFacesNum = aSketchResult->facesNum(); + for (int a = 0; a < aFacesNum; ++a) { + theEdges.push_back(std::list()); + std::list& aCurEdges = theEdges.back(); + + GeomFacePtr aFace = aSketchResult->face(a); + for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE); + anExp.more(); anExp.next()) { + GeomCurvePtr aCurrent = untrimmedCurve(anExp.current()); + aCurEdges.push_back(aCurves[aCurrent]); + } + } +} + +//-------------------------------------------------------------------------------------- + void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const { FeaturePtr aBase = feature(); @@ -754,7 +1585,7 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const aBase->attribute(SketchPlugin_Sketch::DIRX_ID()))->dir(); // Check the plane is coordinate plane - std::string aPlaneName = defaultPlane(anOrigin, aNormal, aDirX); + std::wstring aPlaneName = defaultPlane(anOrigin, aNormal, aDirX); if(anExternal->context()) { // checking for selected planes if (!aPlaneName.empty() && anExternal->context()->data() @@ -794,4 +1625,26 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const // dump sketch's subfeatures CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(aBase); theDumper.processSubs(aCompFeat, true); + + // if face order differs to the order generated by SketchBuilder, + // dump the list of faces for correct execution of the script + if (isCustomFacesOrder(aCompFeat)) { + std::list > aFaces; + edgesOfSketchFaces(aCompFeat, aFaces); + + const std::string& aSketchName = theDumper.name(aBase); + std::string aMethodName(".changeFacesOrder"); + std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' '); + + theDumper << aSketchName << aMethodName << "(["; + for (std::list >::iterator aFIt = aFaces.begin(); + aFIt != aFaces.end(); ++aFIt) { + if (aFIt != aFaces.begin()) + theDumper << ",\n" << aSpaceShift << " "; + theDumper << *aFIt; + } + theDumper << "\n" << aSpaceShift << " ])" << std::endl; + // call model.do() for correct update of the document's labels related to the changed faces + theDumper << "model.do()" << std::endl; + } }