X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchPlugin%2FSketchPlugin_Arc.cpp;h=7d285d079dd1cfa00f5c3494330be7ef428054cf;hb=df51e63f5d87b0c8fa46f5cda0c7c92aad5da888;hp=ed8d3be222a4874f54694d3ac2d7884ffe04347a;hpb=3eb36845861d4ae0fd4b775a0cc5e938dd75f5c3;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index ed8d3be22..7d285d079 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + // File: SketchPlugin_Arc.cpp // Created: 26 Apr 2014 // Author: Artem ZHIDKOV @@ -5,123 +7,326 @@ #include "SketchPlugin_Arc.h" #include "SketchPlugin_Sketch.h" #include +#include +#include +#include +#include +#include #include +#include #include - #include #include - #include #include #include +// for sqrt on Linux +#include + +const double tolerance = 1e-7; +const double paramTolerance = 1.e-4; +const double PI =3.141592653589793238463; -#include SketchPlugin_Arc::SketchPlugin_Arc() - : SketchPlugin_Feature() + : SketchPlugin_SketchEntity() { + myStartUpdate = false; + myEndUpdate = false; + // default values + myXEndBefore = 0; + myYEndBefore = 0; + + myParamBefore = 0; } void SketchPlugin_Arc::initAttributes() { - data()->addAttribute(ARC_ATTR_CENTER, GeomDataAPI_Point2D::type()); - data()->addAttribute(ARC_ATTR_START, GeomDataAPI_Point2D::type()); - data()->addAttribute(ARC_ATTR_END, GeomDataAPI_Point2D::type()); -} + SketchPlugin_SketchEntity::initAttributes(); -void SketchPlugin_Arc::execute() -{ + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId()); + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId())); + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); + + data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId()); + AttributeBooleanPtr isInversed = + std::dynamic_pointer_cast(attribute(INVERSED_ID())); + if (!isInversed->isInitialized()) + isInversed->setValue(false); + + // get the initial values + if (anEndAttr->isInitialized()) { + myXEndBefore = anEndAttr->x(); + myYEndBefore = anEndAttr->y(); + } } -const boost::shared_ptr& SketchPlugin_Arc::preview() +void SketchPlugin_Arc::execute() { SketchPlugin_Sketch* aSketch = sketch(); - if (aSketch) { - std::list > aShapes; - + // result for the arc is set only when all obligatory attributes are initialized, + // otherwise AIS object is used to visualize the arc's preview + if (aSketch && isFeatureValid()) { // compute a circle point in 3D view - boost::shared_ptr aCenterAttr = - boost::dynamic_pointer_cast(data()->attribute(ARC_ATTR_CENTER)); - boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); + std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); + // compute the arc start point + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(START_ID())); + + std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); // make a visible point - boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); - aShapes.push_back(aCenterPointShape); + std::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); + std::shared_ptr aConstr1 = document()->createConstruction( + data(), 0); + aConstr1->setShape(aCenterPointShape); + aConstr1->setIsInHistory(false); + setResult(aConstr1, 0); // make a visible circle - boost::shared_ptr aNDir = - boost::dynamic_pointer_cast(aSketch->data()->attribute(SKETCH_ATTR_NORM)); - bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); - if (aHasPlane) { - boost::shared_ptr aNormal = aNDir->dir(); - // compute the arc start point - boost::shared_ptr aStartAttr = - boost::dynamic_pointer_cast(data()->attribute(ARC_ATTR_START)); - boost::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); - - // compute and change the arc end point - boost::shared_ptr anEndAttr = - boost::dynamic_pointer_cast(data()->attribute(ARC_ATTR_END)); - if (anEndAttr->isInitialized()) - { - boost::shared_ptr aCircleForArc( - new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); - boost::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); - if (aProjection && anEndAttr->pnt()->distance(aProjection) > Precision::Confusion()) - anEndAttr->setValue(aProjection); + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); + + // compute and change the arc end point + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(END_ID())); + /* must be automatically done in attributeChanged + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) + anEndAttr->setValue(aProjection); + */ + std::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); + AttributeBooleanPtr isInversed = + std::dynamic_pointer_cast(attribute(INVERSED_ID())); + + std::shared_ptr anXDir(new GeomAPI_Dir(aStartPoint->xyz()->decreased(aCenter->xyz()))); + std::shared_ptr anAx2(new GeomAPI_Ax2(aCenter, aNormal, anXDir)); + std::shared_ptr aCirc(new GeomAPI_Circ(anAx2, aCenter->distance(aStartPoint))); + double aParameterNew = 0.0; + if(aCirc->parameter(aEndPoint, paramTolerance, aParameterNew)) { + if(0 <= myParamBefore && myParamBefore <= PI / 2.0 + && PI * 1.5 <= aParameterNew && aParameterNew <= PI * 2.0) { + isInversed->setValue(true); + } else if(PI * 1.5 <= myParamBefore && myParamBefore <= PI * 2.0 + && 0 <= aParameterNew && aParameterNew <= PI / 2.0) { + isInversed->setValue(false); } - boost::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); + } + myParamBefore = aParameterNew; + + std::shared_ptr aCircleShape; + if(!isInversed->value()) { + aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStartPoint, aEndPoint, aNormal); + } else { + aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aEndPoint, aStartPoint, aNormal); + } + + if (aCircleShape) { + std::shared_ptr aConstr2 = document()->createConstruction( + data(), 1); + aConstr2->setShape(aCircleShape); + aConstr2->setIsInHistory(false); + setResult(aConstr2, 1); + } + } +} + +AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious) +{ + SketchPlugin_Sketch* aSketch = sketch(); + if (aSketch) { + // if the feature is valid, the execute() method should be performed, AIS object is empty + if (!isFeatureValid()) { + // compute a circle point in 3D view + std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); + if (aCenterAttr->isInitialized()) { + std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); - boost::shared_ptr aCircleShape = - GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStartPoint, aEndPoint, aNormal); - if (aCircleShape) - aShapes.push_back(aCircleShape); + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); + if (aStartAttr->isInitialized()) { + // make a visible circle + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); + if (aHasPlane) { + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); + std::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( + aCenter, aStartPoint, aStartPoint, aNormal); + if (aCircleShape) { + std::list > aShapes; + // make a visible point + std::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); + aShapes.push_back(aCenterPointShape); + + aShapes.push_back(aCircleShape); + if (!aShapes.empty()) + { + std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + AISObjectPtr anAIS = thePrevious; + if (!anAIS) + anAIS = AISObjectPtr(new GeomAPI_AISObject); + anAIS->createShape(aCompound); + anAIS->setWidth(3); + return anAIS; + } + } + } + } + } } - boost::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); - setPreview(aCompound); } - return getPreview(); + return AISObjectPtr(); } void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY) { - boost::shared_ptr aData = data(); + std::shared_ptr aData = data(); if (!aData->isValid()) return; - boost::shared_ptr aPoint1 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_CENTER)); - aPoint1->setValue(aPoint1->x() + theDeltaX, aPoint1->y() + theDeltaY); + myStartUpdate = true; + myEndUpdate = true; + std::shared_ptr aPoint2 = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Arc::START_ID())); + aPoint2->move(theDeltaX, theDeltaY); + + std::shared_ptr aPoint3 = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Arc::END_ID())); + aPoint3->move(theDeltaX, theDeltaY); + myStartUpdate = false; + myEndUpdate = false; + + std::shared_ptr aPoint1 = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Arc::CENTER_ID())); + aPoint1->move(theDeltaX, theDeltaY); +} + +bool SketchPlugin_Arc::isFixed() { + return data()->selection(EXTERNAL_ID())->context().get() != NULL; +} + +bool SketchPlugin_Arc::isFeatureValid() +{ + std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID())); + + return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized(); +} + +void SketchPlugin_Arc::attributeChanged(const std::string& theID) +{ + std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); + std::shared_ptr aStartAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(START_ID())); + std::shared_ptr anEndAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(END_ID())); + // the second condition for unability to move external segments anywhere + if (theID == EXTERNAL_ID() || isFixed()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + // update arguments due to the selection value + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr aCirc = anEdge->circle(); + if (aCirc.get()) { + aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint())); + anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint())); + aCenterAttr->setValue(sketch()->to2D(aCirc->center())); + } + } + return; + } + if (!aCenterAttr->isInitialized()) + return; + if (!aStartAttr->isInitialized()) + return; + if (!anEndAttr->isInitialized()) + return; + + // update the points in accordance to the changed point changes + if (theID == END_ID() && !myEndUpdate) { + myEndUpdate = true; + // compute and change the arc end point + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) { + if (!isStable()) { // issue #855: trying to update only not-updated coordinate if it is possible + if (fabs(myXEndBefore - anEndAttr->x()) < 1.e-10) { // keep Y unchanged + double aVy = aCenterAttr->y() - anEndAttr->y(); + double aVy2 = aVy * aVy; + double aR2 = aCircleForArc->radius() * aCircleForArc->radius(); + if (aVy2 <= aR2) { + double aDX = sqrt(aR2 - aVy * aVy); + if (anEndAttr->x() > aCenterAttr->x()) + aProjection->setX(aCenterAttr->x() + aDX); + else + aProjection->setX(aCenterAttr->x() - aDX); + aProjection->setY(anEndAttr->y()); + } + } else if (fabs(myYEndBefore - anEndAttr->y()) < 1.e-10) { // keep X unchanged + double aVx = aCenterAttr->x() - anEndAttr->x(); + double aVx2 = aVx * aVx; + double aR2 = aCircleForArc->radius() * aCircleForArc->radius(); + if (aVx2 <= aR2) { + double aDY = sqrt(aR2 - aVx * aVx); + if (anEndAttr->y() > aCenterAttr->y()) + aProjection->setY(aCenterAttr->y() + aDY); + else + aProjection->setY(aCenterAttr->y() - aDY); + aProjection->setX(anEndAttr->x()); + } + } + } - boost::shared_ptr aPoint2 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_START)); - aPoint2->setValue(aPoint2->x() + theDeltaX, aPoint2->y() + theDeltaY); + anEndAttr->setValue(aProjection); + } + myXEndBefore = anEndAttr->x(); + myYEndBefore = anEndAttr->y(); + myEndUpdate = false; + } else if (theID == START_ID() && !myStartUpdate) { + myStartUpdate = true; + // compute and change the arc start point + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(aStartAttr->pnt()); + if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance) + aStartAttr->setValue(aProjection); + myStartUpdate = false; + } else if (theID == CENTER_ID() && !myEndUpdate) { + myEndUpdate = true; + // compute and change the arc end point + std::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) + anEndAttr->setValue(aProjection); + myEndUpdate = false; + } +} - boost::shared_ptr aPoint3 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_END)); - aPoint3->setValue(aPoint3->x() + theDeltaX, aPoint3->y() + theDeltaY); +void SketchPlugin_Arc::setReversed(bool isReversed) +{ + std::dynamic_pointer_cast(attribute(INVERSED_ID()))->setValue(isReversed); + myParamBefore = 0.0; } -double SketchPlugin_Arc::distanceToPoint(const boost::shared_ptr& thePoint) +bool SketchPlugin_Arc::isReversed() { - double aDelta = 0; - boost::shared_ptr aData = data(); - - boost::shared_ptr aPoint1 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_CENTER)); - aDelta = aPoint1->pnt()->distance(thePoint); - - boost::shared_ptr aPoint2 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_START)); - double aDistance = aPoint2->pnt()->distance(thePoint); - if (aDelta < aDistance) - aDelta = aDistance; - - boost::shared_ptr aPoint3 = - boost::dynamic_pointer_cast(aData->attribute(ARC_ATTR_END)); - aDistance = aPoint3->pnt()->distance(thePoint); - if (aDelta < aDistance) - aDelta = aDistance; - - return aDelta; + return std::dynamic_pointer_cast(attribute(INVERSED_ID()))->value(); }