* Introduce ellipse in SketchPlugin.
* Make ellipse processable by the solver.
mv -f covElse_res covElse
fi
done
-# remove SketchPlugin's Ellipse feature (unsupported yet)
-lcov -r covElse SketchPlugin*Ellipse* --output-file covElse_res -q
-mv -f covElse_res covElse
rm -rf lcov_htmlElse
genhtml covElse --output-directory lcov_htmlElse -q
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_Ellipse.cpp
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Sketch.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt2d.h>
+
#include <GeomDataAPI_Point2D.h>
+
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
void SketchPlugin_Ellipse::initDerivedClassAttributes()
{
data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
- data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
return;
}
- // Compute a ellipse in 3D view.
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
- AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
- AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
- if (!aCenterAttr->isInitialized() ||
- !aFocusAttr->isInitialized() ||
- !aMajorRadiusAttr->isInitialized() ||
- !aMinorRadiusAttr->isInitialized()) {
- return;
- }
-
- double aMajorRadius = aMajorRadiusAttr->value();
- double aMinorRadius = aMinorRadiusAttr->value();
- if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
- return;
- }
-
- // Make a visible point.
- SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
-
- std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+ // Calculate all characteristics of the ellipse.
+ fillCharacteristicPoints();
+
+ // Make visible points related to ellipse characteristics.
+ int aResultIndex = 0;
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, FIRST_FOCUS_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, SECOND_FOCUS_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MAJOR_AXIS_START_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MAJOR_AXIS_END_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MINOR_AXIS_START_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MINOR_AXIS_END_ID(), aResultIndex++);
+
+ // Make auxiliary axes
+ SketchPlugin_Sketch::createLine2DResult(this, aSketch,
+ MAJOR_AXIS_START_ID(), MAJOR_AXIS_END_ID(), aResultIndex++);
+ SketchPlugin_Sketch::createLine2DResult(this, aSketch,
+ MINOR_AXIS_START_ID(), MINOR_AXIS_END_ID(), aResultIndex++);
+
+ // Mark already created results auxiliary
+ myAuxiliaryResults.clear();
+ const std::list<ResultPtr>& aResults = results();
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ for (int anIndex = 0; anIt != aResults.end() && anIndex < aResultIndex; ++anIt, ++anIndex)
+ myAuxiliaryResults.insert(*anIt);
// Make a visible ellipse.
- std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
- std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
- std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
- std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
- aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
-
- std::shared_ptr<GeomAPI_Shape> anEllipseShape =
- GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
-
- std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
- aResult->setShape(anEllipseShape);
- aResult->setIsInHistory(false);
- setResult(aResult, 1);
+ createEllipse(aSketch, aResultIndex);
}
bool SketchPlugin_Ellipse::isFixed() {
return data()->selection(EXTERNAL_ID())->context().get() != NULL;
}
+bool SketchPlugin_Ellipse::isAuxiliary(ResultPtr theResult)
+{
+ return myAuxiliaryResults.find(theResult) != myAuxiliaryResults.end();
+}
+
void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
// the second condition for unability to move external segments anywhere
if (theID == EXTERNAL_ID() || isFixed()) {
aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
}
}
}
+
+bool SketchPlugin_Ellipse::fillCharacteristicPoints()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+ if (!aCenterAttr->isInitialized() ||
+ !aFocusAttr->isInitialized() ||
+ !aMajorRadiusAttr->isInitialized() ||
+ !aMinorRadiusAttr->isInitialized()) {
+ return false;
+ }
+
+ double aMajorRadius = aMajorRadiusAttr->value();
+ double aMinorRadius = aMinorRadiusAttr->value();
+ if (aMajorRadius < tolerance || aMinorRadius < tolerance) {
+ return false;
+ }
+
+ data()->blockSendAttributeUpdated(true);
+ GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+ GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+ GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+ aFocus2d->y() - aCenter2d->y()));
+ GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+ ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+ data()->blockSendAttributeUpdated(false);
+
+ return true;
+}
+
+void SketchPlugin_Ellipse::createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex)
+{
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+ double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+ GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+ if (aFocus->distance(aCenter) > tolerance) {
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ anEllipseShape =
+ GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+ }
+ else {
+ // build circle instead of ellipse
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+ }
+
+ ResultConstructionPtr aResult = document()->createConstruction(data(), theResultIndex);
+ aResult->setShape(anEllipseShape);
+ aResult->setIsInHistory(false);
+ setResult(aResult, theResultIndex);
+}
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_Ellipse.h
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#ifndef SketchPlugin_Ellipse_H_
#define SketchPlugin_Ellipse_H_
}
/// 2D point - focus of the ellipse
- inline static const std::string& FOCUS_ID()
+ inline static const std::string& FIRST_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_first_focus");
+ return ID;
+ }
+ /// 2D point - second focus of the ellipse
+ inline static const std::string& SECOND_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_second_focus");
+ return ID;
+ }
+
+ /// 2D point - start point of major axis
+ inline static const std::string& MAJOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_major_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of major axis
+ inline static const std::string& MAJOR_AXIS_END_ID()
{
- static const std::string ID("ellipse_focus");
+ static const std::string ID("ellipse_major_axis_end_point");
+ return ID;
+ }
+
+ /// 2D point - start point of minor axis
+ inline static const std::string& MINOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of minor axis
+ inline static const std::string& MINOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_end_point");
return ID;
}
/// Use plugin manager for features creation
SketchPlugin_Ellipse();
+ /// Returns \c true if the result is marked as auxiliary
+ virtual bool isAuxiliary(ResultPtr theResult);
+
protected:
/// \brief Initializes attributes of derived class.
virtual void initDerivedClassAttributes();
+
+private:
+ bool fillCharacteristicPoints();
+
+ void createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex);
+
+private:
+ std::set<ResultPtr> myAuxiliaryResults;
};
#endif
#include <ModelAPI_Validator.h>
#include <ModelAPI_Session.h>
-#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Edge.h>
#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pnt2d.h>
-#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomDataAPI_Point2D.h>
SketchPlugin_Line::SketchPlugin_Line()
std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
GeomDataAPI_Point2D>(data()->attribute(END_ID()));
if (aStartAttr->isInitialized() && anEndAttr->isInitialized()) {
- std::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
- std::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
- //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
- // <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
- // make linear edge
- std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
- // store the result
- std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(
- data());
- aConstr->setShape(anEdge);
- aConstr->setIsInHistory(false);
- setResult(aConstr);
+ SketchPlugin_Sketch::createLine2DResult(this, aSketch, START_ID(), END_ID());
static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_MacroEllipse.cpp
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#include <SketchPlugin_MacroEllipse.h>
#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_MacroArcReentrantMessage.h>
#include <SketchPlugin_Tools.h>
#include <SketchPlugin_Sketch.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeRefAttr.h>
-#include <ModelAPI_EventReentrantMessage.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Events.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_Ellipse2d.h>
#include <GeomAPI_Vertex.h>
void SketchPlugin_MacroEllipse::initAttributes()
{
- data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
- data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
- data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
- data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(EDIT_ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+
+ data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
- ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
- ModelAPI_Session::get()->validators()->
- registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+ string(EDIT_ELLIPSE_TYPE())->setValue("");
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ELLIPSE_TYPE());
}
void SketchPlugin_MacroEllipse::execute()
{
FeaturePtr anEllipse = createEllipseFeature();
- constraintsForEllipse(anEllipse);
+
+ std::string aType = string(ELLIPSE_TYPE())->value();
+ if (aType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT())
+ constraintsForEllipseByCenterAxisAndPassed(anEllipse);
+ else if (aType == ELLIPSE_TYPE_BY_AXIS_AND_POINT())
+ constraintsForEllipseByMajoxAxisAndPassed(anEllipse);
// message to init reentrant operation
- static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
- ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this));
+ static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+ <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
+
+ std::string anEditType = string(EDIT_ELLIPSE_TYPE())->value();
+ aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType);
aMessage->setCreatedFeature(anEllipse);
Events_Loop::loop()->send(aMessage);
}
void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
{
static const int NB_POINTS = 3;
- std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(),
- MAJOR_AXIS_POINT_ID(),
+ std::string aPointAttrName[NB_POINTS] = { FIRST_POINT_ID(),
+ SECOND_POINT_ID(),
PASSED_POINT_ID() };
- std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(),
- MAJOR_AXIS_POINT_REF_ID(),
+ std::string aPointRefName[NB_POINTS] = { FIRST_POINT_REF_ID(),
+ SECOND_POINT_REF_ID(),
PASSED_POINT_REF_ID() };
- int aNbInitialized = 0;
- std::shared_ptr<GeomAPI_Pnt2d> anEllipsePoints[NB_POINTS];
+ // type of ellipse switched, thus reset all attributes
+ if (theID == ELLIPSE_TYPE()) {
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ SketchPlugin_Tools::resetAttribute(this, aPointAttrName[aPntIndex]);
+ SketchPlugin_Tools::resetAttribute(this, aPointRefName[aPntIndex]);
+ }
+ }
+ else {
+ int aNbInitialized = 0;
+ GeomPnt2dPtr anEllipsePoints[NB_POINTS];
+
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+ if (!aPointAttr->isInitialized())
+ continue;
+
+ AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+ // calculate ellipse parameters
+ GeomPnt2dPtr aPassedPoint;
+ GeomShapePtr aTangentCurve;
+ SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+ aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
- for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
- AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
- if (!aPointAttr->isInitialized())
- continue;
+ anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ }
- AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
- // calculate ellipse parameters
- std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
- std::shared_ptr<GeomAPI_Shape> aTangentCurve;
- SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
- aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+ if (aNbInitialized <= 1)
+ return; // too few points for the ellipse
- anEllipsePoints[aNbInitialized++] = aPassedPoint;
- }
+ if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+ // ellipse is given by major axis and passing point,
+ // recalculate the first point to be a center
+ anEllipsePoints[0]->setX(0.5 * (anEllipsePoints[0]->x() + anEllipsePoints[1]->x()));
+ anEllipsePoints[0]->setY(0.5 * (anEllipsePoints[0]->y() + anEllipsePoints[1]->y()));
+ }
- std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
- if (aNbInitialized == 2) {
- std::shared_ptr<GeomAPI_Dir2d> aXDir(new GeomAPI_Dir2d(
- anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
- anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
- double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
- anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
- new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
- } else if (aNbInitialized == 3) {
- anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+ if (aNbInitialized == 2) {
+ GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+ anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+ double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+ }
+ else if (aNbInitialized == 3) {
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
- }
+ }
- if (!anEllipse || anEllipse->implPtr<void>() == 0)
- return;
+ if (!anEllipse || anEllipse->implPtr<void>() == 0)
+ return;
- myCenter = anEllipse->center();
- myFocus = anEllipse->firstFocus();
- myMajorRadius = anEllipse->majorRadius();
- myMinorRadius = anEllipse->minorRadius();
+ myCenter = anEllipse->center();
+ myFocus = anEllipse->firstFocus();
+ myMajorRadius = anEllipse->majorRadius();
+ myMinorRadius = anEllipse->minorRadius();
- AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
- AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
- bool aWasBlocked = data()->blockSendAttributeUpdated(true);
- // center attribute is used in processEvent() to set reference to reentrant arc
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->setValue(myCenter);
- aMajorRadiusAttr->setValue(myMajorRadius);
- aMinorRadiusAttr->setValue(myMinorRadius);
- data()->blockSendAttributeUpdated(aWasBlocked, false);
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ // center attribute is used in processEvent() to set reference to reentrant arc
+//// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()))
+//// ->setValue(myCenter);
+ aMajorRadiusAttr->setValue(myMajorRadius);
+ aMinorRadiusAttr->setValue(myMinorRadius);
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+ }
}
+// LCOV_EXCL_START
std::string SketchPlugin_MacroEllipse::processEvent(
const std::shared_ptr<Events_Message>& theMessage)
{
std::string aFilledAttributeName;
- ReentrantMessagePtr aReentrantMessage =
- std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+ std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
if (aReentrantMessage) {
FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+ std::string anEllipseType = aReentrantMessage->typeOfCreation();
+
+ string(ELLIPSE_TYPE())->setValue(anEllipseType);
+
+ aFilledAttributeName = ELLIPSE_TYPE();
ObjectPtr anObject = aReentrantMessage->selectedObject();
AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
if (aClickedPoint && (anObject || anAttribute)) {
- aFilledAttributeName = CENTER_POINT_ID();
- std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+ aFilledAttributeName = FIRST_POINT_ID();
+ std::string aReferenceAttributeName = FIRST_POINT_REF_ID();
// fill 2d point attribute
AttributePoint2DPtr aPointAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
if (anAttribute) {
if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
- if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
- anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID());
+ if (aCreatedFeature && anAttribute->id() == FIRST_POINT_ID())
+ anAttribute = aCreatedFeature->attribute(
+ anEllipseType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT() ?
+ SketchPlugin_Ellipse::CENTER_ID() :
+ SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
}
aRefAttr->setAttr(anAttribute);
}
else if (anObject.get()) {
- // if presentation of previous reentrant macro arc is used, the object is invalid,
- // we should use result of previous feature of the message(Arc)
- if (!anObject->data()->isValid())
- anObject = aCreatedFeature->lastResult();
- aRefAttr->setObject(anObject);
+ // if attribute is NULL, only object is defined, it should be processed outside
+ // the feature because it might be an external feature, that will be
+ // removed/created again after restart operation
+ // #2468 - Crash when sketching circles successively on a repetition
+ aFilledAttributeName = ELLIPSE_TYPE();
}
}
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
}
return aFilledAttributeName;
}
+// LCOV_EXCL_STOP
-void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature)
+void SketchPlugin_MacroEllipse::constraintsForEllipseByCenterAxisAndPassed(
+ FeaturePtr theEllipseFeature)
{
+ // tangency on-the-fly is not applicable for ellipses
+ static const bool isTangencyApplicable = false;
// Create constraints.
SketchPlugin_Tools::createCoincidenceOrTangency(
- this, CENTER_POINT_REF_ID(),
+ this, FIRST_POINT_REF_ID(),
theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
- ObjectPtr(), false);
+ ObjectPtr(), isTangencyApplicable);
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, SECOND_POINT_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ ObjectPtr(), isTangencyApplicable);
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, PASSED_POINT_REF_ID(), AttributePtr(),
+ theEllipseFeature->lastResult(), isTangencyApplicable);
+}
+
+void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed(
+ FeaturePtr theEllipseFeature)
+{
+ // tangency on-the-fly is not applicable for ellipses
+ static const bool isTangencyApplicable = false;
+ // Create constraints.
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, FIRST_POINT_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ ObjectPtr(), isTangencyApplicable);
SketchPlugin_Tools::createCoincidenceOrTangency(
- this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(),
- theEllipseFeature->lastResult(), true);
+ this, SECOND_POINT_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ ObjectPtr(), isTangencyApplicable);
SketchPlugin_Tools::createCoincidenceOrTangency(
this, PASSED_POINT_REF_ID(), AttributePtr(),
- theEllipseFeature->lastResult(), true);
+ theEllipseFeature->lastResult(), isTangencyApplicable);
}
FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
aCenterAttr->setValue(myCenter->x(), myCenter->y());
AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID()));
+ aEllipseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
aFocusAttr->setValue(myFocus->x(), myFocus->y());
aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
// Compute a ellipse in 3D view.
- std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
- std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
- std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
- std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomPointPtr aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
std::shared_ptr<GeomAPI_Shape> anEllipseShape =
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_MacroEllipse.h
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#ifndef SketchPlugin_MacroEllipse_H_
#define SketchPlugin_MacroEllipse_H_
return ID;
}
- /// 2D point - center of the ellipse.
- inline static const std::string& CENTER_POINT_ID()
+ static const std::string& ELLIPSE_TYPE()
+ {
+ static const std::string ID("ellipse_type");
+ return ID;
+ }
+
+ static const std::string& ELLIPSE_TYPE_BY_CENTER_AXIS_POINT()
+ {
+ static const std::string ID("by_center_axis_point");
+ return ID;
+ }
+ static const std::string& ELLIPSE_TYPE_BY_AXIS_AND_POINT()
+ {
+ static const std::string ID("by_major_axis_and_point");
+ return ID;
+ }
+
+ static const std::string& EDIT_ELLIPSE_TYPE()
+ {
+ static const std::string ID("edit_ellipse_type");
+ return ID;
+ }
+
+ /// Attribute for the first point selected during ellipse creation.
+ inline static const std::string& FIRST_POINT_ID()
{
- static const std::string ID("center_point");
+ static const std::string ID("first_point");
return ID;
}
- /// Reference for center point selection.
- inline static const std::string& CENTER_POINT_REF_ID()
+ /// Reference to the first selected point.
+ inline static const std::string& FIRST_POINT_REF_ID()
{
- static const std::string ID("center_point_ref");
+ static const std::string ID("first_point_ref");
return ID;
}
- /// 2D point - major axis point of the ellipse.
- inline static const std::string& MAJOR_AXIS_POINT_ID()
+ /// Attribute for the second point selected during ellipse creation.
+ inline static const std::string& SECOND_POINT_ID()
{
- static const std::string ID("major_axis_point");
+ static const std::string ID("second_point");
return ID;
}
- /// Reference for major axis point selection.
- inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+ /// Reference to the second selected point.
+ inline static const std::string& SECOND_POINT_REF_ID()
{
- static const std::string ID("major_axis_point_ref");
+ static const std::string ID("second_point_ref");
return ID;
}
- /// 2D point - passed point of the ellipse
+ /// Attribute for the third point selected during ellipse creation.
inline static const std::string& PASSED_POINT_ID()
{
static const std::string ID("passed_point");
/// Major radius of the ellipse
inline static const std::string& MAJOR_RADIUS_ID()
{
- static const std::string ID("ellipse_major_radius");
+ static const std::string ID("major_radius");
return ID;
}
/// Minor radius of the ellipse
inline static const std::string& MINOR_RADIUS_ID()
{
- static const std::string ID("ellipse_minor_radius");
+ static const std::string ID("minor_radius");
return ID;
}
SketchPlugin_MacroEllipse();
private:
- void constraintsForEllipse(FeaturePtr theEllipseFeature);
+ void constraintsForEllipseByCenterAxisAndPassed(FeaturePtr theEllipseFeature);
+ void constraintsForEllipseByMajoxAxisAndPassed(FeaturePtr theEllipseFeature);
FeaturePtr createEllipseFeature();
aMsg->setState(SketchPlugin_Trim::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane);
// SketchRectangle is a python feature, so its ID is passed just as a string
theFeature->setResult(aResult, theIndex);
}
+void SketchPlugin_Sketch::createLine2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theStartAttrID,
+ const std::string& theEndAttrID,
+ const int theIndex)
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theStartAttrID));
+ std::shared_ptr<GeomDataAPI_Point2D> anEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theEndAttrID));
+
+ if (!aStartAttr || !aStartAttr->isInitialized() ||
+ !anEndAttr || !anEndAttr->isInitialized())
+ return;
+
+ std::shared_ptr<GeomAPI_Pnt> aStart(theSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+ std::shared_ptr<GeomAPI_Pnt> anEnd(theSketch->to3D(anEndAttr->x(), anEndAttr->y()));
+ //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
+ // <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
+ // make linear edge
+ std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
+ // store the result
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult =
+ theFeature->document()->createConstruction(theFeature->data(), theIndex);
+ aResult->setShape(anEdge);
+ aResult->setIsInHistory(false);
+ theFeature->setResult(aResult, theIndex);
+}
+
FeaturePtr SketchPlugin_Sketch::addUniqueNamedCopiedFeature(FeaturePtr theFeature,
SketchPlugin_Sketch* theSketch,
const bool theIsCopy)
SketchPlugin_Sketch* theSketch,
const std::string& theAttributeID, const int theIndex);
+ /// \brief Create a result for the segment given by a pair of attributes
+ /// \param theFeature a source feature
+ /// \param theSketch a sketch intance
+ /// \param theStartAttrID an attribute string
+ /// \param theEndAttrID an attribute string
+ /// \param theIndex an index of the result
+ static void createLine2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theStartAttrID,
+ const std::string& theEndAttrID,
+ const int theIndex = 0);
+
/// Add new feature and fill the data of the feature by the data of the parameter feature.
/// The name of the created feature stays unique.
/// \param theFeature a source feature
}
// LCOV_EXCL_START
+ /// Returns \c true if the result is marked as auxiliary
+ virtual bool isAuxiliary(ResultPtr theResult)
+ { return false; }
+
/// Customize presentation of the feature
virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
std::vector<int> aColor;
std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
- bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
+ bool isConstruction = (anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value())
+ || isAuxiliary(theResult);
if (isConstruction) {
aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
}
id="Sketch"
nested="SketchPoint SketchIntersectionPoint SketchLine
SketchCircle SketchMacroCircle SketchArc SketchMacroArc
+ SketchEllipse SketchMacroEllipse
SketchRectangle
SketchProjection
SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
</feature>
</group>
-<excluded>
<group id="Elliptic geometry">
<!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
<feature id="SketchEllipse"
tooltip="Center coordinates"
accept_expressions="0"
enable_value="enable_by_preferences"/>
- <sketch-2dpoint_selector id="ellipse_focus"
- title="Focus"
+ <sketch-2dpoint_selector id="ellipse_first_focus"
+ title="First focus"
tooltip="Focus coordinates"
accept_expressions="0"
enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_second_focus"
+ title="Second focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_start_point"
+ title="Major axis start"
+ tooltip="Coordinates of point on negative direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_end_point"
+ title="Major axis end"
+ tooltip="Coordinates of point on positive direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_start_point"
+ title="Minor axis start"
+ tooltip="Coordinates of point on negative direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_end_point"
+ title="Minor axis end"
+ tooltip="Coordinates of point on positive direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
<labelvalue id="ellipse_major_radius"
- icon="icons/Sketch/radius.png"
+ icon="icons/Sketch/radius_major.png"
label="Major radius:"
tooltip="Set major radius"
default="computed"
enable_value="enable_by_preferences">
</labelvalue>
<labelvalue id="ellipse_minor_radius"
- icon="icons/Sketch/radius.png"
+ icon="icons/Sketch/radius_minor.png"
label="Minor radius:"
tooltip="Set minor radius"
default="computed"
title="Ellipse"
tooltip="Create ellipse"
helpfile="ellipseFeature.html">
- <sketch-2dpoint_selector id="center_point"
- reference_attribute="center_point_ref"
- title="Center point"
- tooltip="Center point coordinates"
- accept_expressions="0"
- enable_value="enable_by_preferences"/>
- <sketch-2dpoint_selector id="major_axis_point"
- reference_attribute="major_axis_point_ref"
- title="Major axis point"
- tooltip="Major axis point coordinates"
- accept_expressions="0"
- enable_value="enable_by_preferences"/>
- <sketch-2dpoint_selector id="passed_point"
- reference_attribute="passed_point_ref"
- title="Passed point"
- tooltip="Passed point coordinates"
- accept_expressions="0"
- enable_value="enable_by_preferences">
-<!-- <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
- </sketch-2dpoint_selector>
+ <toolbox id="ellipse_type" modified_in_edit="edit_ellipse_type">
+ <box id="by_center_axis_point"
+ icon="icons/Sketch/ellipse_cent_rad_32x32.png"
+ title="Center, major semi-axis and passing point">
+ <sketch-2dpoint_selector id="first_point"
+ reference_attribute="first_point_ref"
+ title="Center point"
+ tooltip="Center point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="second_point"
+ reference_attribute="second_point_ref"
+ title="Major axis point"
+ tooltip="Major axis point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="passed_point"
+ reference_attribute="passed_point_ref"
+ title="Passed point"
+ tooltip="Passed point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ <!-- <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
+ </sketch-2dpoint_selector>
+ </box>
+ <box id="by_major_axis_and_point"
+ icon="icons/Sketch/ellipse_axes_32x32.png"
+ title="Major axis and passing point">
+ <sketch-2dpoint_selector id="first_point"
+ reference_attribute="first_point_ref"
+ title="Major axis start point"
+ tooltip="Major axis start point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="second_point"
+ reference_attribute="second_point_ref"
+ title="Major axis end point"
+ tooltip="Major axis end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="passed_point"
+ reference_attribute="passed_point_ref"
+ title="Passed point"
+ tooltip="Passed point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ </box>
+ </toolbox>
<!-- <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
- <labelvalue id="ellipse_major_radius"
- icon="icons/Sketch/radius.png"
+ <labelvalue id="major_radius"
+ icon="icons/Sketch/radius_major.png"
label="Major radius:"
tooltip="Set major radius"
default="computed"
enable_value="enable_by_preferences">
<validator id="GeomValidators_Positive"/>
</labelvalue>
- <labelvalue id="ellipse_minor_radius"
- icon="icons/Sketch/radius.png"
+ <labelvalue id="minor_radius"
+ icon="icons/Sketch/radius_minor.png"
label="Minor radius:"
tooltip="Set minor radius"
default="computed"
obligatory="0"/>
</feature>
</group>
-</excluded>
<group id="Projection">
<!-- Projected feature -->
PlaneGCSSolver_Storage.h
PlaneGCSSolver_ConstraintWrapper.h
PlaneGCSSolver_EdgeWrapper.h
- PlaneGCSSolver_EdgeWrapper.h
+ PlaneGCSSolver_EntityWrapper.h
PlaneGCSSolver_PointWrapper.h
PlaneGCSSolver_ScalarWrapper.h
PlaneGCSSolver_AngleWrapper.h
ENTITY_POINT,
ENTITY_LINE,
ENTITY_CIRCLE,
- ENTITY_ARC
+ ENTITY_ARC,
+ ENTITY_ELLIPSE,
+ ENTITY_ELLIPTICAL_ARC
};
/// Types of constraints
else {
std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
if (aCircle) myType = ENTITY_CIRCLE;
+ else {
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
+ if (anEllipse) myType = ENTITY_ELLIPSE;
+ }
}
}
}
return aSqRadius < aSqTol || aSqRadius > aMaxRadius * aMaxRadius || // <- arc radius
anAngleDiff < anAngleTol || fabs(anAngleDiff - 2*PI) < anAngleTol; // <- arc angle
}
+ else if (myType == ENTITY_ELLIPSE) {
+ std::shared_ptr<GCS::Ellipse> anEllipse = std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
+ return *anEllipse->radmin < tolerance;
+ }
return false;
}
#include <list>
#include <memory>
+class PlaneGCSSolver_EntityWrapper;
+typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
+
/**
* Wrapper providing operations with entities regardless the solver.
*/
/// \brief Return the External flag
bool isExternal() const { return myExternal; }
+ /// \brief Store names of attributes and their values if necessary
+ void setAdditionalAttributes(const std::map<std::string, EntityWrapperPtr>& theAttribues)
+ { myAdditionalAttributes = theAttribues; }
+ /// \brief Return the list of additional attributes
+ const std::map<std::string, EntityWrapperPtr>& additionalAttributes() const
+ { return myAdditionalAttributes; }
+
private:
bool myExternal;
+ std::map<std::string, EntityWrapperPtr> myAdditionalAttributes;
};
-typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
-
#endif
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
PlaneGCSSolver_Storage* theStorage);
+static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
// Arc
else if (aFeatureKind == SketchPlugin_Arc::ID())
aResult = createArc(myAttributes, myStorage);
+ // Ellipse
+ else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+ aResult = createEllipse(myAttributes);
// Point (it has low probability to be an attribute of constraint, so it is checked at the end)
else if (aFeatureKind == SketchPlugin_Point::ID() ||
aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
return anArcWrapper;
}
+EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
+{
+ std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
+
+ std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
+
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (aPoint) {
+ if (anIt->first->id() == SketchPlugin_Ellipse::CENTER_ID())
+ aNewEllipse->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Ellipse::FIRST_FOCUS_ID())
+ aNewEllipse->focus1 = *(aPoint->point());
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+ else if (anIt->first->id() == SketchPlugin_Ellipse::MINOR_RADIUS_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewEllipse->radmin = aScalar->scalar();
+ }
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+
+ EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
+ anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+ return anEllipseWrapper;
+}
+
bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
{
if (theOwnerName == SketchPlugin_Arc::ID()) {
return theAttrName == SketchPlugin_Line::START_ID() ||
theAttrName == SketchPlugin_Line::END_ID();
}
+ else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
+ return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
+ theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
+ }
// suppose that all remaining features are points
return theAttrName == SketchPlugin_Point::COORD_ID();
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Projection.h>
#include <cmath>
// (do not want to add several copies of it while adding attributes)
aRelated = createFeature(theFeature, &aBuilder);
myFeatureMap[theFeature] = aRelated;
- createArcConstraints(aRelated);
+ createAuxiliaryConstraints(aRelated);
isUpdated = true;
}
if (theEntity->isExternal())
return;
- removeArcConstraints(theEntity);
+ removeAuxiliaryConstraints(theEntity);
GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
mySketchSolver->removeParameters(aParameters);
mySketchSolver->addParameters(aParameters);
theEntity->setExternal(false);
- createArcConstraints(theEntity);
+ createAuxiliaryConstraints(theEntity);
myNeedToResolve = true;
}
-void PlaneGCSSolver_Storage::createArcConstraints(const EntityWrapperPtr& theArc)
+static void createArcConstraints(const EntityWrapperPtr& theArc,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
{
- if (!theArc || theArc->type() != ENTITY_ARC || theArc->isExternal())
- return;
-
EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
std::list<GCSConstraintPtr> anArcConstraints;
// constrain the start point on the arc
anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
- anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
+ anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
- anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
+ anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
// constrain the end point on the arc
anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
- anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
+ anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
- anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+ anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+
+ ConstraintWrapperPtr aWrapper(
+ new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
+ aWrapper->setId(theConstraintID);
+ constraintsToSolver(aWrapper, theSolver);
+
+ theConstraints[theArc] = aWrapper;
+}
+
+static void createEllipseConstraints(
+ const EntityWrapperPtr& theEllipse,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
+{
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipse);
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+ // Additional constaints to fix ellipse's extra points
+ std::list<GCSConstraintPtr> anEllipseConstraints;
+
+ const std::map<std::string, EntityWrapperPtr>& anAttributes = theEllipse->additionalAttributes();
+ for (std::map<std::string, EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
+ anIt != anAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (!aPoint)
+ continue;
+
+ GCS::InternalAlignmentType anAlignmentX, anAlignmentY;
+ if (anIt->first == SketchPlugin_Ellipse::SECOND_FOCUS_ID())
+ anAlignmentX = GCS::EllipseFocus2X;
+ else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())
+ anAlignmentX = GCS::EllipseNegativeMajorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
+ anAlignmentX = GCS::EllipsePositiveMajorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_START_ID())
+ anAlignmentX = GCS::EllipseNegativeMinorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
+ anAlignmentX = GCS::EllipsePositiveMinorX;
+
+ anEllipseConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintInternalAlignmentPoint2Ellipse(*anEllipse, *(aPoint->point()), anAlignmentX)));
+ anAlignmentY = (GCS::InternalAlignmentType)((int)anAlignmentX + 1);
+ anEllipseConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintInternalAlignmentPoint2Ellipse(*anEllipse, *(aPoint->point()), anAlignmentY)));
+ }
+
+ // constraint to bind the major radius value
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aMajorAxisStart =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
+ anAttributes.at(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
+ ScalarWrapperPtr aMajorRadius =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
+ anAttributes.at(SketchPlugin_Ellipse::MAJOR_RADIUS_ID()));
+ anEllipseConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anEllipse->center, *(aMajorAxisStart->point()), aMajorRadius->scalar())));
ConstraintWrapperPtr aWrapper(
- new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
- aWrapper->setId(++myConstraintLastID);
- constraintsToSolver(aWrapper, mySketchSolver);
+ new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
+ aWrapper->setId(theConstraintID);
+ constraintsToSolver(aWrapper, theSolver);
- myArcConstraintMap[theArc] = aWrapper;
+ theConstraints[theEllipse] = aWrapper;
}
-void PlaneGCSSolver_Storage::removeArcConstraints(const EntityWrapperPtr& theArc)
+void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
+{
+ if (!theEntity || theEntity->isExternal())
+ return;
+
+ if (theEntity->type() == ENTITY_ARC)
+ createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+ else if (theEntity->type() == ENTITY_ELLIPSE)
+ createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+}
+
+void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
{
std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
- aFound = myArcConstraintMap.find(theArc);
- if (aFound != myArcConstraintMap.end()) {
+ aFound = myAuxConstraintMap.find(theEntity);
+ if (aFound != myAuxConstraintMap.end()) {
mySketchSolver->removeConstraint(aFound->second->id());
- myArcConstraintMap.erase(aFound);
+ myAuxConstraintMap.erase(aFound);
}
}
void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
{
- std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myArcConstraintMap.begin();
- for (; anIt != myArcConstraintMap.end(); ++anIt) {
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
+ for (; anIt != myAuxConstraintMap.end(); ++anIt) {
EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
+ if (!anArc)
+ continue;
// tune start angle of the arc to be in [0, 2PI]
while (*anArc->startAngle < -PI)
*anArc->startAngle += 2.0 * PI;
aDestroyer.remove(aFIter->second);
// remove invalid arc
- removeArcConstraints(aFIter->second);
+ removeAuxiliaryConstraints(aFIter->second);
}
std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
/// \brief Check the storage has constraints
virtual bool isEmpty() const
- { return SketchSolver_Storage::isEmpty() && myArcConstraintMap.empty(); }
+ { return SketchSolver_Storage::isEmpty() && myAuxConstraintMap.empty(); }
/// \brief Make parametrization of arcs consistent.
/// Forward arcs should have the last parameter greater than the first parameter.
EntityWrapperPtr createAttribute(const AttributePtr& theAttribute,
PlaneGCSSolver_EntityBuilder* theBuilder);
- void createArcConstraints(const EntityWrapperPtr& theArc);
- void removeArcConstraints(const EntityWrapperPtr& theArc);
+ /// \brief Create additional constaints:
+ /// * for arc to fix extra parameters;
+ /// * for ellipse to keep auxiliary points on their places
+ void createAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
+ void removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
private:
ConstraintID myConstraintLastID; ///< identifier of last added constraint
- /// additional constraints for correct processing of the arcs
- std::map<EntityWrapperPtr, ConstraintWrapperPtr> myArcConstraintMap;
+ /// additional constraints for correct processing of the arcs, ellipses, elliptical arcs
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr> myAuxConstraintMap;
/// list of removed constraints to notify solver
std::list<GCSConstraintPtr> myRemovedConstraints;
static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
+static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
return circleParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_ARC:
return arcParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_ELLIPSE:
+ return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
default: break;
}
return GCS::SET_pD();
new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
break;
}
+ case ENTITY_ELLIPSE:
+ case ENTITY_ELLIPTICAL_ARC: {
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
+ aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
+ break;
+ }
default:
return ConstraintWrapperPtr();
}
std::shared_ptr<GCS::Circle> aCirc2 =
std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
+ if (aCirc1 && aCirc2)
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
+ else {
+ std::shared_ptr<GCS::Ellipse> anEllipse1 =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
+ std::shared_ptr<GCS::Ellipse> anEllipse2 =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
+
+ aConstrList.push_back(GCSConstraintPtr(
+ new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
+ aConstrList.push_back(GCSConstraintPtr(
+ new GCS::ConstraintEqualMajorAxesConic(anEllipse1.get(), anEllipse2.get())));
+ }
}
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
aParams.insert(anArc->rad);
return aParams;
}
+
+GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
+{
+ GCS::SET_pD aParams;
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
+ aParams.insert(anEllipse->center.x);
+ aParams.insert(anEllipse->center.y);
+ aParams.insert(anEllipse->focus1.x);
+ aParams.insert(anEllipse->focus1.y);
+ aParams.insert(anEllipse->radmin);
+ return aParams;
+}
aParameters.push_back(anArc->endAngle);
break;
}
+ case ENTITY_ELLIPSE: {
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
+ aParameters.push_back(anEllipse->center.x);
+ aParameters.push_back(anEllipse->center.y);
+ aParameters.push_back(anEllipse->focus1.x);
+ aParameters.push_back(anEllipse->focus1.y);
+ aParameters.push_back(anEllipse->radmin);
+ break;
+ }
default:
break;
}
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <GeomAPI_Pnt2d.h>
+#include <cmath>
+
+static GCS::Point createGCSPoint(double* x, double* y)
+{
+ GCS::Point aPoint;
+ aPoint.x = x;
+ aPoint.y = y;
+ return aPoint;
+}
+
SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
: SketchSolver_ConstraintFixed(ConstraintPtr()),
{
bool isSimple = true;
#ifdef CHANGE_RADIUS_WHILE_MOVE
- if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
+ if (theMovedFeature->getKind() == SketchPlugin_Circle::ID() ||
+ theMovedFeature->getKind() == SketchPlugin_Ellipse::ID())
isSimple = (theDraggedPoint.get() != 0);
else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
isSimple = (theDraggedPoint.get() != 0 &&
else {
if (myDraggedPoint) // start or end point of arc has been moved
aConstraint = fixArcExtremity(anEntity);
- else // arc or circle has been moved
+ else if (anEntity->type() == ENTITY_CIRCLE || anEntity->type() == ENTITY_ARC) {
+ // arc or circle has been moved
aConstraint = fixPointOnCircle(anEntity);
+ }
+ else if (anEntity->type() == ENTITY_ELLIPSE || anEntity->type() == ENTITY_ELLIPTICAL_ARC) {
+ // ellipse or elliptical arc has been moved
+ aConstraint = fixPointOnEllipse(anEntity);
+ }
}
return aConstraint;
myFixedValues.push_back(*aCircular->center.y);
// create a moved point
- GCS::Point aPointOnCircle;
- aPointOnCircle.x = &myFixedValues[0];
- aPointOnCircle.y = &myFixedValues[1];
+ GCS::Point aPointOnCircle = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
std::list<GCSConstraintPtr> aConstraints;
// point-on-circle
new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
}
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnEllipse(
+ const EntityWrapperPtr& theConic)
+{
+ static const double scale = 0.01;
+ static const int nbParams = 6;
+ myFixedValues.reserve(nbParams); // moved point; center and focus of ellipse
+
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theConic);
+ std::shared_ptr<GCS::Ellipse> aConic = std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+ // major axis direction
+ double dx = *aConic->focus1.x - *aConic->center.x;
+ double dy = *aConic->focus1.y - *aConic->center.y;
+ double norm = sqrt(dx * dx + dy* dy);
+ if (norm < tolerance) {
+ dx = 1.0;
+ dy = 0.0;
+ }
+ else {
+ dx /= norm;
+ dy /= norm;
+ }
+
+ double aMajorRad = aConic->getRadMaj();
+
+ // initialize fixed values
+ myFixedValues.push_back(*aConic->center.x + dx * aMajorRad);
+ myFixedValues.push_back(*aConic->center.y + dy * aMajorRad);
+ myFixedValues.push_back(*aConic->center.x);
+ myFixedValues.push_back(*aConic->center.y);
+ myFixedValues.push_back(*aConic->focus1.x);
+ myFixedValues.push_back(*aConic->focus1.y);
+
+ // create a moved point
+ GCS::Point aPointOnEllipse = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
+
+ std::list<GCSConstraintPtr> aConstraints;
+ // point-on-circle
+ GCSConstraintPtr aNewConstraint(
+ new GCS::ConstraintPointOnEllipse(aPointOnEllipse, *aConic));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (x)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[2], aConic->center.x));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (y)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[3], aConic->center.y));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // focus on the major axis
+ GCS::Point aStartPoint = createGCSPoint(&myFixedValues[2], &myFixedValues[3]);
+ GCS::Point aEndPoint = createGCSPoint(&myFixedValues[4], &myFixedValues[5]);
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintPointOnLine(aConic->focus1, aStartPoint, aEndPoint));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+}
void SketchSolver_ConstraintMovement::startPoint(
const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint)
/// \brief Create constraint to fix moved arc extremity
ConstraintWrapperPtr fixArcExtremity(const EntityWrapperPtr& theArcExtremity);
- /// \brief Creat constraint to fix moved point on circle/arc
+ /// \brief Create constraint to fix moved point on circle/arc
ConstraintWrapperPtr fixPointOnCircle(const EntityWrapperPtr& theCircular);
+ /// \brief Create constraint to fix moved point on ellipse/elliptical arc
+ ConstraintWrapperPtr fixPointOnEllipse(const EntityWrapperPtr& theConic);
+
private:
FeaturePtr myMovedFeature; ///< fixed feature (if set, myBaseConstraint should be NULL)
AttributePtr myDraggedPoint; ///< one of the feature points which has been moved