From: asozinov Date: Tue, 6 Jun 2023 10:52:31 +0000 (+0100) Subject: [EDF] (2023-T1) Sketch middle point constrain should create point if missing X-Git-Tag: V9_12_0b1~10 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2FCR35150;p=modules%2Fshaper.git [EDF] (2023-T1) Sketch middle point constrain should create point if missing - Added new way for create middle point constraint: Only by segment - Added MacroMiddlePoint, which create point and middle constraint between point and passed object. Returns point - SketchAPI: added setMiddlePoint() command, which pass only object and create middle point for object. - will be updated documentation and tests --- diff --git a/src/SketchAPI/CMakeLists.txt b/src/SketchAPI/CMakeLists.txt index 2d07f9a20..e83046e9e 100644 --- a/src/SketchAPI/CMakeLists.txt +++ b/src/SketchAPI/CMakeLists.txt @@ -32,6 +32,7 @@ SET(PROJECT_HEADERS SketchAPI_Line.h SketchAPI_MacroArc.h SketchAPI_MacroCircle.h + SketchAPI_MacroMiddlePoint.h SketchAPI_MacroEllipse.h SketchAPI_MacroEllipticArc.h SketchAPI_Mirror.h @@ -57,6 +58,7 @@ SET(PROJECT_SOURCES SketchAPI_Line.cpp SketchAPI_MacroArc.cpp SketchAPI_MacroCircle.cpp + SketchAPI_MacroMiddlePoint.cpp SketchAPI_MacroEllipse.cpp SketchAPI_MacroEllipticArc.cpp SketchAPI_Mirror.cpp diff --git a/src/SketchAPI/SketchAPI.i b/src/SketchAPI/SketchAPI.i index 19238b33b..ab4de1120 100644 --- a/src/SketchAPI/SketchAPI.i +++ b/src/SketchAPI/SketchAPI.i @@ -81,6 +81,7 @@ %shared_ptr(SketchAPI_Sketch) %shared_ptr(SketchAPI_SketchEntity) %shared_ptr(SketchAPI_Point) +%shared_ptr(SketchAPI_MacroMiddlePoint) %shared_ptr(SketchAPI_Projection) %shared_ptr(SketchAPI_Rectangle) %shared_ptr(SketchAPI_Rotation) @@ -573,6 +574,7 @@ // all supported interfaces (the order is very important according dependencies: base class first) %include "SketchAPI_SketchEntity.h" %include "SketchAPI_Point.h" +%include "SketchAPI_MacroMiddlePoint.h" %include "SketchAPI_IntersectionPoint.h" %include "SketchAPI_Line.h" %include "SketchAPI_Circle.h" diff --git a/src/SketchAPI/SketchAPI_Constraint.cpp b/src/SketchAPI/SketchAPI_Constraint.cpp index 9149d2395..d69c35f88 100644 --- a/src/SketchAPI/SketchAPI_Constraint.cpp +++ b/src/SketchAPI/SketchAPI_Constraint.cpp @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include @@ -198,35 +201,61 @@ void SketchAPI_Constraint::dump(ModelHighAPI_Dumper& theDumper) const return; } - // postpone constraint until all its attributes be dumped - if (!areAllAttributesDumped(theDumper)) - return; - const std::string& aSketchName = theDumper.parentName(aBase); - theDumper << aSketchName << "." << aSetter << "("; - bool isFirstAttr = true; - for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { - AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + // Dump middle constraint by object + if (SketchPlugin_ConstraintMiddle::ID() == aBase->getKind() && + aBase->string(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE())->value() == SketchPlugin_ConstraintMiddle::MIDDLE_TYPE_BY_LINE()) + { + FeaturePtr aFeature; + AttributeRefAttrPtr aPointRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(1)); + AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(0)); + + if (!theDumper.isDumped(aRefAttr)) + { + theDumper.postpone(aBase); + return; + } + aFeature = ModelAPI_Feature::feature(aPointRefAttr->object()); + + theDumper.name(aFeature, false, true, true); // mark point as dumped + + theDumper << theDumper.name(aFeature) << " = " << aSketchName << "." << aSetter << "("; if (aRefAttr && aRefAttr->isInitialized()) { - theDumper << (isFirstAttr ? "" : ", ") << aRefAttr; - isFirstAttr = false; + theDumper << aRefAttr; } + theDumper << ")" << std::endl; } + else + { + // postpone constraint until all its attributes be dumped + if (!areAllAttributesDumped(theDumper)) + return; + + theDumper << aSketchName << "." << aSetter << "("; + bool isFirstAttr = true; + for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) { + AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i)); + if (aRefAttr && aRefAttr->isInitialized()) { + theDumper << (isFirstAttr ? "" : ", ") << aRefAttr; + isFirstAttr = false; + } + } - AttributeDoublePtr aValueAttr; - if (aBase->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() || + AttributeDoublePtr aValueAttr; + if (aBase->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() || aBase->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) - aValueAttr = aBase->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()); - else - aValueAttr = aBase->real(SketchPlugin_Constraint::VALUE()); - if (aValueAttr && aValueAttr->isInitialized()) - theDumper << ", " << aValueAttr; + aValueAttr = aBase->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()); + else + aValueAttr = aBase->real(SketchPlugin_Constraint::VALUE()); + if (aValueAttr && aValueAttr->isInitialized()) + theDumper << ", " << aValueAttr; - if (aBase->getKind() == SketchPlugin_ConstraintDistance::ID()) { - AttributeBooleanPtr isSigned = aBase->boolean(SketchPlugin_ConstraintDistance::SIGNED()); - theDumper << ", " << isSigned->value(); + if (aBase->getKind() == SketchPlugin_ConstraintDistance::ID()) { + AttributeBooleanPtr isSigned = aBase->boolean(SketchPlugin_ConstraintDistance::SIGNED()); + theDumper << ", " << isSigned->value(); + } + theDumper << ")" << std::endl; } - theDumper << ")" << std::endl; } diff --git a/src/SketchAPI/SketchAPI_Constraint.h b/src/SketchAPI/SketchAPI_Constraint.h index 220d1d59d..fe4ece791 100644 --- a/src/SketchAPI/SketchAPI_Constraint.h +++ b/src/SketchAPI/SketchAPI_Constraint.h @@ -29,6 +29,7 @@ #include class ModelHighAPI_Double; +class SketchAPI_SketchEntity; /**\class SketchAPI_Constraint * \ingroup CPPHighAPI diff --git a/src/SketchAPI/SketchAPI_MacroMiddlePoint.cpp b/src/SketchAPI/SketchAPI_MacroMiddlePoint.cpp new file mode 100644 index 000000000..3ec3a3610 --- /dev/null +++ b/src/SketchAPI/SketchAPI_MacroMiddlePoint.cpp @@ -0,0 +1,71 @@ +// Copyright (C) 2019-2022 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 "SketchAPI_MacroMiddlePoint.h" + +#include + +#include + +#include + +SketchAPI_MacroMiddlePoint::SketchAPI_MacroMiddlePoint( + const std::shared_ptr & theFeature) +: SketchAPI_Point(theFeature) +{ + ConstraintPtr aConstraint = std::dynamic_pointer_cast(theFeature); + if (aConstraint) + initialize(); +} + +SketchAPI_MacroMiddlePoint::SketchAPI_MacroMiddlePoint(const std::shared_ptr& theFeature, + const ModelHighAPI_RefAttr& theLine, const std::shared_ptr& thePoint) + : SketchAPI_Point(theFeature, thePoint) +{ + createConstraint(theLine); +} + +void SketchAPI_MacroMiddlePoint::createConstraint(const ModelHighAPI_RefAttr& theLine) +{ + // Find sketch + CompositeFeaturePtr aSketch; + const std::set& aRefs = feature()->data()->refsToMe(); + for (std::set::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) + if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID()) + { + aSketch = std::dynamic_pointer_cast((*anIt)->owner()); + break; + } + if (!aSketch) + return; + + // Create middle constraint for line and poiunt + std::shared_ptr aConstrFeature = + aSketch->addFeature(SketchPlugin_ConstraintMiddle::ID()); + aConstrFeature->string(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE())->setValue(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE_BY_LINE()); + aConstrFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(theLine.object()); + aConstrFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(coordinates()); + std::dynamic_pointer_cast(aConstrFeature->attribute(SketchPlugin_ConstraintMiddle::POINT_REF_ID()))->setValue(coordinates()->x(), coordinates()->y()); + + aConstrFeature->execute(); + + feature()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + feature()->reference(SketchPlugin_SketchEntity::PARENT_ID())->setValue(aConstrFeature); + feature()->execute(); +} diff --git a/src/SketchAPI/SketchAPI_MacroMiddlePoint.h b/src/SketchAPI/SketchAPI_MacroMiddlePoint.h new file mode 100644 index 000000000..2e747dff0 --- /dev/null +++ b/src/SketchAPI/SketchAPI_MacroMiddlePoint.h @@ -0,0 +1,58 @@ +// Copyright (C) 2019-2022 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 SRC_SKETCHAPI_SKETCHAPI_MACRO_MIDDLEPOINT_H_ +#define SRC_SKETCHAPI_SKETCHAPI_MACRO_MIDDLEPOINT_H_ + +#include "SketchAPI_SketchEntity.h" + +#include + +class ModelHighAPI_RefAttr; + + +/**\class SketchAPI_MacroMiddlePoint + * \ingroup CPPHighAPI + * \brief Interface for Middle Point feature + */ +class SketchAPI_MacroMiddlePoint : public SketchAPI_Point +{ +public: + /// Constructor without values + SKETCHAPI_EXPORT + explicit SketchAPI_MacroMiddlePoint(const std::shared_ptr & theFeature); + + /// Constructor with line and middle point coordinates + SKETCHAPI_EXPORT + SketchAPI_MacroMiddlePoint(const std::shared_ptr& theFeature, + const ModelHighAPI_RefAttr& theLine, + const std::shared_ptr& thePoint); + + static std::string ID() + { + static const std::string MY_SKETCH_CONSTRAINT_ID = "MacroConstraintMiddle"; + return MY_SKETCH_CONSTRAINT_ID; + } + virtual std::string getID() { return ID(); } + +protected: + void createConstraint(const ModelHighAPI_RefAttr& theLine); +}; + +#endif diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index 34503d972..b0836ae12 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -67,6 +67,7 @@ #include "SketchAPI_MacroCircle.h" #include "SketchAPI_MacroEllipse.h" #include "SketchAPI_MacroEllipticArc.h" +#include "SketchAPI_MacroMiddlePoint.h" #include "SketchAPI_Mirror.h" #include "SketchAPI_Offset.h" #include "SketchAPI_Point.h" @@ -74,6 +75,7 @@ #include "SketchAPI_Rectangle.h" #include "SketchAPI_Rotation.h" #include "SketchAPI_Translation.h" +#include "SketchAPI_Constraint.h" //-------------------------------------------------------------------------------------- #include #include @@ -85,6 +87,125 @@ #include #include //-------------------------------------------------------------------------------------- + + +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; +} + SketchAPI_Sketch::SketchAPI_Sketch( const std::shared_ptr & theFeature) : ModelHighAPI_Interface(theFeature) @@ -1246,12 +1367,29 @@ std::shared_ptr SketchAPI_Sketch::setMiddlePoint( { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_ConstraintMiddle::ID()); + auto aType = aFeature->data()->string(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE()); + fillAttribute(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE_BY_LINE_AND_POINT(), aType); + fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())); fillAttribute(theLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B())); + aFeature->execute(); return InterfacePtr(new ModelHighAPI_Interface(aFeature)); } +std::shared_ptr SketchAPI_Sketch::setMiddlePoint( + const ModelHighAPI_RefAttr& theLine) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Point::ID()); + + ObjectPtr anObj = theLine.object(); + auto aPoint = middlePoint(anObj, this); + + return std::shared_ptr + (new SketchAPI_MacroMiddlePoint(aFeature, theLine, aPoint)); +} + std::shared_ptr SketchAPI_Sketch::setParallel( const ModelHighAPI_RefAttr & theLine1, const ModelHighAPI_RefAttr & theLine2) @@ -1312,123 +1450,6 @@ 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) { diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index f9c8fdb79..993e6ef90 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -57,6 +57,7 @@ class SketchAPI_Projection; class SketchAPI_Rectangle; class SketchAPI_Rotation; class SketchAPI_Translation; +class SketchAPI_MacroMiddlePoint; //-------------------------------------------------------------------------------------- typedef std::pair, ModelHighAPI_RefAttr> PointOrReference; @@ -523,6 +524,11 @@ public: const ModelHighAPI_RefAttr & thePoint, const ModelHighAPI_RefAttr & theLine); + /// Set middle + SKETCHAPI_EXPORT + std::shared_ptr setMiddlePoint( + const ModelHighAPI_RefAttr& theLine); + /// Set parallel SKETCHAPI_EXPORT std::shared_ptr setParallel( diff --git a/src/SketchAPI/SketchAPI_swig.h b/src/SketchAPI/SketchAPI_swig.h index 9fb8e6211..111782427 100644 --- a/src/SketchAPI/SketchAPI_swig.h +++ b/src/SketchAPI/SketchAPI_swig.h @@ -41,6 +41,7 @@ #include "SketchAPI_Sketch.h" #include "SketchAPI_SketchEntity.h" #include "SketchAPI_Point.h" + #include "SketchAPI_MacroMiddlePoint.h" #include "SketchAPI_Projection.h" #include "SketchAPI_Rectangle.h" #include "SketchAPI_Rotation.h" diff --git a/src/SketchPlugin/SketchPlugin_ConstraintMiddle.cpp b/src/SketchPlugin/SketchPlugin_ConstraintMiddle.cpp index ad9ab3755..9d478833b 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintMiddle.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintMiddle.cpp @@ -21,28 +21,113 @@ #include "SketcherPrs_Factory.h" +#include + +#include +#include + +#include +#include +#include + SketchPlugin_ConstraintMiddle::SketchPlugin_ConstraintMiddle() { } +// Create new point for Middle constraint +void SketchPlugin_ConstraintMiddle::CreatePoint() +{ + // Wait all objects being created, then send update events + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + + auto aTrPnt = std::dynamic_pointer_cast(data()->attribute(POINT_REF_ID())); + + if (!myPoint) + { + // Get last subfeature (constraintMiddle) for set as parent + FeaturePtr aCurrentFeature = sketch()->subFeature(sketch()->numberOfSubs() - 1); + keepCurrentFeature(); + myPoint = sketch()->addFeature(SketchPlugin_Point::ID()); + myPoint->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + restoreCurrentFeature(); + + myPoint->reference(SketchPlugin_Point::PARENT_ID())->setValue(aCurrentFeature); + } + + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + myPoint->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(aTrPnt->pnt()); + + myPoint->execute(); + + // Init second attr for constraint + refattr(SketchPlugin_Constraint::ENTITY_B())->setObject(myPoint); + + + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, true); +} + void SketchPlugin_ConstraintMiddle::initAttributes() { + data()->addAttribute(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()); + + data()->addAttribute(POINT_REF_ID(), GeomDataAPI_Point2D::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), POINT_REF_ID()); } void SketchPlugin_ConstraintMiddle::execute() { + if (string(MIDDLE_TYPE())->value() == MIDDLE_TYPE_BY_LINE()) + { + std::dynamic_pointer_cast(data()->attribute(POINT_REF_ID()))->setValue(1., 1.); + AttributeRefAttrPtr aPointRes = std::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Constraint::ENTITY_B())); + + auto aRefAttr = data()->refattr(SketchPlugin_Constraint::ENTITY_A())->object(); + if (!aRefAttr.get()) + return; + + + if (!attribute(ENTITY_B())->isInitialized()) + CreatePoint(); // Create new point + } +} + +void SketchPlugin_ConstraintMiddle::attributeChanged(const std::string& theID) +{ + if (theID == MIDDLE_TYPE()) + { + SketchPlugin_Tools::resetAttribute(this, ENTITY_A()); + SketchPlugin_Tools::resetAttribute(this, ENTITY_B()); + } + else if (theID == POINT_REF_ID()) + { + if (!myPoint) + return; + + auto aTrPnt = std::dynamic_pointer_cast(data()->attribute(POINT_REF_ID())); + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + myPoint->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(aTrPnt->pnt()); + + myPoint->execute(); + } } AISObjectPtr SketchPlugin_ConstraintMiddle::getAISObject(AISObjectPtr thePrevious) { if (!sketch()) return thePrevious; - AISObjectPtr anAIS = SketcherPrs_Factory::middleConstraint(this, sketch(), thePrevious); + return anAIS; } - - diff --git a/src/SketchPlugin/SketchPlugin_ConstraintMiddle.h b/src/SketchPlugin/SketchPlugin_ConstraintMiddle.h index 6c0ac43ce..ddb3c2faa 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintMiddle.h +++ b/src/SketchPlugin/SketchPlugin_ConstraintMiddle.h @@ -24,6 +24,8 @@ #include #include "SketchPlugin_ConstraintBase.h" +class ModelAPI_Feature; + /** \class SketchPlugin_ConstraintMiddle * \ingroup Plugins * \brief Feature for creation of a new constraint which places a point in the middle of a line @@ -40,6 +42,35 @@ class SketchPlugin_ConstraintMiddle : public SketchPlugin_ConstraintBase static const std::string MY_CONSTRAINT_MIDDLE_ID("SketchConstraintMiddle"); return MY_CONSTRAINT_MIDDLE_ID; } + + /// Middle constraint kind + inline static const std::string& MIDDLE_TYPE() + { + static const std::string MY_TYPE_ID("middle_type"); + return MY_TYPE_ID; + } + + /// Middle constraint type by line and point + inline static const std::string& MIDDLE_TYPE_BY_LINE_AND_POINT() + { + static const std::string MY_TYPE_ID("middle_type_by_line_and_point"); + return MY_TYPE_ID; + } + + /// Middle constraint type by line + inline static const std::string& MIDDLE_TYPE_BY_LINE() + { + static const std::string MY_TYPE_ID("middle_type_by_line"); + return MY_TYPE_ID; + } + + /// Created points for middle type by line + inline static const std::string& POINT_REF_ID() + { + static const std::string MY_POINT_REF("point"); + return MY_POINT_REF; + } + /// \brief Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { @@ -47,6 +78,9 @@ class SketchPlugin_ConstraintMiddle : public SketchPlugin_ConstraintBase return MY_KIND; } + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + /// \brief Creates a new part document if needed SKETCHPLUGIN_EXPORT virtual void execute(); @@ -58,6 +92,11 @@ class SketchPlugin_ConstraintMiddle : public SketchPlugin_ConstraintBase /// \brief Use plugin manager for features creation SketchPlugin_ConstraintMiddle(); + +private: + void CreatePoint(); + + std::shared_ptr myPoint; }; #endif diff --git a/src/SketchPlugin/Test/TestConstraintMiddlePoint.py b/src/SketchPlugin/Test/TestConstraintMiddlePoint.py index 36aef57cf..9814bb731 100644 --- a/src/SketchPlugin/Test/TestConstraintMiddlePoint.py +++ b/src/SketchPlugin/Test/TestConstraintMiddlePoint.py @@ -37,6 +37,7 @@ """ from GeomDataAPI import * from ModelAPI import * +from SketchAPI import * import math from salome.shaper import model @@ -105,6 +106,8 @@ aSession.startOperation() aConstraint = aSketchFeature.addFeature("SketchConstraintMiddle") reflistA = aConstraint.refattr("ConstraintEntityA") reflistB = aConstraint.refattr("ConstraintEntityB") +anAlgoType = aConstraint.string("middle_type") +anAlgoType.setValue("middle_type_by_line_and_point") reflistA.setAttr(aEndPoint2) reflistB.setObject(aLine1.lastResult()) aConstraint.execute() @@ -122,6 +125,8 @@ aEndPoint2.setValue(80., 25.) aConstraint = aSketchFeature.addFeature("SketchConstraintMiddle") reflistA = aConstraint.refattr("ConstraintEntityA") reflistB = aConstraint.refattr("ConstraintEntityB") +anAlgoType = aConstraint.string("middle_type") +anAlgoType.setValue("middle_type_by_line_and_point") reflistA.setAttr(aEndPoint2) reflistB.setObject(aLine1.lastResult()) aConstraint.execute() @@ -172,6 +177,8 @@ aSession.startOperation() aConstraint = aSketchFeature.addFeature("SketchConstraintMiddle") reflistA = aConstraint.refattr("ConstraintEntityA") reflistB = aConstraint.refattr("ConstraintEntityB") +anAlgoType = aConstraint.string("middle_type") +anAlgoType.setValue("middle_type_by_line_and_point") reflistA.setObject(aLine2.lastResult()) reflistB.setObject(anOrigin.lastResult()) aSession.finishOperation() @@ -205,6 +212,8 @@ aSession.startOperation() aMiddle = aSketchFeature.addFeature("SketchConstraintMiddle") reflistA = aMiddle.refattr("ConstraintEntityA") reflistB = aMiddle.refattr("ConstraintEntityB") +anAlgoType = aMiddle.string("middle_type") +anAlgoType.setValue("middle_type_by_line_and_point") reflistA.setAttr(aEndPoint3) reflistB.setObject(aLine1.lastResult()) aSession.finishOperation() @@ -225,6 +234,37 @@ aEndPoint1.setValue(aEndPoint1.x() + deltaX, aEndPoint1.y() + deltaY) aSession.finishOperation() checkMiddlePoint(aEndPoint3, aLine1) assert (model.dof(aSketchFeature) == 8) +#========================================================================= +# CreateLine +#========================================================================= +aSession.startOperation() +aLine4 = aSketchFeature.addFeature("SketchLine") +aStartPoint4 = geomDataAPI_Point2D(aLine4.attribute("StartPoint")) +aEndPoint4 = geomDataAPI_Point2D(aLine4.attribute("EndPoint")) +aStartPoint4.setValue(2., 8.) +aEndPoint4.setValue(20., 14.) +aRigidConstraint1 = aSketchFeature.addFeature("SketchConstraintRigid") +aRigidConstraint1.refattr("ConstraintEntityA").setAttr(aStartPoint4) +aRigidConstraint2 = aSketchFeature.addFeature("SketchConstraintRigid") +aRigidConstraint2.refattr("ConstraintEntityA").setAttr(aEndPoint4) +aSession.finishOperation() +#========================================================================= +# Set middle point on line +#========================================================================= +aSession.startOperation() +aMiddle = aSketchFeature.addFeature("SketchConstraintMiddle") +reflistA = aMiddle.refattr("ConstraintEntityA") +anAlgoType = aMiddle.string("middle_type") +anAlgoType.setValue("middle_type_by_line") +reflistA.setObject(aLine4.lastResult()) +aSession.finishOperation() +arefB = aMiddle.refattr("ConstraintEntityB") +aPointRes = ModelAPI_Feature.feature(arefB.object()) +aMidPoint = geomDataAPI_Point2D(SketchAPI_Point(aPointRes).coordinates()) + +# check the point, and no error message +checkMiddlePoint(aMidPoint, aLine4) + #========================================================================= # End of test diff --git a/src/SketchPlugin/Test/TestConstraintMiddlePointOnArc.py b/src/SketchPlugin/Test/TestConstraintMiddlePointOnArc.py index 3312d07ea..208cbf7d8 100644 --- a/src/SketchPlugin/Test/TestConstraintMiddlePointOnArc.py +++ b/src/SketchPlugin/Test/TestConstraintMiddlePointOnArc.py @@ -44,7 +44,7 @@ class TestMiddlePointOnArc(unittest.TestCase): def tearDown(self): if self.myTestPassed: model.assertArcValidity(self.myArc) - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.checkDOF() model.end() assert(model.checkPythonDump()) @@ -55,7 +55,7 @@ class TestMiddlePointOnArc(unittest.TestCase): def checkMiddlePoint(self, thePoint, theArc): self.myTestPassed = False # check point on arc - dist = thePoint.pnt().distance(theArc.center().pnt()) + dist = thePoint.distance(theArc.center().pnt()) NB_DIGITS = 7 - math.floor(math.log10(theArc.radius().value())) self.assertAlmostEqual(dist, theArc.radius().value(), NB_DIGITS) # check middle point @@ -86,14 +86,14 @@ class TestMiddlePointOnArc(unittest.TestCase): while fullAngle < ANGLE_THRESHOLD: self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), -ANGLE_STEP) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) fullAngle += ANGLE_STEP # move start point of the arc conterclockwise fullAngle = 0.0 while fullAngle < ANGLE_THRESHOLD: self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), ANGLE_STEP) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) fullAngle += ANGLE_STEP # move end point of the arc clockwise @@ -101,14 +101,14 @@ class TestMiddlePointOnArc(unittest.TestCase): while fullAngle < ANGLE_THRESHOLD: self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), -ANGLE_STEP) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) fullAngle += ANGLE_STEP # move end point of the arc conterclockwise fullAngle = 0.0 while fullAngle < ANGLE_THRESHOLD: self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), ANGLE_STEP) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) fullAngle += ANGLE_STEP # move center of the arc @@ -118,14 +118,14 @@ class TestMiddlePointOnArc(unittest.TestCase): DELTA = [-DELTA[0], -DELTA[1]] self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1]) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) DELTA = [-1.0, 1.0] for i in range(0, 40): if i == 10 or i == 30: DELTA = [-DELTA[0], -DELTA[1]] self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1]) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) def moveLine(self): DELTA = [1.0, 0.0] @@ -134,14 +134,14 @@ class TestMiddlePointOnArc(unittest.TestCase): DELTA = [-DELTA[0], -DELTA[1]] self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1]) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) DELTA = [0.0, 1.0] for i in range(0, 40): if i == 10 or i == 30: DELTA = [-DELTA[0], -DELTA[1]] self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1]) model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) def test_middle_point_PA(self): @@ -187,7 +187,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.myDOF -= 2 model.do() # this check will fail due to the limitation of PlanGCS - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) def test_middle_point_move_arc(self): """ Test 6. Set middle point constraint and move arc @@ -195,7 +195,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1]) self.myDOF -= 2 model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.moveArc() def test_middle_point_coincidence_move_arc(self): @@ -206,7 +206,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1]) self.myDOF -= 2 model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.moveArc() def test_middle_point_move_line(self): @@ -215,7 +215,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1]) self.myDOF -= 2 model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.moveLine() def test_middle_point_coincidence_move_line(self): @@ -226,7 +226,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1]) self.myDOF -= 2 model.do() - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.moveLine() def test_remove_middle_point(self): @@ -236,7 +236,7 @@ class TestMiddlePointOnArc(unittest.TestCase): self.myDOF -= 2 model.do() model.assertArcValidity(self.myArc) - self.checkMiddlePoint(self.myLine.startPoint(), self.myArc) + self.checkMiddlePoint(self.myLine.startPoint().pnt(), self.myArc) self.checkDOF() # remove middle point self.myDocument.removeFeature(mp.feature()) @@ -246,6 +246,36 @@ class TestMiddlePointOnArc(unittest.TestCase): # set flag False to avoid checking middle point constraint in tearDown() method self.myTestPassed = False + def test_middle_point_by_object(self): + """ Test 11. Set middle point constraint on Arc + """ + self.myArc = self.mySketch.addArc(6, 4, 15, 1, 14, 9, False) + self.mySketch.setFixed(self.myArc.center()) + self.mySketch.setRadius(self.myArc.results()[1], 10) + + SketchLine_2 = self.mySketch.addLine(6, 4, 16, 4) + SketchLine_2.setAuxiliary(True) + self.mySketch.setCoincident(self.myArc.center(), SketchLine_2.startPoint()) + self.mySketch.setCoincident(self.myArc.startPoint(), SketchLine_2.endPoint()) + self.mySketch.setHorizontal(SketchLine_2.result()) + + SketchLine_3 = self.mySketch.addLine(6, 4, 14.66025403784439, 9) + SketchLine_3.setAuxiliary(True) + self.mySketch.setCoincident(self.myArc.center(), SketchLine_3.startPoint()) + self.mySketch.setCoincident(self.myArc.endPoint(), SketchLine_3.endPoint()) + + ### Create SketchConstraintAngle + self.mySketch.setAngle(SketchLine_2.result(), SketchLine_3.result(), 30, type = "Direct") + + # Ajout d'un point auxiliaire au milieu + SketchPoint_02 = self.mySketch.setMiddlePoint(self.myArc.results()[1]) + model.do() + + aPoint = SketchPoint_02.coordinates().pnt() + self.checkMiddlePoint(aPoint, self.myArc) + + # set flag False to avoid checking middle point constraint in tearDown() method + self.myTestPassed = False if __name__ == "__main__": test_program = unittest.main(exit=False) diff --git a/src/SketchPlugin/Test/TestConstraintMiddlePointOnEllipticArc.py b/src/SketchPlugin/Test/TestConstraintMiddlePointOnEllipticArc.py index 794a7d37b..714f9e949 100644 --- a/src/SketchPlugin/Test/TestConstraintMiddlePointOnEllipticArc.py +++ b/src/SketchPlugin/Test/TestConstraintMiddlePointOnEllipticArc.py @@ -281,6 +281,59 @@ class TestMiddlePointOnEllipticArc(unittest.TestCase): # set flag False to avoid checking middle point constraint in tearDown() method self.myTestPassed = False + def test_middle_point_by_object(self): + """ Test 12. Set middle point constraint on elliptic arc + """ + + self.myArc = self.mySketch.addEllipticArc(26.13481199028052, 14.44743211950145, 27.10553481386106, 8.942189418241149, 30, 8.856406460551019, 22, 11, False) + [SketchPoint_1, SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchLine_4, SketchLine_5] = self.myArc.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux") + self.mySketch.setLength(SketchLine_5.result(), 10) + self.mySketch.setLength(SketchLine_4.result(), 15) + + ### Create SketchProjection + SketchProjection_1 = self.mySketch.addProjection(model.selection("EDGE", "PartSet/OX"), False) + SketchLine_6 = SketchProjection_1.createdFeature() + + ### Create SketchConstraintAngle + self.mySketch.setAngle(SketchLine_6.result(), SketchLine_5.result(), 10, type = "Direct") + + ### Create SketchProjection + SketchProjection_2 = self.mySketch.addProjection(model.selection("EDGE", "PartSet/OX"), False) + SketchLine_7 = SketchProjection_2.createdFeature() + + ### Create SketchLine + SketchLine_8 = self.mySketch.addLine(22, 11, 30, 8.856406460551019) + SketchLine_8.setAuxiliary(True) + self.mySketch.setCoincident(self.myArc.endPoint(), SketchLine_8.startPoint()) + self.mySketch.setCoincident(self.myArc.startPoint(), SketchLine_8.endPoint()) + + ### Create SketchConstraintAngle + self.mySketch.setAngle(SketchLine_7.result(), SketchLine_8.result(), 15, type = "Direct") + + ### Create SketchProjection + SketchProjection_3 = self.mySketch.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) + SketchPoint_8 = SketchProjection_3.createdFeature() + self.mySketch.setHorizontalDistance(SketchAPI_Point(SketchPoint_8).coordinates(), SketchLine_8.startPoint(), 22) + + ### Create SketchProjection + SketchProjection_4 = self.mySketch.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) + SketchPoint_9 = SketchProjection_4.createdFeature() + self.mySketch.setVerticalDistance(SketchAPI_Point(SketchPoint_9).coordinates(), SketchLine_8.startPoint(), 11) + + ### Create SketchProjection + SketchProjection_5 = self.mySketch.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) + SketchPoint_10 = SketchProjection_5.createdFeature() + self.mySketch.setHorizontalDistance(SketchAPI_Point(SketchPoint_10).coordinates(), SketchLine_8.endPoint(), 30) + + # Create auxiliaire middle point + SketchPoint_03 = self.mySketch.setMiddlePoint(self.myArc.result()) + model.do() + + aPoint = SketchPoint_03.result().resultSubShapePair()[0].shape().vertex().point() + self.checkMiddlePoint(self.mySketch.to2D(aPoint), self.myArc) + + # set flag False to avoid checking middle point constraint in tearDown() method + self.myTestPassed = False if __name__ == "__main__": test_program = unittest.main(exit=False) diff --git a/src/SketchPlugin/doc/examples/middle.py b/src/SketchPlugin/doc/examples/middle.py index c6aa514e2..b37468fc1 100644 --- a/src/SketchPlugin/doc/examples/middle.py +++ b/src/SketchPlugin/doc/examples/middle.py @@ -8,5 +8,8 @@ Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) SketchCircle_1 = Sketch_1.addCircle(16, 54, 10) SketchLine_1 = Sketch_1.addLine(10, 10, 80, 80) SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchCircle_1.center(), SketchLine_1.result()) + +SketchLine_2 = Sketch_1.addLine(20, 10, 90, 80) +SketchPoint_01 = Sketch_1.setMiddlePoint(SketchLine_2.result()) model.do() model.end() diff --git a/src/SketchPlugin/doc/images/MiddlePoint_obj.png b/src/SketchPlugin/doc/images/MiddlePoint_obj.png new file mode 100644 index 000000000..af1252161 Binary files /dev/null and b/src/SketchPlugin/doc/images/MiddlePoint_obj.png differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_obj_panel.png b/src/SketchPlugin/doc/images/Middlepoint_obj_panel.png new file mode 100644 index 000000000..1254bccd1 Binary files /dev/null and b/src/SketchPlugin/doc/images/Middlepoint_obj_panel.png differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_obj_point_panel.png b/src/SketchPlugin/doc/images/Middlepoint_obj_point_panel.png new file mode 100644 index 000000000..762dd9981 Binary files /dev/null and b/src/SketchPlugin/doc/images/Middlepoint_obj_point_panel.png differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_obj_point_res.png b/src/SketchPlugin/doc/images/Middlepoint_obj_point_res.png new file mode 100644 index 000000000..8eed3309d Binary files /dev/null and b/src/SketchPlugin/doc/images/Middlepoint_obj_point_res.png differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_obj_res.png b/src/SketchPlugin/doc/images/Middlepoint_obj_res.png new file mode 100644 index 000000000..d46c16d0a Binary files /dev/null and b/src/SketchPlugin/doc/images/Middlepoint_obj_res.png differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_panel.png b/src/SketchPlugin/doc/images/Middlepoint_panel.png deleted file mode 100644 index ea306951c..000000000 Binary files a/src/SketchPlugin/doc/images/Middlepoint_panel.png and /dev/null differ diff --git a/src/SketchPlugin/doc/images/Middlepoint_res.png b/src/SketchPlugin/doc/images/Middlepoint_res.png deleted file mode 100644 index 8eed3309d..000000000 Binary files a/src/SketchPlugin/doc/images/Middlepoint_res.png and /dev/null differ diff --git a/src/SketchPlugin/doc/middleFeature.rst b/src/SketchPlugin/doc/middleFeature.rst index f39a34879..a6d0142f8 100644 --- a/src/SketchPlugin/doc/middleFeature.rst +++ b/src/SketchPlugin/doc/middleFeature.rst @@ -10,9 +10,27 @@ To create a Middle point in the active Sketch: #. select in the Main Menu *Sketch - > Middle point* item or #. click |middlepoint.icon| **Middle point** button in Sketch toolbar: +There are 2 algorithms for creation of a middle constraint: + +.. figure:: images/MiddlePoint.png + :align: left + :height: 24px + +**By object and point** create a middle constraint by object (segment or arc) and point + +.. figure:: images/MiddlePoint_obj.png + :align: left + :height: 24px + +**By object** create a middle point on the object (segment or arc) + +------------------------------------------------------------------------------------------- + +By object and point +"""""""""""""""""""""""""" Property panel: -.. figure:: images/Middlepoint_panel.png +.. figure:: images/Middlepoint_obj_point_panel.png :align: center Input fields: @@ -38,7 +56,38 @@ Result Created Middle point constraint appears in the view. -.. figure:: images/Middlepoint_res.png +.. figure:: images/Middlepoint_obj_point_res.png + :align: center + + Created middle point constraint + +By object +"""""""""""""""""""""""""" +Property panel: + +.. figure:: images/Middlepoint_obj_panel.png + :align: center + +Input fields: + +- **Object** is a line selected in the view. + +| After the object are selected, will be created auxiliary point on the middle of the line. +| The middle points are marked with a special sign. + +**TUI Command**: + +.. py:function:: SketchPoint_1 = Sketch_1.setMiddlePoint(Line) + + :param object: A line. + :return: Created middle point. + +Result +"""""" + +Created Middle point constraint appears in the view. + +.. figure:: images/Middlepoint_obj_res.png :align: center Created middle point constraint diff --git a/src/SketchPlugin/icons/middlepoint_obj.png b/src/SketchPlugin/icons/middlepoint_obj.png new file mode 100644 index 000000000..af1252161 Binary files /dev/null and b/src/SketchPlugin/icons/middlepoint_obj.png differ diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 6f665a49e..f69c00040 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -1432,16 +1432,38 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index ab382114e..1f0fd0e7c 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -527,7 +527,6 @@ bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName, theAttrName == SketchPlugin_BSplinePeriodic::MULTS_ID() || theAttrName == SketchPlugin_BSplinePeriodic::DEGREE_ID(); } - // suppose that all remaining features are points return theAttrName == SketchPlugin_Point::COORD_ID(); }