#include <ModelAPI_Events.h>
#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Tools.h>
+#include <GeomAPI_Edge.h>
class RaiiSetBoolFlag {
public:
bool *myBoolPtr;
};
+const double TOL = 1.e-5;
SketchPlugin_ConstraintMiddle::SketchPlugin_ConstraintMiddle()
{
myBlockAttribInit = false;
}
-// 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<GeomDataAPI_Point2D>(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<GeomDataAPI_Point2D>(
- 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()
{
// To maintain compatibility with older study versions, keep the order of all previously existing attributes:
aMethodAttr->setValue(MIDDLE_TYPE_BY_LINE_AND_POINT());
}
+ myX = 1., myY = 1.;
data()->addAttribute(POINT_REF_ID(), GeomDataAPI_Point2D::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), POINT_REF_ID());
{
if (string(MIDDLE_TYPE())->value() == MIDDLE_TYPE_BY_LINE())
{
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_REF_ID()))->setValue(1., 1.);
- AttributeRefAttrPtr aPointRes = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- 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
+ {
+ computePointCoordinates();
+ createPoint(); // Create new point
+ }
}
}
+void SketchPlugin_ConstraintMiddle::computePointCoordinates()
+{
+ if (string(MIDDLE_TYPE())->value() != MIDDLE_TYPE_BY_LINE()
+ || attribute(ENTITY_B())->isInitialized())
+ return;
+
+ auto aRefAttr = data()->refattr(SketchPlugin_Constraint::ENTITY_A())->object();
+ if (!aRefAttr.get())
+ return;
+
+ // calculate position of middle point(poor placement of a point can greatly
+ // deform the position of the original shape in the sketch)
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr);
+ if(aFeature->getKind() == SketchPlugin_Line::ID() || aFeature->getKind() == SketchPlugin_Arc::ID())
+ {
+ GeomShapePtr aShape = aFeature->lastResult()->shape();
+ if (aShape && aShape->shapeType() == GeomAPI_Shape::EDGE)
+ {
+ GeomAPI_Edge anEdge(aShape->edge());
+ GeomPointPtr aMiddle = anEdge.middlePoint();
+ GeomPnt2dPtr aMiddle2d = sketch()->to2D(aMiddle);
+ myX = aMiddle2d->x();
+ myY = aMiddle2d->y();
+
+ // Workaround: The exact midpoint causes an exception in the solver when attempting to use this point in subsequent features.
+ auto deltaX = sketch()->to2D(anEdge.firstPoint())->x() - sketch()->to2D(anEdge.lastPoint())->x();
+ (deltaX < TOL) ? myX += TOL : myY += TOL;
+ }
+ }
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_REF_ID()))->setValue(myX, myY);
+}
+
+// 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<GeomDataAPI_Point2D>(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<GeomDataAPI_Point2D>(
+ 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::attributeChanged(const std::string& theID)
{
if (theID == MIDDLE_TYPE())