diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp
index d00e2a431b..b751e8f611 100644
--- a/src/Mod/Part/App/AppPart.cpp
+++ b/src/Mod/Part/App/AppPart.cpp
@@ -66,6 +66,7 @@
#include "EllipsePy.h"
#include "ArcPy.h"
#include "ArcOfCirclePy.h"
+#include "ArcOfEllipsePy.h"
#include "BezierCurvePy.h"
#include "BSplineCurvePy.h"
#include "HyperbolaPy.h"
@@ -172,6 +173,7 @@ void PartExport initPart()
Base::Interpreter().addType(&Part::ParabolaPy ::Type,partModule,"Parabola");
Base::Interpreter().addType(&Part::ArcPy ::Type,partModule,"Arc");
Base::Interpreter().addType(&Part::ArcOfCirclePy ::Type,partModule,"ArcOfCircle");
+ Base::Interpreter().addType(&Part::ArcOfEllipsePy ::Type,partModule,"ArcOfEllipse");
Base::Interpreter().addType(&Part::BezierCurvePy ::Type,partModule,"BezierCurve");
Base::Interpreter().addType(&Part::BSplineCurvePy ::Type,partModule,"BSplineCurve");
Base::Interpreter().addType(&Part::OffsetCurvePy ::Type,partModule,"OffsetCurve");
@@ -261,6 +263,7 @@ void PartExport initPart()
Part::GeomBSplineCurve ::init();
Part::GeomCircle ::init();
Part::GeomArcOfCircle ::init();
+ Part::GeomArcOfEllipse ::init();
Part::GeomEllipse ::init();
Part::GeomHyperbola ::init();
Part::GeomParabola ::init();
diff --git a/src/Mod/Part/App/ArcOfEllipsePy.xml b/src/Mod/Part/App/ArcOfEllipsePy.xml
new file mode 100644
index 0000000000..2f0f8bf813
--- /dev/null
+++ b/src/Mod/Part/App/ArcOfEllipsePy.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+ Describes a portion of an ellipse
+
+
+
+ The major radius of the ellipse.
+
+
+
+
+
+ The minor radius of the ellipse.
+
+
+
+
+
+ The angle between the X axis and the major axis of the ellipse.
+
+
+
+
+
+ Center of the ellipse.
+
+
+
+
+
+ The axis direction of the ellipse
+
+
+
+
+
+ The internal ellipse representation
+
+
+
+
+
diff --git a/src/Mod/Part/App/ArcOfEllipsePyImp.cpp b/src/Mod/Part/App/ArcOfEllipsePyImp.cpp
new file mode 100644
index 0000000000..341f9e7942
--- /dev/null
+++ b/src/Mod/Part/App/ArcOfEllipsePyImp.cpp
@@ -0,0 +1,233 @@
+/***************************************************************************
+ * Copyright (c) 2014 Abdullah Tahiri
+# include
+# include
+# include
+# include
+#endif
+
+#include "Mod/Part/App/Geometry.h"
+#include "ArcOfEllipsePy.h"
+#include "ArcOfEllipsePy.cpp"
+#include "EllipsePy.h"
+#include "OCCError.h"
+
+#include
+#include
+
+using namespace Part;
+
+extern const char* gce_ErrorStatusText(gce_ErrorType et);
+
+// returns a string which represents the object e.g. when printed in python
+std::string ArcOfEllipsePy::representation(void) const
+{
+ Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
+ (getGeomArcOfEllipsePtr()->handle());
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
+
+ gp_Ax1 axis = ellipse->Axis();
+ gp_Dir dir = axis.Direction();
+ gp_Pnt loc = axis.Location();
+ Standard_Real fMajRad = ellipse->MajorRadius();
+ Standard_Real fMinRad = ellipse->MinorRadius();
+ Standard_Real u1 = trim->FirstParameter();
+ Standard_Real u2 = trim->LastParameter();
+
+ gp_Dir normal = ellipse->Axis().Direction();
+ gp_Dir xdir = ellipse->XAxis().Direction();
+
+ gp_Ax2 xdirref(loc, normal); // this is a reference XY for the ellipse
+
+ Standard_Real fAngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
+
+
+ std::stringstream str;
+ str << "ArcOfEllipse (";
+ str << "MajorRadius : " << fMajRad << ", ";
+ str << "MinorRadius : " << fMinRad << ", ";
+ str << "AngleXU : " << fAngleXU << ", ";
+ str << "Position : (" << loc.X() << ", "<< loc.Y() << ", "<< loc.Z() << "), ";
+ str << "Direction : (" << dir.X() << ", "<< dir.Y() << ", "<< dir.Z() << "), ";
+ str << "Parameter : (" << u1 << ", " << u2 << ")";
+ str << ")";
+
+ return str.str();
+}
+
+PyObject *ArcOfEllipsePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
+{
+ // create a new instance of ArcOfEllipsePy and the Twin object
+ return new ArcOfEllipsePy(new GeomArcOfEllipse);
+}
+
+// constructor method
+int ArcOfEllipsePy::PyInit(PyObject* args, PyObject* kwds)
+{
+ PyObject* o;
+ double u1, u2;
+ PyObject *sense=Py_True;
+ if (PyArg_ParseTuple(args, "O!dd|O!", &(Part::EllipsePy::Type), &o, &u1, &u2, &PyBool_Type, &sense)) {
+ try {
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast
+ (static_cast(o)->getGeomEllipsePtr()->handle());
+ GC_MakeArcOfEllipse arc(ellipse->Elips(), u1, u2, PyObject_IsTrue(sense) ? Standard_True : Standard_False);
+ if (!arc.IsDone()) {
+ PyErr_SetString(PartExceptionOCCError, gce_ErrorStatusText(arc.Status()));
+ return -1;
+ }
+
+ getGeomArcOfEllipsePtr()->setHandle(arc.Value());
+ return 0;
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
+ return -1;
+ }
+ catch (...) {
+ PyErr_SetString(PartExceptionOCCError, "creation of arc failed");
+ return -1;
+ }
+ }
+
+ // All checks failed
+ PyErr_SetString(PyExc_TypeError,
+ "ArcOfEllipse constructor expects an ellipse curve and a parameter range");
+ return -1;
+}
+
+Py::Float ArcOfEllipsePy::getMajorRadius(void) const
+{
+ return Py::Float(getGeomArcOfEllipsePtr()->getMajorRadius());
+}
+
+void ArcOfEllipsePy::setMajorRadius(Py::Float arg)
+{
+ getGeomArcOfEllipsePtr()->setMajorRadius((double)arg);
+}
+
+Py::Float ArcOfEllipsePy::getMinorRadius(void) const
+{
+ return Py::Float(getGeomArcOfEllipsePtr()->getMinorRadius());
+}
+
+void ArcOfEllipsePy::setMinorRadius(Py::Float arg)
+{
+ getGeomArcOfEllipsePtr()->setMinorRadius((double)arg);
+}
+
+Py::Float ArcOfEllipsePy::getAngleXU(void) const
+{
+ return Py::Float(getGeomArcOfEllipsePtr()->getAngleXU());
+}
+
+void ArcOfEllipsePy::setAngleXU(Py::Float arg)
+{
+ getGeomArcOfEllipsePtr()->setAngleXU((double)arg);
+}
+
+Py::Object ArcOfEllipsePy::getCenter(void) const
+{
+ return Py::Vector(getGeomArcOfEllipsePtr()->getCenter());
+}
+
+void ArcOfEllipsePy::setCenter(Py::Object arg)
+{
+ PyObject* p = arg.ptr();
+ if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
+ Base::Vector3d loc = static_cast(p)->value();
+ getGeomArcOfEllipsePtr()->setCenter(loc);
+ }
+ else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
+ Base::Vector3d loc = Base::getVectorFromTuple(p);
+ getGeomArcOfEllipsePtr()->setCenter(loc);
+ }
+ else {
+ std::string error = std::string("type must be 'Vector', not ");
+ error += p->ob_type->tp_name;
+ throw Py::TypeError(error);
+ }
+}
+
+Py::Object ArcOfEllipsePy::getAxis(void) const
+{
+ Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
+ (getGeomArcOfEllipsePtr()->handle());
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
+ gp_Ax1 axis = ellipse->Axis();
+ gp_Dir dir = axis.Direction();
+ return Py::Vector(Base::Vector3d(dir.X(), dir.Y(), dir.Z()));
+}
+
+void ArcOfEllipsePy::setAxis(Py::Object arg)
+{
+ PyObject* p = arg.ptr();
+ Base::Vector3d val;
+ if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
+ val = static_cast(p)->value();
+ }
+ else if (PyTuple_Check(p)) {
+ val = Base::getVectorFromTuple(p);
+ }
+ else {
+ std::string error = std::string("type must be 'Vector', not ");
+ error += p->ob_type->tp_name;
+ throw Py::TypeError(error);
+ }
+
+ Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
+ (getGeomArcOfEllipsePtr()->handle());
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
+ try {
+ gp_Ax1 axis;
+ axis.SetLocation(ellipse->Location());
+ axis.SetDirection(gp_Dir(val.x, val.y, val.z));
+ ellipse->SetAxis(axis);
+ }
+ catch (Standard_Failure) {
+ throw Py::Exception("cannot set axis");
+ }
+}
+
+Py::Object ArcOfEllipsePy::getEllipse(void) const
+{
+ Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
+ (getGeomArcOfEllipsePtr()->handle());
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
+ return Py::Object(new EllipsePy(new GeomEllipse(ellipse)), true);
+}
+
+PyObject *ArcOfEllipsePy::getCustomAttributes(const char* attr) const
+{
+ return 0;
+}
+
+int ArcOfEllipsePy::setCustomAttributes(const char* attr, PyObject *obj)
+{
+ return 0;
+}
diff --git a/src/Mod/Part/App/ArcPy.xml b/src/Mod/Part/App/ArcPy.xml
index 4b13d299c4..f48eab49e0 100644
--- a/src/Mod/Part/App/ArcPy.xml
+++ b/src/Mod/Part/App/ArcPy.xml
@@ -21,5 +21,12 @@
const Geom_Circle & value(void) const {return *getGeom_CirclePtr();}
-->
+
diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt
index 1d17486221..b745a5a2c6 100644
--- a/src/Mod/Part/App/CMakeLists.txt
+++ b/src/Mod/Part/App/CMakeLists.txt
@@ -40,6 +40,7 @@ endif(FREETYPE_FOUND)
generate_from_xml(ArcPy)
generate_from_xml(ArcOfCirclePy)
generate_from_xml(CirclePy)
+generate_from_xml(ArcOfEllipsePy)
generate_from_xml(EllipsePy)
generate_from_xml(HyperbolaPy)
generate_from_xml(ParabolaPy)
@@ -148,6 +149,8 @@ SET(Python_SRCS
ArcOfCirclePyImp.cpp
CirclePy.xml
CirclePyImp.cpp
+ ArcOfEllipsePy.xml
+ ArcOfEllipsePyImp.cpp
EllipsePy.xml
EllipsePyImp.cpp
HyperbolaPy.xml
diff --git a/src/Mod/Part/App/EllipsePy.xml b/src/Mod/Part/App/EllipsePy.xml
index 35a366c024..a5777183ca 100644
--- a/src/Mod/Part/App/EllipsePy.xml
+++ b/src/Mod/Part/App/EllipsePy.xml
@@ -46,6 +46,12 @@
+
+
+ The angle between the X axis and the major axis of the ellipse.
+
+
+
The eccentricity of the ellipse.
diff --git a/src/Mod/Part/App/EllipsePyImp.cpp b/src/Mod/Part/App/EllipsePyImp.cpp
index ede1c21e6d..929a1e0026 100644
--- a/src/Mod/Part/App/EllipsePyImp.cpp
+++ b/src/Mod/Part/App/EllipsePyImp.cpp
@@ -151,6 +151,38 @@ void EllipsePy::setMinorRadius(Py::Float arg)
ellipse->SetMinorRadius((double)arg);
}
+Py::Float EllipsePy::getAngleXU(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());
+
+ gp_Pnt center = ellipse->Axis().Location();
+ gp_Dir normal = ellipse->Axis().Direction();
+ gp_Dir xdir = ellipse->XAxis().Direction();
+
+ gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
+
+ return Py::Float(-xdir.AngleWithRef(xdirref.XDirection(),normal));
+
+}
+
+void EllipsePy::setAngleXU(Py::Float arg)
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());
+
+
+ gp_Pnt center = ellipse->Axis().Location();
+ gp_Dir normal = ellipse->Axis().Direction();
+
+ gp_Ax1 normaxis(center, normal);
+
+ gp_Ax2 xdirref(center, normal);
+
+ xdirref.Rotate(normaxis,arg);
+
+ ellipse->SetPosition(xdirref);
+
+}
+
Py::Float EllipsePy::getEccentricity(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());
diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp
index b0377b2175..91cf9819a4 100644
--- a/src/Mod/Part/App/Geometry.cpp
+++ b/src/Mod/Part/App/Geometry.cpp
@@ -78,6 +78,7 @@
# include
# include
# include
+# include
# include
# include
# include
@@ -91,6 +92,7 @@
#include "EllipsePy.h"
#include "ArcPy.h"
#include "ArcOfCirclePy.h"
+#include "ArcOfEllipsePy.h"
#include "BezierCurvePy.h"
#include "BSplineCurvePy.h"
#include "HyperbolaPy.h"
@@ -888,6 +890,44 @@ void GeomEllipse::setMinorRadius(double Radius)
}
}
+double GeomEllipse::getAngleXU(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle());
+
+ gp_Pnt center = this->myCurve->Axis().Location();
+ gp_Dir normal = this->myCurve->Axis().Direction();
+ gp_Dir xdir = this->myCurve->XAxis().Direction();
+
+
+ gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
+
+ return -xdir.AngleWithRef(xdirref.XDirection(),normal);
+
+}
+
+void GeomEllipse::setAngleXU(double angle)
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle());
+
+ try {
+ gp_Pnt center = this->myCurve->Axis().Location();
+ gp_Dir normal = this->myCurve->Axis().Direction();
+
+ gp_Ax1 normaxis(center, normal);
+
+ gp_Ax2 xdirref(center, normal);
+
+ xdirref.Rotate(normaxis,angle);
+
+ this->myCurve->SetPosition(xdirref);
+
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
// Persistence implementer
unsigned int GeomEllipse::getMemSize (void) const
{
@@ -901,7 +941,13 @@ void GeomEllipse::Save(Base::Writer& writer) const
gp_Pnt center = this->myCurve->Axis().Location();
gp_Dir normal = this->myCurve->Axis().Direction();
-
+ gp_Dir xdir = this->myCurve->XAxis().Direction();
+
+ gp_Ax2 xdirref(center, normal); // this is a reference XY for the ellipse
+
+ double AngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
+
+
writer.Stream()
<< writer.ind()
<< "myCurve->MajorRadius() << "\" "
<< "MinorRadius=\"" << this->myCurve->MinorRadius() << "\" "
+ << "AngleXU=\"" << AngleXU << "\" "
<< "/>" << endl;
}
@@ -921,7 +968,7 @@ void GeomEllipse::Restore(Base::XMLReader& reader)
// read the attributes of the father class
GeomCurve::Restore(reader);
- double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius;
+ double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius,AngleXU;
// read my Element
reader.readElement("Ellipse");
// get the value of my Attribute
@@ -933,12 +980,25 @@ void GeomEllipse::Restore(Base::XMLReader& reader)
NormalZ = reader.getAttributeAsFloat("NormalZ");
MajorRadius = reader.getAttributeAsFloat("MajorRadius");
MinorRadius = reader.getAttributeAsFloat("MinorRadius");
+
+ // This is for backwards compatibility
+ if(reader.hasAttribute("AngleXU"))
+ AngleXU = reader.getAttributeAsFloat("AngleXU");
+ else
+ AngleXU = 0;
// set the read geometry
gp_Pnt p1(CenterX,CenterY,CenterZ);
gp_Dir norm(NormalX,NormalY,NormalZ);
+
+ gp_Ax1 normaxis(p1,norm);
+
+ gp_Ax2 xdir(p1, norm);
+
+ xdir.Rotate(normaxis,AngleXU);
+
try {
- GC_MakeEllipse mc(gp_Ax2(p1, norm), MajorRadius, MinorRadius);
+ GC_MakeEllipse mc(xdir, MajorRadius, MinorRadius);
if (!mc.IsDone())
throw Base::Exception(gce_ErrorStatusText(mc.Status()));
@@ -955,6 +1015,271 @@ PyObject *GeomEllipse::getPyObject(void)
return new EllipsePy((GeomEllipse*)this->clone());
}
+// -------------------------------------------------
+
+TYPESYSTEM_SOURCE(Part::GeomArcOfEllipse,Part::GeomCurve);
+
+GeomArcOfEllipse::GeomArcOfEllipse()
+{
+ Handle_Geom_Ellipse e = new Geom_Ellipse(gp_Elips());
+ this->myCurve = new Geom_TrimmedCurve(e, e->FirstParameter(),e->LastParameter());
+}
+
+GeomArcOfEllipse::GeomArcOfEllipse(const Handle_Geom_Ellipse& e)
+{
+ this->myCurve = new Geom_TrimmedCurve(e, e->FirstParameter(),e->LastParameter());
+}
+
+GeomArcOfEllipse::~GeomArcOfEllipse()
+{
+}
+
+void GeomArcOfEllipse::setHandle(const Handle_Geom_TrimmedCurve& c)
+{
+ Handle_Geom_Ellipse basis = Handle_Geom_Ellipse::DownCast(c->BasisCurve());
+ if (basis.IsNull())
+ Standard_Failure::Raise("Basis curve is not an ellipse");
+ this->myCurve = Handle_Geom_TrimmedCurve::DownCast(c->Copy());
+}
+
+const Handle_Geom_Geometry& GeomArcOfEllipse::handle() const
+{
+ return myCurve;
+}
+
+Geometry *GeomArcOfEllipse::clone(void) const
+{
+ GeomArcOfEllipse* copy = new GeomArcOfEllipse();
+ copy->setHandle(this->myCurve);
+ copy->Construction = this->Construction;
+ return copy;
+}
+
+Base::Vector3d GeomArcOfEllipse::getStartPoint() const
+{
+ gp_Pnt pnt = this->myCurve->StartPoint();
+ return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z());
+}
+
+Base::Vector3d GeomArcOfEllipse::getEndPoint() const
+{
+ gp_Pnt pnt = this->myCurve->EndPoint();
+ return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z());
+}
+
+Base::Vector3d GeomArcOfEllipse::getCenter(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+ gp_Ax1 axis = ellipse->Axis();
+ const gp_Pnt& loc = axis.Location();
+ return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
+}
+
+void GeomArcOfEllipse::setCenter(const Base::Vector3d& Center)
+{
+ gp_Pnt p1(Center.x,Center.y,Center.z);
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+
+ try {
+ ellipse->SetLocation(p1);
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+double GeomArcOfEllipse::getMajorRadius(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+ return ellipse->MajorRadius();
+}
+
+void GeomArcOfEllipse::setMajorRadius(double Radius)
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+
+ try {
+ ellipse->SetMajorRadius(Radius);
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+double GeomArcOfEllipse::getMinorRadius(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+ return ellipse->MinorRadius();
+}
+
+void GeomArcOfEllipse::setMinorRadius(double Radius)
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+
+ try {
+ ellipse->SetMinorRadius(Radius);
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+double GeomArcOfEllipse::getAngleXU(void) const
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+
+ gp_Pnt center = ellipse->Axis().Location();
+ gp_Dir normal = ellipse->Axis().Direction();
+ gp_Dir xdir = ellipse->XAxis().Direction();
+
+ gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
+
+ return -xdir.AngleWithRef(xdirref.XDirection(),normal);
+
+}
+
+void GeomArcOfEllipse::setAngleXU(double angle)
+{
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
+
+ try {
+ gp_Pnt center = ellipse->Axis().Location();
+ gp_Dir normal = ellipse->Axis().Direction();
+
+ gp_Ax1 normaxis(center, normal);
+
+ gp_Ax2 xdirref(center, normal);
+
+ xdirref.Rotate(normaxis,angle);
+
+ ellipse->SetPosition(xdirref);
+
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+void GeomArcOfEllipse::getRange(double& u, double& v) const
+{
+ u = myCurve->FirstParameter();
+ v = myCurve->LastParameter();
+}
+
+void GeomArcOfEllipse::setRange(double u, double v)
+{
+ try {
+ myCurve->SetTrim(u, v);
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+// Persistence implementer
+unsigned int GeomArcOfEllipse::getMemSize (void) const
+{
+ return sizeof(Geom_Ellipse) + 2 *sizeof(double);
+}
+
+void GeomArcOfEllipse::Save(Base::Writer &writer) const
+{
+ // save the attributes of the father class
+ GeomCurve::Save(writer);
+
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(this->myCurve->BasisCurve());
+
+ gp_Pnt center = ellipse->Axis().Location();
+ gp_Dir normal = ellipse->Axis().Direction();
+ gp_Dir xdir = ellipse->XAxis().Direction();
+
+ gp_Ax2 xdirref(center, normal); // this is a reference XY for the ellipse
+
+ double AngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
+
+
+ writer.Stream()
+ << writer.ind()
+ << "MajorRadius() << "\" "
+ << "MinorRadius=\"" << ellipse->MinorRadius() << "\" "
+ << "AngleXU=\"" << AngleXU << "\" "
+ << "StartAngle=\"" << this->myCurve->FirstParameter() << "\" "
+ << "EndAngle=\"" << this->myCurve->LastParameter() << "\" "
+ << "/>" << endl;
+}
+
+void GeomArcOfEllipse::Restore(Base::XMLReader &reader)
+{
+ // read the attributes of the father class
+ GeomCurve::Restore(reader);
+
+ double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius,AngleXU,StartAngle,EndAngle;
+ // read my Element
+ reader.readElement("ArcOfEllipse");
+ // get the value of my Attribute
+ CenterX = reader.getAttributeAsFloat("CenterX");
+ CenterY = reader.getAttributeAsFloat("CenterY");
+ CenterZ = reader.getAttributeAsFloat("CenterZ");
+ NormalX = reader.getAttributeAsFloat("NormalX");
+ NormalY = reader.getAttributeAsFloat("NormalY");
+ NormalZ = reader.getAttributeAsFloat("NormalZ");
+ MajorRadius = reader.getAttributeAsFloat("MajorRadius");
+ MinorRadius = reader.getAttributeAsFloat("MinorRadius");
+ AngleXU = reader.getAttributeAsFloat("AngleXU");
+ StartAngle = reader.getAttributeAsFloat("StartAngle");
+ EndAngle = reader.getAttributeAsFloat("EndAngle");
+
+
+ // set the read geometry
+ gp_Pnt p1(CenterX,CenterY,CenterZ);
+ gp_Dir norm(NormalX,NormalY,NormalZ);
+
+ gp_Ax1 normaxis(p1,norm);
+
+ gp_Ax2 xdir(p1, norm);
+
+ xdir.Rotate(normaxis,AngleXU);
+
+ try {
+ GC_MakeEllipse mc(xdir, MajorRadius, MinorRadius);
+ if (!mc.IsDone())
+ throw Base::Exception(gce_ErrorStatusText(mc.Status()));
+
+ GC_MakeArcOfEllipse ma(mc.Value()->Elips(), StartAngle, EndAngle, 1);
+ if (!ma.IsDone())
+ throw Base::Exception(gce_ErrorStatusText(ma.Status()));
+
+ Handle_Geom_TrimmedCurve tmpcurve = ma.Value();
+ Handle_Geom_Ellipse tmpellipse = Handle_Geom_Ellipse::DownCast(tmpcurve->BasisCurve());
+ Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(this->myCurve->BasisCurve());
+
+ ellipse->SetElips(tmpellipse->Elips());
+ this->myCurve->SetTrim(tmpcurve->FirstParameter(), tmpcurve->LastParameter());
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ throw Base::Exception(e->GetMessageString());
+ }
+}
+
+PyObject *GeomArcOfEllipse::getPyObject(void)
+{
+ return new ArcOfEllipsePy(static_cast(this->clone()));
+}
+
+
// -------------------------------------------------
TYPESYSTEM_SOURCE(Part::GeomHyperbola,Part::GeomCurve);
diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h
index b066cf9d55..3d583bf392 100644
--- a/src/Mod/Part/App/Geometry.h
+++ b/src/Mod/Part/App/Geometry.h
@@ -244,6 +244,8 @@ public:
void setMajorRadius(double Radius);
double getMinorRadius(void) const;
void setMinorRadius(double Radius);
+ double getAngleXU(void) const;
+ void setAngleXU(double angle);
// Persistence implementer ---------------------
virtual unsigned int getMemSize(void) const;
@@ -258,6 +260,45 @@ private:
Handle_Geom_Ellipse myCurve;
};
+class PartExport GeomArcOfEllipse : public GeomCurve
+{
+ TYPESYSTEM_HEADER();
+public:
+ GeomArcOfEllipse();
+ GeomArcOfEllipse(const Handle_Geom_Ellipse&);
+ virtual ~GeomArcOfEllipse();
+ virtual Geometry *clone(void) const;
+
+ Base::Vector3d getStartPoint() const;
+ Base::Vector3d getEndPoint() const;
+
+ Base::Vector3d getCenter(void) const;
+ void setCenter(const Base::Vector3d& Center);
+ double getMajorRadius(void) const;
+ void setMajorRadius(double Radius);
+ double getMinorRadius(void) const;
+ void setMinorRadius(double Radius);
+ double getAngleXU(void) const;
+ void setAngleXU(double angle);
+
+ void getRange(double& u, double& v) const;
+ void setRange(double u, double v);
+
+ // Persistence implementer ---------------------
+ virtual unsigned int getMemSize(void) const;
+ virtual void Save(Base::Writer &/*writer*/) const;
+ virtual void Restore(Base::XMLReader &/*reader*/);
+ // Base implementer ----------------------------
+ virtual PyObject *getPyObject(void);
+
+ void setHandle(const Handle_Geom_TrimmedCurve&);
+ const Handle_Geom_Geometry& handle() const;
+
+private:
+ Handle_Geom_TrimmedCurve myCurve;
+};
+
+
class PartExport GeomHyperbola : public GeomCurve
{
TYPESYSTEM_HEADER();
@@ -340,7 +381,7 @@ public:
Base::Vector3d getStartPoint() const;
Base::Vector3d getEndPoint() const;
- void setPoints(const Base::Vector3d& p1,
+ void setPoints(const Base::Vector3d& p1,
const Base::Vector3d& p2);
// Persistence implementer ---------------------
@@ -674,14 +715,14 @@ bool find2DLinesIntersection(const GeomLineSegment *lineSeg1, const GeomLineSegm
PartExport
bool findFilletCenter(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2, double radius,
Base::Vector3d ¢er);
-PartExport
+PartExport
bool findFilletCenter(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2, double radius,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
Base::Vector3d ¢er);
PartExport
double suggestFilletRadius(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2,
const Base::Vector3d &refPnt1, const Base::Vector3d &refPnt2);
-PartExport
+PartExport
GeomArcOfCircle *createFilletGeometry(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2,
const Base::Vector3d ¢er, double radius);
}
diff --git a/src/Mod/Part/App/Makefile.am b/src/Mod/Part/App/Makefile.am
new file mode 100644
index 0000000000..0d717e96fb
--- /dev/null
+++ b/src/Mod/Part/App/Makefile.am
@@ -0,0 +1,309 @@
+
+lib_LTLIBRARIES=libPart.la Part.la
+
+BUILT_SOURCES=\
+ ArcPy.cpp \
+ ArcOfCirclePy.cpp \
+ ArcOfEllipsePy.cpp \
+ BRepOffsetAPI_MakePipeShellPy.cpp \
+ CirclePy.cpp \
+ EllipsePy.cpp \
+ HyperbolaPy.cpp \
+ ParabolaPy.cpp \
+ OffsetCurvePy.cpp \
+ GeometryPy.cpp \
+ GeometryCurvePy.cpp \
+ GeometrySurfacePy.cpp \
+ LinePy.cpp \
+ PointPy.cpp \
+ BezierCurvePy.cpp \
+ BSplineCurvePy.cpp \
+ PlanePy.cpp \
+ ConePy.cpp \
+ CylinderPy.cpp \
+ SpherePy.cpp \
+ ToroidPy.cpp \
+ BezierSurfacePy.cpp \
+ BSplineSurfacePy.cpp \
+ OffsetSurfacePy.cpp \
+ RectangularTrimmedSurfacePy.cpp \
+ SurfaceOfExtrusionPy.cpp \
+ SurfaceOfRevolutionPy.cpp \
+ PartFeaturePy.cpp \
+ FeaturePythonPy.cpp \
+ Part2DObjectPy.cpp \
+ TopoShapeCompoundPy.cpp \
+ TopoShapeCompSolidPy.cpp \
+ TopoShapeEdgePy.cpp \
+ TopoShapeFacePy.cpp \
+ TopoShapeShellPy.cpp \
+ TopoShapeSolidPy.cpp \
+ TopoShapeVertexPy.cpp \
+ TopoShapeWirePy.cpp \
+ TopoShapePy.cpp
+
+libPart_la_BUILT=\
+ ArcPy.h \
+ ArcOfCirclePy.h \
+ ArcOfEllipsePy.h \
+ BRepOffsetAPI_MakePipeShellPy.h \
+ CirclePy.h \
+ EllipsePy.h \
+ HyperbolaPy.h \
+ ParabolaPy.h \
+ OffsetCurvePy.h \
+ GeometryPy.h \
+ GeometryCurvePy.h \
+ GeometrySurfacePy.h \
+ LinePy.h \
+ PointPy.h \
+ BezierCurvePy.h \
+ BSplineCurvePy.h \
+ PlanePy.h \
+ ConePy.h \
+ CylinderPy.h \
+ SpherePy.h \
+ ToroidPy.h \
+ BezierSurfacePy.h \
+ BSplineSurfacePy.h \
+ OffsetSurfacePy.h \
+ RectangularTrimmedSurfacePy.h \
+ SurfaceOfExtrusionPy.h \
+ SurfaceOfRevolutionPy.h \
+ PartFeaturePy.h \
+ FeaturePythonPy.h \
+ Part2DObjectPy.h \
+ TopoShapeCompoundPy.h \
+ TopoShapeCompSolidPy.h \
+ TopoShapeEdgePy.h \
+ TopoShapeFacePy.h \
+ TopoShapeShellPy.h \
+ TopoShapeSolidPy.h \
+ TopoShapeVertexPy.h \
+ TopoShapeWirePy.h \
+ TopoShapePy.h
+
+libPart_la_SOURCES=\
+ AppPartPy.cpp \
+ ArcPyImp.cpp \
+ ArcOfCirclePyImp.cpp \
+ ArcOfEllipsePyImp.cpp \
+ BRepOffsetAPI_MakePipeShellPyImp.cpp \
+ CirclePyImp.cpp \
+ CrossSection.cpp \
+ EllipsePyImp.cpp \
+ HyperbolaPyImp.cpp \
+ ParabolaPyImp.cpp \
+ OffsetCurvePyImp.cpp \
+ GeometryPyImp.cpp \
+ GeometryCurvePyImp.cpp \
+ GeometrySurfacePyImp.cpp \
+ LinePyImp.cpp \
+ PointPyImp.cpp \
+ BezierCurvePyImp.cpp \
+ BSplineCurvePyImp.cpp \
+ PlanePyImp.cpp \
+ ConePyImp.cpp \
+ CylinderPyImp.cpp \
+ SpherePyImp.cpp \
+ ToroidPyImp.cpp \
+ BezierSurfacePyImp.cpp \
+ BSplineSurfacePyImp.cpp \
+ OffsetSurfacePyImp.cpp \
+ RectangularTrimmedSurfacePyImp.cpp \
+ SurfaceOfExtrusionPyImp.cpp \
+ SurfaceOfRevolutionPyImp.cpp \
+ edgecluster.cpp \
+ FeaturePartBoolean.cpp \
+ FeaturePartBox.cpp \
+ FeaturePartCircle.cpp \
+ FeaturePartCurveNet.cpp \
+ FeaturePartCommon.cpp \
+ FeaturePartCut.cpp \
+ FeaturePartFuse.cpp \
+ FeaturePartImportBrep.cpp \
+ FeaturePartImportIges.cpp \
+ FeaturePartImportStep.cpp \
+ FeaturePartPolygon.cpp \
+ FeaturePartSection.cpp \
+ FeatureChamfer.cpp \
+ FeatureExtrusion.cpp \
+ FeatureFillet.cpp \
+ FeatureGeometrySet.cpp \
+ FeatureRevolution.cpp \
+ FeatureMirroring.cpp \
+ PartFeatures.cpp \
+ Geometry.cpp \
+ ImportIges.cpp \
+ ImportStep.cpp \
+ modelRefine.cpp \
+ CustomFeature.cpp \
+ PartFeature.cpp \
+ PartFeatureReference.cpp \
+ PartFeaturePyImp.cpp \
+ FeaturePythonPyImp.cpp \
+ Part2DObject.cpp \
+ Part2DObjectPyImp.cpp \
+ PreCompiled.cpp \
+ PreCompiled.h \
+ PrimitiveFeature.cpp \
+ ProgressIndicator.cpp \
+ PropertyGeometryList.cpp \
+ PropertyTopoShape.cpp \
+ TopoShape.cpp \
+ TopoShapeCompoundPyImp.cpp \
+ TopoShapeCompSolidPyImp.cpp \
+ TopoShapeEdgePyImp.cpp \
+ TopoShapeFacePyImp.cpp \
+ TopoShapeShellPyImp.cpp \
+ TopoShapeSolidPyImp.cpp \
+ TopoShapeVertexPyImp.cpp \
+ TopoShapeWirePyImp.cpp \
+ TopoShapePyImp.cpp
+
+nodist_include_HEADERS=\
+ $(libPart_la_BUILT)
+
+include_HEADERS=\
+ CrossSection.h \
+ edgecluster.h \
+ FeaturePartBoolean.h \
+ FeaturePartBox.h \
+ FeaturePartCircle.h \
+ FeaturePartCurveNet.h \
+ FeaturePartCommon.h \
+ FeaturePartCut.h \
+ FeaturePartFuse.h \
+ FeaturePartImportBrep.h \
+ FeaturePartImportIges.h \
+ FeaturePartImportStep.h \
+ FeaturePartPolygon.h \
+ FeaturePartSection.h \
+ FeatureChamfer.h \
+ FeatureExtrusion.h \
+ FeatureFillet.h \
+ FeatureGeometrySet.h \
+ FeatureRevolution.h \
+ FeatureMirroring.h \
+ PartFeatures.h \
+ Geometry.h \
+ ImportIges.h \
+ ImportStep.h \
+ modelRefine.h \
+ PartFeature.h \
+ PartFeatureReference.h \
+ CustomFeature.h \
+ Part2DObject.h \
+ PrimitiveFeature.h \
+ ProgressIndicator.h \
+ PropertyGeometryList.h \
+ PropertyTopoShape.h \
+ Tools.h \
+ TopoShape.h
+
+
+# the library search path.
+libPart_la_LDFLAGS = -L../../../Base -L../../../App -L/usr/X11R6/lib -L$(OCC_LIB) $(all_libraries) \
+ -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@
+libPart_la_CPPFLAGS = -DPartExport=
+
+libPart_la_LIBADD = \
+ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ \
+ -l@PYTHON_LIB@ \
+ -lxerces-c \
+ -lFreeCADBase \
+ -lFreeCADApp \
+ -lTKernel \
+ -lTKFillet \
+ -lTKG2d \
+ -lTKG3d \
+ -lTKMath \
+ -lTKMesh \
+ -lTKSTEP \
+ -lTKSTEPAttr \
+ -lTKSTEPBase \
+ -lTKIGES \
+ -lTKSTL \
+ -lTKShHealing \
+ -lTKXSBase \
+ -lTKBool \
+ -lTKBO \
+ -lTKBRep \
+ -lTKTopAlgo \
+ -lTKGeomAlgo \
+ -lTKGeomBase \
+ -lTKOffset \
+ -lTKPrim
+
+%.cpp: %.xml $(top_srcdir)/src/Tools/generateTemplates/templateClassPyExport.py
+ $(PYTHON) $(top_srcdir)/src/Tools/generate.py --outputPath $(@D) $<
+
+#--------------------------------------------------------------------------------------
+# Loader of libPart
+
+Part_la_SOURCES=\
+ AppPart.cpp
+
+# the library search path.
+Part_la_LDFLAGS = $(libPart_la_LDFLAGS) -module -avoid-version
+Part_la_CPPFLAGS = $(libPart_la_CPPFLAGS)
+
+Part_la_LIBADD = \
+ $(libPart_la_LIBADD) \
+ -lPart
+
+Part_la_DEPENDENCIES = libPart.la
+
+#--------------------------------------------------------------------------------------
+
+# set the include path found by configure
+AM_CXXFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src $(all_includes) -I$(OCC_INC)
+
+
+includedir = @includedir@/Mod/Part/App
+libdir = $(prefix)/Mod/Part
+
+CLEANFILES = $(BUILT_SOURCES) $(libPart_la_BUILT)
+
+EXTRA_DIST = \
+ OpenCascadeAll.h \
+ ArcPy.xml \
+ ArcOfCirclePy.xml \
+ ArcOfEllipsePy.xml \
+ BRepOffsetAPI_MakePipeShellPy.xml \
+ CirclePy.xml \
+ EllipsePy.xml \
+ HyperbolaPy.xml \
+ ParabolaPy.xml \
+ OffsetCurvePy.xml \
+ GeometryPy.xml \
+ GeometryCurvePy.xml \
+ GeometrySurfacePy.xml \
+ LinePy.xml \
+ PointPy.xml \
+ BezierCurvePy.xml \
+ BSplineCurvePy.xml \
+ PlanePy.xml \
+ ConePy.xml \
+ CylinderPy.xml \
+ SpherePy.xml \
+ ToroidPy.xml \
+ BezierSurfacePy.xml \
+ BSplineSurfacePy.xml \
+ OffsetSurfacePy.xml \
+ RectangularTrimmedSurfacePy.xml \
+ SurfaceOfExtrusionPy.xml \
+ SurfaceOfRevolutionPy.xml \
+ PartFeaturePy.xml \
+ FeaturePythonPy.xml \
+ Part2DObjectPy.xml \
+ TopoShapePy.xml \
+ TopoShapeCompSolidPy.xml \
+ TopoShapeCompoundPy.xml \
+ TopoShapeEdgePy.xml \
+ TopoShapeFacePy.xml \
+ TopoShapeShellPy.xml \
+ TopoShapeSolidPy.xml \
+ TopoShapeVertexPy.xml \
+ TopoShapeWirePy.xml \
+ CMakeLists.txt
diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp
index 7912f968b9..093d95958c 100644
--- a/src/Mod/PartDesign/Gui/Workbench.cpp
+++ b/src/Mod/PartDesign/Gui/Workbench.cpp
@@ -172,6 +172,10 @@ Gui::MenuItem* Workbench::setupMenuBar() const
Gui::MenuItem* cons = new Gui::MenuItem();
cons->setCommand("Sketcher constraints");
SketcherGui::addSketcherWorkbenchConstraints( *cons );
+
+ Gui::MenuItem* consaccel = new Gui::MenuItem();
+ consaccel->setCommand("Sketcher tools");
+ SketcherGui::addSketcherWorkbenchTools(*consaccel);
Gui::MenuItem* part = new Gui::MenuItem;
root->insertItem(item, part);
@@ -233,6 +237,10 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
cons->setCommand("Sketcher constraints");
SketcherGui::addSketcherWorkbenchConstraints( *cons );
+ Gui::ToolBarItem* consaccel = new Gui::ToolBarItem(root);
+ consaccel->setCommand("Sketcher tools");
+ SketcherGui::addSketcherWorkbenchTools( *consaccel );
+
return root;
}
diff --git a/src/Mod/Sketcher/App/Constraint.cpp b/src/Mod/Sketcher/App/Constraint.cpp
index b9d1c04056..416b2ca9d6 100644
--- a/src/Mod/Sketcher/App/Constraint.cpp
+++ b/src/Mod/Sketcher/App/Constraint.cpp
@@ -43,6 +43,7 @@ const int Constraint::GeoUndef = -2000;
Constraint::Constraint()
: Type(None),
+ AlignmentType(Undef),
Name(""),
Value(0.0),
First(GeoUndef),
@@ -58,6 +59,7 @@ Constraint::Constraint()
Constraint::Constraint(const Constraint& from)
: Type(from.Type),
+ AlignmentType(from.AlignmentType),
Name(from.Name),
Value(from.Value),
First(from.First),
@@ -92,18 +94,22 @@ unsigned int Constraint::getMemSize (void) const
void Constraint::Save (Writer &writer) const
{
- writer.Stream() << writer.ind() << ""
+ writer.Stream() << writer.ind() << "Type==InternalAlignment)
+ writer.Stream()
+ << "InternalAlignmentType=\"" << (int)AlignmentType << "\" ";
+ writer.Stream()
+ << "Value=\"" << Value << "\" "
+ << "First=\"" << First << "\" "
+ << "FirstPos=\"" << (int) FirstPos << "\" "
+ << "Second=\"" << Second << "\" "
+ << "SecondPos=\"" << (int) SecondPos << "\" "
+ << "Third=\"" << Third << "\" "
+ << "ThirdPos=\"" << (int) ThirdPos << "\" "
+ << "LabelDistance=\"" << LabelDistance << "\" "
+ << "LabelPosition=\"" << LabelPosition << "\" />"
<< std::endl;
}
@@ -118,6 +124,11 @@ void Constraint::Restore(XMLReader &reader)
Second = reader.getAttributeAsInteger("Second");
SecondPos = (PointPos) reader.getAttributeAsInteger("SecondPos");
+ if(this->Type==InternalAlignment)
+ AlignmentType = (InternalAlignmentType) reader.getAttributeAsInteger("InternalAlignmentType");
+ else
+ AlignmentType = Undef;
+
// read the third geo group if present
if (reader.hasAttribute("Third")) {
Third = reader.getAttributeAsInteger("Third");
diff --git a/src/Mod/Sketcher/App/Constraint.h b/src/Mod/Sketcher/App/Constraint.h
index 520363a795..18adacbd29 100644
--- a/src/Mod/Sketcher/App/Constraint.h
+++ b/src/Mod/Sketcher/App/Constraint.h
@@ -31,21 +31,30 @@ namespace Sketcher
{
enum ConstraintType {
- None,
- Coincident,
- Horizontal,
- Vertical,
- Parallel,
- Tangent,
- Distance,
- DistanceX,
- DistanceY,
- Angle,
- Perpendicular,
- Radius,
- Equal,
- PointOnObject,
- Symmetric
+ None = 0,
+ Coincident = 1,
+ Horizontal = 2,
+ Vertical = 3,
+ Parallel = 4,
+ Tangent = 5,
+ Distance = 6,
+ DistanceX = 7,
+ DistanceY = 8,
+ Angle = 9,
+ Perpendicular = 10,
+ Radius = 11,
+ Equal = 12,
+ PointOnObject = 13,
+ Symmetric = 14,
+ InternalAlignment = 15
+};
+
+enum InternalAlignmentType {
+ Undef = 0,
+ EllipseMajorDiameter = 1,
+ EllipseMinorDiameter = 2,
+ EllipseFocus1 = 3,
+ EllipseFocus2 = 4
};
/// define if you want to use the end or start point
@@ -74,6 +83,7 @@ public:
public:
ConstraintType Type;
+ InternalAlignmentType AlignmentType;
std::string Name;
double Value;
int First;
diff --git a/src/Mod/Sketcher/App/ConstraintPyImp.cpp b/src/Mod/Sketcher/App/ConstraintPyImp.cpp
index 1c235cb1d7..bef00372f6 100644
--- a/src/Mod/Sketcher/App/ConstraintPyImp.cpp
+++ b/src/Mod/Sketcher/App/ConstraintPyImp.cpp
@@ -93,6 +93,20 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
this->getConstraintPtr()->Type = Equal;
valid = true;
}
+ else if (strstr(ConstraintType,"InternalAlignment") != NULL) {
+ this->getConstraintPtr()->Type = InternalAlignment;
+
+ valid = true;
+ if(strstr(ConstraintType,"EllipseMajorDiameter") != NULL)
+ this->getConstraintPtr()->AlignmentType=EllipseMajorDiameter;
+ else if(strstr(ConstraintType,"EllipseMinorDiameter") != NULL)
+ this->getConstraintPtr()->AlignmentType=EllipseMinorDiameter;
+ else {
+ this->getConstraintPtr()->AlignmentType=Undef;
+ valid = false;
+ }
+ }
+
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
@@ -155,6 +169,20 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
this->getConstraintPtr()->Type = PointOnObject;
valid = true;
}
+ else if (strstr(ConstraintType,"InternalAlignment") != NULL) {
+ this->getConstraintPtr()->Type = InternalAlignment;
+
+ valid = true;
+
+ if(strstr(ConstraintType,"EllipseFocus1") != NULL)
+ this->getConstraintPtr()->AlignmentType=EllipseFocus1;
+ else if(strstr(ConstraintType,"EllipseFocus2") != NULL)
+ this->getConstraintPtr()->AlignmentType=EllipseFocus2;
+ else {
+ this->getConstraintPtr()->AlignmentType=Undef;
+ valid = false;
+ }
+ }
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
@@ -340,17 +368,27 @@ std::string ConstraintPy::representation(void) const
std::stringstream result;
result << "getConstraintPtr()->Type) {
- case None : result << "'None'>";break;
- case DistanceX : result << "'DistanceX'>";break;
- case DistanceY : result << "'DistanceY'>";break;
- case Coincident : result << "'Coincident'>";break;
- case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
- case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
- case Parallel : result << "'Parallel'>";break;
- case Tangent : result << "'Tangent'>";break;
- case Distance : result << "'Distance'>";break;
- case Angle : result << "'Angle'>";break;
- default : result << "'?'>";break;
+ case None : result << "'None'>";break;
+ case DistanceX : result << "'DistanceX'>";break;
+ case DistanceY : result << "'DistanceY'>";break;
+ case Coincident : result << "'Coincident'>";break;
+ case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
+ case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
+ case Parallel : result << "'Parallel'>";break;
+ case Tangent : result << "'Tangent'>";break;
+ case Distance : result << "'Distance'>";break;
+ case Angle : result << "'Angle'>";break;
+ case InternalAlignment :
+ switch(this->getConstraintPtr()->AlignmentType) {
+ case Undef : result << "'InternalAlignment:Undef'>";break;
+ case EllipseMajorDiameter : result << "'InternalAlignment:EllipseMajorDiameter'>";break;
+ case EllipseMinorDiameter : result << "'InternalAlignment:EllipseMinorDiameter'>";break;
+ case EllipseFocus1 : result << "'InternalAlignment:EllipseFocus1'>";break;
+ case EllipseFocus2 : result << "'InternalAlignment:EllipseFocus2'>";break;
+ default : result << "'InternalAlignment:?'>";break;
+ }
+ break;
+ default : result << "'?'>";break;
}
return result.str();
}
diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp
index fa59c0e57b..7faf6470b4 100644
--- a/src/Mod/Sketcher/App/Sketch.cpp
+++ b/src/Mod/Sketcher/App/Sketch.cpp
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -78,6 +79,8 @@ void Sketch::clear(void)
Lines.clear();
Arcs.clear();
Circles.clear();
+ Ellipses.clear();
+ ArcsOfEllipse.clear();
// deleting the doubles allocated with new
for (std::vector::iterator it = Parameters.begin(); it != Parameters.end(); ++it)
@@ -142,6 +145,8 @@ const char* nameByType(Sketch::GeoType type)
return "circle";
case Sketch::Ellipse:
return "ellipse";
+ case Sketch::ArcOfEllipse:
+ return "arcofellipse";
case Sketch::None:
default:
return "unknown";
@@ -164,10 +169,18 @@ int Sketch::addGeometry(const Part::Geometry *geo, bool fixed)
const GeomCircle *circle = dynamic_cast(geo);
// create the definition struct for that geom
return addCircle(*circle, fixed);
+ } else if (geo->getTypeId() == GeomEllipse::getClassTypeId()) { // add a ellipse
+ const GeomEllipse *ellipse = dynamic_cast(geo);
+ // create the definition struct for that geom
+ return addEllipse(*ellipse, fixed);
} else if (geo->getTypeId() == GeomArcOfCircle::getClassTypeId()) { // add an arc
const GeomArcOfCircle *aoc = dynamic_cast(geo);
// create the definition struct for that geom
return addArc(*aoc, fixed);
+ } else if (geo->getTypeId() == GeomArcOfEllipse::getClassTypeId()) { // add an arc
+ const GeomArcOfEllipse *aoe = dynamic_cast(geo);
+ // create the definition struct for that geom
+ return addArcOfEllipse(*aoe, fixed);
} else {
Base::Exception("Sketch::addGeometry(): Unknown or unsupported type added to a sketch");
return 0;
@@ -341,6 +354,99 @@ int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed)
return Geoms.size()-1;
}
+
+
+int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed)
+{
+ std::vector ¶ms = fixed ? FixParameters : Parameters;
+
+ // create our own copy
+ GeomArcOfEllipse *aoe = static_cast(ellipseSegment.clone());
+ // create the definition struct for that geom
+ GeoDef def;
+ def.geo = aoe;
+ def.type = ArcOfEllipse;
+
+ Base::Vector3d center = aoe->getCenter();
+ Base::Vector3d startPnt = aoe->getStartPoint();
+ Base::Vector3d endPnt = aoe->getEndPoint();
+ double radmaj = aoe->getMajorRadius();
+ double radmin = aoe->getMinorRadius();
+ double phi = aoe->getAngleXU();
+
+ double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin);
+ // solver parameters
+ Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x
+
+ double startAngle, endAngle;
+ aoe->getRange(startAngle, endAngle);
+
+ GCS::Point p1, p2, p3;
+ GCS::Point f1;
+
+ params.push_back(new double(startPnt.x));
+ params.push_back(new double(startPnt.y));
+ p1.x = params[params.size()-2];
+ p1.y = params[params.size()-1];
+
+ params.push_back(new double(endPnt.x));
+ params.push_back(new double(endPnt.y));
+ p2.x = params[params.size()-2];
+ p2.y = params[params.size()-1];
+
+ params.push_back(new double(center.x));
+ params.push_back(new double(center.y));
+ p3.x = params[params.size()-2];
+ p3.y = params[params.size()-1];
+
+ params.push_back(new double(focus1.x));
+ params.push_back(new double(focus1.y));
+ f1.x = params[params.size()-2];
+ f1.y = params[params.size()-1];
+
+ def.startPointId = Points.size();
+ Points.push_back(p1);
+ def.endPointId = Points.size();
+ Points.push_back(p2);
+ def.midPointId = Points.size();
+ Points.push_back(p3);
+
+ Points.push_back(f1);
+
+
+ // add the radius parameters
+ params.push_back(new double(radmin));
+ double *rmin = params[params.size()-1];
+ params.push_back(new double(startAngle));
+ double *a1 = params[params.size()-1];
+ params.push_back(new double(endAngle));
+ double *a2 = params[params.size()-1];
+
+
+
+ // set the arc for later constraints
+ GCS::ArcOfEllipse a;
+ a.start = p1;
+ a.end = p2;
+ a.center = p3;
+ a.focus1 = f1;
+ a.radmin = rmin;
+ a.startAngle = a1;
+ a.endAngle = a2;
+ def.index = ArcsOfEllipse.size();
+ ArcsOfEllipse.push_back(a);
+
+ // store complete set
+ Geoms.push_back(def);
+
+ // arcs require an ArcRules constraint for the end points
+ if (!fixed)
+ GCSsys.addConstraintArcOfEllipseRules(a); // TODO: ArcOfEllipse implementation.
+
+ // return the position of the newly added geometry
+ return Geoms.size()-1;
+}
+
int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
{
std::vector ¶ms = fixed ? FixParameters : Parameters;
@@ -384,8 +490,66 @@ int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
return Geoms.size()-1;
}
-int Sketch::addEllipse(const Part::GeomEllipse &ellipse, bool fixed)
+int Sketch::addEllipse(const Part::GeomEllipse &elip, bool fixed)
{
+ // TODO: Ellipse
+ std::vector ¶ms = fixed ? FixParameters : Parameters;
+
+ // create our own copy
+ GeomEllipse *elips = static_cast(elip.clone());
+ // create the definition struct for that geom
+ GeoDef def;
+ def.geo = elips;
+ def.type = Ellipse;
+
+ Base::Vector3d center = elips->getCenter();
+ double radmaj = elips->getMajorRadius();
+ double radmin = elips->getMinorRadius();
+ double phi = elips->getAngleXU();
+
+ double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin);
+ // solver parameters
+ Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x
+ //double *radmin;
+
+ GCS::Point c;
+
+ params.push_back(new double(center.x));
+ params.push_back(new double(center.y));
+ c.x = params[params.size()-2];
+ c.y = params[params.size()-1];
+
+ def.midPointId = Points.size(); // this takes midPointId+1
+ Points.push_back(c);
+
+ GCS::Point f1;
+
+ params.push_back(new double(focus1.x));
+ params.push_back(new double(focus1.y));
+ f1.x = params[params.size()-2];
+ f1.y = params[params.size()-1];
+
+ //def.midPointId = Points.size();
+ Points.push_back(f1);
+
+
+
+ // add the radius parameters
+ params.push_back(new double(radmin));
+ double *rmin = params[params.size()-1];
+
+ // set the ellipse for later constraints
+ GCS::Ellipse e;
+ e.focus1 = f1;
+ e.center = c;
+ e.radmin = rmin;
+
+ def.index = Ellipses.size();
+ Ellipses.push_back(e);
+
+ // store complete set
+ Geoms.push_back(def);
+
// return the position of the newly added geometry
return Geoms.size()-1;
}
@@ -422,7 +586,11 @@ Py::Tuple Sketch::getPyGeometry(void) const
} else if (it->type == Ellipse) {
GeomEllipse *ellipse = dynamic_cast(it->geo->clone());
tuple[i] = Py::asObject(new EllipsePy(ellipse));
- } else {
+ } else if (it->type == ArcOfEllipse) {
+ GeomArcOfEllipse *ellipse = dynamic_cast(it->geo->clone());
+ tuple[i] = Py::asObject(new ArcOfEllipsePy(ellipse));
+ }
+ else {
// not implemented type in the sketch!
}
}
@@ -549,6 +717,22 @@ int Sketch::addConstraint(const Constraint *constraint)
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
constraint->Second,constraint->SecondPos,constraint->Third);
break;
+ case InternalAlignment:
+ switch(constraint->AlignmentType) {
+ case EllipseMajorDiameter:
+ rtn = addInternalAlignmentEllipseMajorDiameter(constraint->First,constraint->Second);
+ break;
+ case EllipseMinorDiameter:
+ rtn = addInternalAlignmentEllipseMinorDiameter(constraint->First,constraint->Second);
+ break;
+ case EllipseFocus1:
+ rtn = addInternalAlignmentEllipseFocus1(constraint->First,constraint->Second);
+ break;
+ case EllipseFocus2:
+ rtn = addInternalAlignmentEllipseFocus2(constraint->First,constraint->Second);
+ break;
+ }
+ break;
case None:
break;
}
@@ -861,6 +1045,15 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnLine(p2, l1, tag);
return ConstraintsCounter;
}
+ else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: Ellipse
+ GCS::Ellipse &c2 = Ellipses[Geoms[geoId2].index];
+ GCS::Point &p2 = Points[Geoms[geoId2].midPointId];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintPointOnEllipse(p1, c2, tag);
+ GCSsys.addConstraintPointOnLine(p2, l1, tag);
+ return ConstraintsCounter;
+ }
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -871,7 +1064,8 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnLine(a1.center, l2, tag);
return ConstraintsCounter;
}
- else if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle) {
+ else if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle || Geoms[geoId2].type == Ellipse) {
+ // TODO: ellipse real implementation
int tag = ++ConstraintsCounter;
GCS::Point ¢er = Points[Geoms[geoId2].midPointId];
double *radius;
@@ -879,10 +1073,15 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
radius = a2.rad;
}
- else {
+ else if (Geoms[geoId2].type == Circle) {
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
radius = c2.rad;
}
+ else {
+ // TODO: Ellipse
+ GCS::Ellipse &c2 = Ellipses[Geoms[geoId2].index];
+ radius = c2.radmin;
+ }
if (pos1 == start)
GCSsys.addConstraintPerpendicularCircle2Arc(center, radius, a1, tag);
else if (pos1 == end)
@@ -1026,6 +1225,18 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(l, c, tag);
return ConstraintsCounter;
+ } else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: real implementation
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(l, e, tag);
+ return ConstraintsCounter;
+ } else if (Geoms[geoId2].type == ArcOfEllipse) {
+ // TODO: real implementation
+ GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(l, a, tag);
+ return ConstraintsCounter;
}
} else if (Geoms[geoId1].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId1].index];
@@ -1034,12 +1245,33 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, c2, tag);
return ConstraintsCounter;
- } else if (Geoms[geoId2].type == Arc) {
+ } else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: real implementation
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(e, c, tag);
+ return ConstraintsCounter;
+ }
+ else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
}
+ } else if (Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e = Ellipses[Geoms[geoId1].index];
+ // TODO: Ellipse
+ if (Geoms[geoId2].type == Circle) {
+ GCS::Circle &c = Circles[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(e, c, tag);
+ return ConstraintsCounter;
+ } else if (Geoms[geoId2].type == Arc) {
+ GCS::Arc &a = Arcs[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(e, a, tag);
+ return ConstraintsCounter;
+ }
} else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId1].index];
if (Geoms[geoId2].type == Circle) {
@@ -1047,6 +1279,12 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
+ } else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: Ellipse
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangent(e, a, tag);
+ return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
@@ -1096,6 +1334,14 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintTangent(l1, c2, tag);
return ConstraintsCounter;
}
+ else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: Ellipse
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintPointOnEllipse(p1, e, tag);
+ GCSsys.addConstraintTangent(l1, e, tag);
+ return ConstraintsCounter;
+ }
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -1125,6 +1371,19 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintTangentArc2Circle(a1, c2, tag);
return ConstraintsCounter;
}
+ } else if (Geoms[geoId2].type == Ellipse) {
+ // TODO: Ellipse
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ if (pos1 == start) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentEllipse2Arc(e, a1, tag);
+ return ConstraintsCounter;
+ }
+ else if (pos1 == end) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentArc2Ellipse(a1, e, tag);
+ return ConstraintsCounter;
+ }
}
}
return -1;
@@ -1198,6 +1457,35 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
else
return -1;
}
+ if (Geoms[geoId2].type == ArcOfEllipse) {
+ GCS::ArcOfEllipse &a2 = ArcsOfEllipse[Geoms[geoId2].index];
+ if (pos2 == start) {
+ if (pos1 == start) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentLine2ArcOfEllipse(l1.p2, l1.p1, l1, a2, tag);
+ return ConstraintsCounter;
+ }
+ else if (pos1 == end) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentLine2ArcOfEllipse(l1.p1, l1.p2, l1, a2, tag);
+ return ConstraintsCounter;
+ }
+ }
+ else if (pos2 == end) {
+ if (pos1 == start) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentArcOfEllipse2Line(a2, l1, l1.p1, l1.p2, tag);
+ return ConstraintsCounter;
+ }
+ else if (pos1 == end) {
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintTangentArcOfEllipse2Line(a2, l1, l1.p2, l1.p1, tag);
+ return ConstraintsCounter;
+ }
+ }
+ else
+ return -1;
+ }
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -1309,7 +1597,7 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo
return -1;
}
-int Sketch::addRadiusConstraint(int geoId, double value)
+int Sketch::addRadiusConstraint(int geoId, double value, int radiusnumber)
{
geoId = checkGeoId(geoId);
@@ -1448,6 +1736,18 @@ int Sketch::addEqualConstraint(int geoId1, int geoId2)
else
std::swap(geoId1, geoId2);
}
+ // TODO: Ellipse
+ if (Geoms[geoId2].type == Ellipse) {
+ if (Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
+ GCS::Ellipse &e2 = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintEqualRadii(e1, e2, tag);
+ return ConstraintsCounter;
+ }
+ else
+ std::swap(geoId1, geoId2);
+ }
if (Geoms[geoId1].type == Circle) {
GCS::Circle &c1 = Circles[Geoms[geoId1].index];
@@ -1502,6 +1802,18 @@ int Sketch::addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnCircle(p1, c, tag);
return ConstraintsCounter;
}
+ else if (Geoms[geoId2].type == Ellipse) {
+ GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintPointOnEllipse(p1, e, tag);
+ return ConstraintsCounter;
+ }
+ else if (Geoms[geoId2].type == ArcOfEllipse) {
+ GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId2].index];
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintPointOnArcOfEllipse(p1, a, tag);
+ return ConstraintsCounter;
+ }
}
return -1;
}
@@ -1555,6 +1867,167 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP
return -1;
}
+int Sketch::addInternalAlignmentEllipseMajorDiameter(int geoId1, int geoId2)
+{
+ std::swap(geoId1, geoId2);
+
+ geoId1 = checkGeoId(geoId1);
+ geoId2 = checkGeoId(geoId2);
+
+ if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
+ return -1;
+ if (Geoms[geoId2].type != Line)
+ return -1;
+
+ int pointId1 = getPointId(geoId2, start);
+ int pointId2 = getPointId(geoId2, end);
+
+ if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
+ pointId2 >= 0 && pointId2 < int(Points.size())) {
+ GCS::Point &p1 = Points[pointId1];
+ GCS::Point &p2 = Points[pointId2];
+
+ if(Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
+
+ // constraints
+ // 1. start point with ellipse -a
+ // 2. end point with ellipse +a
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseMajorDiameter(e1, p1, p2, tag);
+ return ConstraintsCounter;
+
+ }
+ else {
+ GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
+
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseMajorDiameter(a1, p1, p2, tag);
+ return ConstraintsCounter;
+ }
+ }
+ return -1;
+}
+
+int Sketch::addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2)
+{
+ std::swap(geoId1, geoId2);
+
+ geoId1 = checkGeoId(geoId1);
+ geoId2 = checkGeoId(geoId2);
+
+ if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
+ return -1;
+ if (Geoms[geoId2].type != Line)
+ return -1;
+
+ int pointId1 = getPointId(geoId2, start);
+ int pointId2 = getPointId(geoId2, end);
+
+ if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
+ pointId2 >= 0 && pointId2 < int(Points.size())) {
+ GCS::Point &p1 = Points[pointId1];
+ GCS::Point &p2 = Points[pointId2];
+
+ if(Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
+
+ // constraints
+ // 1. start point with ellipse -a
+ // 2. end point with ellipse +a
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseMinorDiameter(e1, p1, p2, tag);
+ return ConstraintsCounter;
+ }
+ else {
+ GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
+
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseMinorDiameter(a1, p1, p2, tag);
+ return ConstraintsCounter;
+ }
+ }
+ return -1;
+}
+
+int Sketch::addInternalAlignmentEllipseFocus1(int geoId1, int geoId2)
+{
+ std::swap(geoId1, geoId2);
+
+ geoId1 = checkGeoId(geoId1);
+ geoId2 = checkGeoId(geoId2);
+
+ if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
+ return -1;
+ if (Geoms[geoId2].type != Point)
+ return -1;
+
+ int pointId1 = getPointId(geoId2, start);
+
+ if (pointId1 >= 0 && pointId1 < int(Points.size())) {
+ GCS::Point &p1 = Points[pointId1];
+
+ if(Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
+
+ // constraints
+ // 1. start point with ellipse -a
+ // 2. end point with ellipse +a
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseFocus1(e1, p1, tag);
+ return ConstraintsCounter;
+ }
+ else {
+ GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
+
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseFocus1(a1, p1, tag);
+ return ConstraintsCounter;
+ }
+ }
+ return -1;
+}
+
+
+int Sketch::addInternalAlignmentEllipseFocus2(int geoId1, int geoId2)
+{
+ std::swap(geoId1, geoId2);
+
+ geoId1 = checkGeoId(geoId1);
+ geoId2 = checkGeoId(geoId2);
+
+ if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
+ return -1;
+ if (Geoms[geoId2].type != Point)
+ return -1;
+
+ int pointId1 = getPointId(geoId2, start);
+
+ if (pointId1 >= 0 && pointId1 < int(Points.size())) {
+ GCS::Point &p1 = Points[pointId1];
+
+ if(Geoms[geoId1].type == Ellipse) {
+ GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
+
+ // constraints
+ // 1. start point with ellipse -a
+ // 2. end point with ellipse +a
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseFocus2(e1, p1, tag);
+ return ConstraintsCounter;
+ }
+ else {
+ GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
+
+ int tag = ++ConstraintsCounter;
+ GCSsys.addConstraintInternalAlignmentEllipseFocus2(a1, p1, tag);
+ return ConstraintsCounter;
+ }
+ }
+ return -1;
+}
+
+
bool Sketch::updateGeometry()
{
int i=0;
@@ -1589,6 +2062,25 @@ bool Sketch::updateGeometry()
);
aoc->setRadius(*myArc.rad);
aoc->setRange(*myArc.startAngle, *myArc.endAngle);
+ } else if (it->type == ArcOfEllipse) {
+ GCS::ArcOfEllipse &myArc = ArcsOfEllipse[it->index];
+
+ GeomArcOfEllipse *aoe = dynamic_cast(it->geo);
+
+ Base::Vector3d center = Vector3d(*Points[it->midPointId].x, *Points[it->midPointId].y, 0.0);
+ Base::Vector3d f1 = Vector3d(*Points[it->midPointId+1].x, *Points[it->midPointId+1].y, 0.0);
+ double radmin = *ArcsOfEllipse[it->index].radmin;
+
+ Base::Vector3d fd=f1-center;
+ double radmaj = sqrt(fd*fd+radmin*radmin);
+
+ double phi = atan2(fd.y,fd.x);
+
+ aoe->setCenter(center);
+ aoe->setMajorRadius(radmaj);
+ aoe->setMinorRadius(radmin);
+ aoe->setAngleXU(phi);
+ aoe->setRange(*myArc.startAngle, *myArc.endAngle);
} else if (it->type == Circle) {
GeomCircle *circ = dynamic_cast(it->geo);
circ->setCenter(Vector3d(*Points[it->midPointId].x,
@@ -1596,6 +2088,23 @@ bool Sketch::updateGeometry()
0.0)
);
circ->setRadius(*Circles[it->index].rad);
+ } else if (it->type == Ellipse) {
+ // TODO: Ellipse
+ GeomEllipse *ellipse = dynamic_cast(it->geo);
+
+ Base::Vector3d center = Vector3d(*Points[it->midPointId].x, *Points[it->midPointId].y, 0.0);
+ Base::Vector3d f1 = Vector3d(*Points[it->midPointId+1].x, *Points[it->midPointId+1].y, 0.0);
+ double radmin = *Ellipses[it->index].radmin;
+
+ Base::Vector3d fd=f1-center;
+ double radmaj = sqrt(fd*fd+radmin*radmin);
+
+ double phi = atan2(fd.y,fd.x);
+
+ ellipse->setCenter(center);
+ ellipse->setMajorRadius(radmaj);
+ ellipse->setMinorRadius(radmin);
+ ellipse->setAngleXU(phi);
}
} catch (Base::Exception e) {
Base::Console().Error("Updating geometry: Error build geometry(%d): %s\n",
@@ -1771,6 +2280,72 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
GCSsys.rescaleConstraint(i-1, 0.01);
GCSsys.rescaleConstraint(i, 0.01);
}
+ } else if (Geoms[geoId].type == Ellipse) {
+ // TODO: Ellipse
+ GCS::Point ¢er = Points[Geoms[geoId].midPointId];
+ GCS::Point p0,p1;
+ if (pos == mid) {
+ MoveParameters.resize(2); // cx,cy
+ p0.x = &MoveParameters[0];
+ p0.y = &MoveParameters[1];
+ *p0.x = *center.x;
+ *p0.y = *center.y;
+ GCSsys.addConstraintP2PCoincident(p0,center,-1);
+ } else if (pos == none) {
+ // TODO: Ellipse
+ MoveParameters.resize(4); // x,y,cx,cy
+ GCS::Ellipse &e = Ellipses[Geoms[geoId].index];
+ p0.x = &MoveParameters[0];
+ p0.y = &MoveParameters[1];
+ *p0.x = *center.x;
+ *p0.y = *center.y + *e.radmin;
+ GCSsys.addConstraintPointOnEllipse(p0,e,-1);
+ p1.x = &MoveParameters[2];
+ p1.y = &MoveParameters[3];
+ *p1.x = *center.x;
+ *p1.y = *center.y;
+ int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
+ GCSsys.rescaleConstraint(i-1, 0.01);
+ GCSsys.rescaleConstraint(i, 0.01);
+ }
+ } else if (Geoms[geoId].type == ArcOfEllipse) {
+ // TODO: ArcOfEllipse
+ GCS::Point ¢er = Points[Geoms[geoId].midPointId];
+ GCS::Point p0,p1;
+ if (pos == mid) {
+ MoveParameters.resize(2); // cx,cy
+ p0.x = &MoveParameters[0];
+ p0.y = &MoveParameters[1];
+ *p0.x = *center.x;
+ *p0.y = *center.y;
+ GCSsys.addConstraintP2PCoincident(p0,center,-1);
+ } else if (pos == start || pos == end || pos == none) {
+ // TODO: Ellipse
+ MoveParameters.resize(4); // x,y,cx,cy
+ if (pos == start || pos == end) {
+ GCS::Point &p = (pos == start) ? Points[Geoms[geoId].startPointId]
+ : Points[Geoms[geoId].endPointId];;
+ p0.x = &MoveParameters[0];
+ p0.y = &MoveParameters[1];
+ *p0.x = *p.x;
+ *p0.y = *p.y;
+ GCSsys.addConstraintP2PCoincident(p0,p,-1);
+ } else if (pos == none) {
+ GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId].index];
+ p0.x = &MoveParameters[0];
+ p0.y = &MoveParameters[1];
+ *p0.x = *center.x;
+ *p0.y = *center.y + *a.radmin;
+ GCSsys.addConstraintPointOnArcOfEllipse(p0,a,-1);
+ }
+ p1.x = &MoveParameters[2];
+ p1.y = &MoveParameters[3];
+ *p1.x = *center.x;
+ *p1.y = *center.y;
+ int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
+ GCSsys.rescaleConstraint(i-1, 0.01);
+ GCSsys.rescaleConstraint(i, 0.01);
+ }
} else if (Geoms[geoId].type == Arc) {
GCS::Point ¢er = Points[Geoms[geoId].midPointId];
GCS::Point p0,p1;
@@ -1858,6 +2433,16 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
MoveParameters[0] = toPoint.x;
MoveParameters[1] = toPoint.y;
}
+ } else if (Geoms[geoId].type == Ellipse) {
+ if (pos == mid || pos == none) {
+ MoveParameters[0] = toPoint.x;
+ MoveParameters[1] = toPoint.y;
+ }
+ } else if (Geoms[geoId].type == ArcOfEllipse) {
+ if (pos == start || pos == end || pos == mid || pos == none) {
+ MoveParameters[0] = toPoint.x;
+ MoveParameters[1] = toPoint.y;
+ }
}
return solve();
@@ -1886,6 +2471,33 @@ int Sketch::getPointId(int geoId, PointPos pos) const
return -1;
}
+int Sketch::getVisiblePointId(int geoId, PointPos pos) const
+{
+ // do a range check first
+ if (geoId < 0 || geoId >= (int)Geoms.size())
+ return -1;
+
+ int invisiblepoints = 0;
+ int i;
+
+ // calculate the number of points in the solver that are not visible in the UI
+ for(i=0;i
#include
#include "Constraint.h"
-
-#include "freegcs/GCS.h"
+
+#include "freegcs/GCS.h"
#include
@@ -82,6 +82,8 @@ public:
/// retrieves the index of a point
int getPointId(int geoId, PointPos pos) const;
+ int getVisiblePointId(int geoId, PointPos pos) const;
+
/// retrieves a point
Base::Vector3d getPoint(int geoId, PointPos pos);
@@ -119,8 +121,10 @@ public:
int addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed=false);
/// add a circle
int addCircle(const Part::GeomCircle &circle, bool fixed=false);
- /// add a ellipse
+ /// add an ellipse
int addEllipse(const Part::GeomEllipse &ellipse, bool fixed=false);
+ /// add an arc of ellipse
+ int addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed=false);
//@}
@@ -163,11 +167,14 @@ public:
int addTangentConstraint(int geoId1, PointPos pos1, int geoId2);
int addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2);
/// add a radius constraint on a circle or an arc
- int addRadiusConstraint(int geoId, double value);
+ int addRadiusConstraint(int geoId, double value, int radiusnumber=0);
/// add an angle constraint on a line or between two lines
int addAngleConstraint(int geoId, double value);
int addAngleConstraint(int geoId1, int geoId2, double value);
int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value);
+ /// add ellipse XDir axis angle constraint with respect to XAxis or a lines
+ int addEllipseAngleXUConstraint(int geoId, double value);
+ int addEllipseAngleXUConstraint(int geoId1, int geoId2, double value);
/// add an equal length or radius constraints between two lines or between circles and arcs
int addEqualConstraint(int geoId1, int geoId2);
/// add a point on line constraint
@@ -177,14 +184,24 @@ public:
/// add a symmetric constraint between three points, the last point is in the middle of the first two
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3);
//@}
-
+
+ /// Internal Alignment constraints
+ //@{
+ /// add InternalAlignmentEllipseMajorDiameter to a line and an ellipse
+ int addInternalAlignmentEllipseMajorDiameter(int geoId1, int geoId2);
+ int addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2);
+ int addInternalAlignmentEllipseFocus1(int geoId1, int geoId2);
+ int addInternalAlignmentEllipseFocus2(int geoId1, int geoId2);
+ //@}
+
enum GeoType {
None = 0,
Point = 1, // 1 Point(start), 2 Parameters(x,y)
Line = 2, // 2 Points(start,end), 4 Parameters(x1,y1,x2,y2)
Arc = 3, // 3 Points(start,end,mid), (4)+5 Parameters((x1,y1,x2,y2),x,y,r,a1,a2)
Circle = 4, // 1 Point(mid), 3 Parameters(x,y,r)
- Ellipse = 5
+ Ellipse = 5, // 1 Point(mid), 5 Parameters(x,y,r1,r2,phi) phi=angle xaxis of elipse with respect of sketch xaxis// TODO: Ellipse
+ ArcOfEllipse = 6
};
float SolveTime;
@@ -217,6 +234,8 @@ protected:
std::vector Lines;
std::vector Arcs;
std::vector Circles;
+ std::vector Ellipses;
+ std::vector ArcsOfEllipse;
bool isInitMove;
bool isFine;
diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp
index 05e2f9b485..a49a346b13 100644
--- a/src/Mod/Sketcher/App/SketchObject.cpp
+++ b/src/Mod/Sketcher/App/SketchObject.cpp
@@ -257,6 +257,10 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
const Part::GeomCircle *circle = dynamic_cast(geo);
if (PosId == mid)
return circle->getCenter();
+ } else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ const Part::GeomEllipse *ellipse = dynamic_cast(geo);
+ if (PosId == mid)
+ return ellipse->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = dynamic_cast(geo);
if (PosId == start)
@@ -265,6 +269,14 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
return aoc->getEndPoint();
else if (PosId == mid)
return aoc->getCenter();
+ } else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
+ const Part::GeomArcOfEllipse *aoc = dynamic_cast(geo);
+ if (PosId == start)
+ return aoc->getStartPoint();
+ else if (PosId == end)
+ return aoc->getEndPoint();
+ else if (PosId == mid)
+ return aoc->getCenter();
}
return Base::Vector3d();
@@ -944,7 +956,9 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
return 0;
}
-
+ } else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ // TODO: Ellipse Trim support
+ return 0;
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = dynamic_cast(geo);
Base::Vector3d center = aoc->getCenter();
@@ -1490,6 +1504,9 @@ void SketchObject::rebuildVertexIndex(void)
} else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
+ } else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ VertexId2GeoId.push_back(i);
+ VertexId2PosId.push_back(mid);
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(start);
@@ -1497,6 +1514,13 @@ void SketchObject::rebuildVertexIndex(void)
VertexId2PosId.push_back(end);
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
+ } else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
+ VertexId2GeoId.push_back(i);
+ VertexId2PosId.push_back(start);
+ VertexId2GeoId.push_back(i);
+ VertexId2PosId.push_back(end);
+ VertexId2GeoId.push_back(i);
+ VertexId2PosId.push_back(mid);
}
}
}
diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
index c4029076ca..df890c2ae5 100644
--- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
+++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
@@ -90,7 +90,9 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
}
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
+ geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
+ geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
ret = this->getSketchObjectPtr()->addGeometry(geo);
}
@@ -131,7 +133,9 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
}
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
+ geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
+ geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
geoList.push_back(geo);
}
diff --git a/src/Mod/Sketcher/App/freegcs/Constraints.cpp b/src/Mod/Sketcher/App/freegcs/Constraints.cpp
index e8de23beee..4d2df2f1ac 100644
--- a/src/Mod/Sketcher/App/freegcs/Constraints.cpp
+++ b/src/Mod/Sketcher/App/freegcs/Constraints.cpp
@@ -912,4 +912,1237 @@ double ConstraintTangentCircumf::grad(double *param)
return scale * deriv;
}
+// ConstraintPointOnEllipse
+ConstraintPointOnEllipse::ConstraintPointOnEllipse(Point &p, Ellipse &e)
+{
+ pvec.push_back(p.x);
+ pvec.push_back(p.y);
+ pvec.push_back(e.center.x);
+ pvec.push_back(e.center.y);
+ pvec.push_back(e.focus1.x);
+ pvec.push_back(e.focus1.y);
+ pvec.push_back(e.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintPointOnEllipse::ConstraintPointOnEllipse(Point &p, ArcOfEllipse &a)
+{
+ pvec.push_back(p.x);
+ pvec.push_back(p.y);
+ pvec.push_back(a.center.x);
+ pvec.push_back(a.center.y);
+ pvec.push_back(a.focus1.x);
+ pvec.push_back(a.focus1.y);
+ pvec.push_back(a.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintType ConstraintPointOnEllipse::getTypeId()
+{
+ return P2OnEllipse;
+}
+
+void ConstraintPointOnEllipse::rescale(double coef)
+{
+ scale = coef * 1;
+}
+
+double ConstraintPointOnEllipse::error()
+{
+ double X_0 = *p1x();
+ double Y_0 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ double err=sqrt(pow(X_0 - X_F1, 2) + pow(Y_0 - Y_F1, 2)) + sqrt(pow(X_0 +
+ X_F1 - 2*X_c, 2) + pow(Y_0 + Y_F1 - 2*Y_c, 2)) - 2*sqrt(pow(b, 2) +
+ pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ return scale * err;
+}
+
+double ConstraintPointOnEllipse::grad(double *param)
+{
+ double deriv=0.;
+ if (param == p1x() || param == p1y() ||
+ param == f1x() || param == f1y() ||
+ param == cx() || param == cy() ||
+ param == rmin()) {
+
+ double X_0 = *p1x();
+ double Y_0 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ if (param == p1x())
+ deriv += (X_0 - X_F1)/sqrt(pow(X_0 - X_F1, 2) + pow(Y_0 - Y_F1, 2)) +
+ (X_0 + X_F1 - 2*X_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) + pow(Y_0 + Y_F1 -
+ 2*Y_c, 2));
+ if (param == p1y())
+ deriv += (Y_0 - Y_F1)/sqrt(pow(X_0 - X_F1, 2) + pow(Y_0 - Y_F1, 2)) +
+ (Y_0 + Y_F1 - 2*Y_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) + pow(Y_0 + Y_F1 -
+ 2*Y_c, 2));
+ if (param == f1x())
+ deriv += -(X_0 - X_F1)/sqrt(pow(X_0 - X_F1, 2) + pow(Y_0 - Y_F1, 2)) -
+ 2*(X_F1 - X_c)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))
+ + (X_0 + X_F1 - 2*X_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) + pow(Y_0 + Y_F1
+ - 2*Y_c, 2));
+ if (param == f1y())
+ deriv +=-(Y_0 - Y_F1)/sqrt(pow(X_0 - X_F1, 2) + pow(Y_0 - Y_F1, 2)) -
+ 2*(Y_F1 - Y_c)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))
+ + (Y_0 + Y_F1 - 2*Y_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) + pow(Y_0 + Y_F1
+ - 2*Y_c, 2));
+ if (param == cx())
+ deriv += 2*(X_F1 - X_c)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)) - 2*(X_0 + X_F1 - 2*X_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) +
+ pow(Y_0 + Y_F1 - 2*Y_c, 2));
+ if (param == cy())
+ deriv +=2*(Y_F1 - Y_c)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)) - 2*(Y_0 + Y_F1 - 2*Y_c)/sqrt(pow(X_0 + X_F1 - 2*X_c, 2) +
+ pow(Y_0 + Y_F1 - 2*Y_c, 2));
+ if (param == rmin())
+ deriv += -2*b/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2));
+ }
+ return scale * deriv;
+}
+
+// ConstraintEllipseTangentLine
+ConstraintEllipseTangentLine::ConstraintEllipseTangentLine(Line &l, Ellipse &e)
+{
+ pvec.push_back(l.p1.x);
+ pvec.push_back(l.p1.y);
+ pvec.push_back(l.p2.x);
+ pvec.push_back(l.p2.y);
+ pvec.push_back(e.center.x);
+ pvec.push_back(e.center.y);
+ pvec.push_back(e.focus1.x);
+ pvec.push_back(e.focus1.y);
+ pvec.push_back(e.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintEllipseTangentLine::ConstraintEllipseTangentLine(Line &l, ArcOfEllipse &a)
+{
+ pvec.push_back(l.p1.x);
+ pvec.push_back(l.p1.y);
+ pvec.push_back(l.p2.x);
+ pvec.push_back(l.p2.y);
+ pvec.push_back(a.center.x);
+ pvec.push_back(a.center.y);
+ pvec.push_back(a.focus1.x);
+ pvec.push_back(a.focus1.y);
+ pvec.push_back(a.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintType ConstraintEllipseTangentLine::getTypeId()
+{
+ return TangentEllipseLine;
+}
+
+void ConstraintEllipseTangentLine::rescale(double coef)
+{
+ scale = coef * 1;
+}
+
+double ConstraintEllipseTangentLine::error()
+{
+ double X_1 = *p1x();
+ double Y_1 = *p1y();
+ double X_2 = *p2x();
+ double Y_2 = *p2y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ double err=-2*(sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2))*sqrt(pow(X_F1, 2) - 2*X_F1*X_c + pow(X_c, 2) +
+ pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) - sqrt(pow(X_1,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) +
+ pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) -
+ 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c +
+ pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2)))
+ + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2));
+ return scale * err;
+}
+
+double ConstraintEllipseTangentLine::grad(double *param)
+{
+ double deriv=0.;
+ if (param == p1x() || param == p1y() ||
+ param == p2x() || param == p2y() ||
+ param == f1x() || param == f1y() ||
+ param == cx() || param == cy() ||
+ param == rmin()) {
+
+ double X_1 = *p1x();
+ double Y_1 = *p1y();
+ double X_2 = *p2x();
+ double Y_2 = *p2y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ // DeepSOIC equation
+ // http://forum.freecadweb.org/viewtopic.php?f=10&t=7520&start=140
+ // Partials:
+
+ if (param == p1x())
+ deriv += 2*(X_1 - X_2)*(sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))*sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) -
+ sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1,
+ 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c -
+ 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c
+ + pow(X_c, 2) + pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c +
+ pow(X_c, 2) + pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2)
+ + pow(Y_c, 2))) + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/pow(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2), 3.0/2.0) - 2*((X_1 - X_2)*sqrt(pow(X_F1, 2) -
+ 2*X_F1*X_c + pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) +
+ pow(b, 2))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2)) - (X_1*(pow(X_c, 2) + pow(Y_c, 2)) -
+ X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(X_1 - X_2) -
+ 2*X_F1*(X_1*X_c - X_2*X_c) + Y_1*(X_2*Y_c - X_F1*Y_c) + pow(Y_2, 2)*(X_1
+ - X_c) - Y_2*(2*X_1*Y_c - X_2*Y_c - X_F1*Y_c + Y_1*(X_2 - X_c)) +
+ Y_F1*(Y_1*(X_F1 - X_c) - Y_2*(X_F1 - X_c)))/sqrt(pow(X_1, 2)*(pow(X_c,
+ 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 +
+ pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2,
+ 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c,
+ 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == p1y())
+ deriv += 2*(Y_1 - Y_2)*(sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))*sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) -
+ sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1,
+ 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c -
+ 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c
+ + pow(X_c, 2) + pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c +
+ pow(X_c, 2) + pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2)
+ + pow(Y_c, 2))) + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/pow(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2), 3.0/2.0) - 2*((Y_1 - Y_2)*sqrt(pow(X_F1, 2) -
+ 2*X_F1*X_c + pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) +
+ pow(b, 2))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2)) - (X_1*X_2*Y_c - pow(X_2, 2)*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) - Y_2*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c,
+ 2)) + pow(Y_F1, 2)*(Y_1 - Y_2) + Y_F1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 -
+ X_2) - 2*Y_1*Y_c + 2*Y_2*Y_c))/sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c,
+ 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) -
+ 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1,
+ 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c, 2)) +
+ 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == p2x())
+ deriv += -2*(X_1 - X_2)*(sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))*sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) -
+ sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1,
+ 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c -
+ 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c
+ + pow(X_c, 2) + pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c +
+ pow(X_c, 2) + pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2)
+ + pow(Y_c, 2))) + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/pow(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2), 3.0/2.0) + 2*((X_1 - X_2)*sqrt(pow(X_F1, 2) -
+ 2*X_F1*X_c + pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) +
+ pow(b, 2))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2)) - (X_1*(pow(X_c, 2) + pow(Y_c, 2)) -
+ X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(X_1 - X_2) -
+ 2*X_F1*(X_1*X_c - X_2*X_c) - pow(Y_1, 2)*(X_2 - X_c) - Y_1*(X_1*Y_c -
+ 2*X_2*Y_c + X_F1*Y_c) + Y_2*(-X_1*Y_c + X_F1*Y_c + Y_1*(X_1 - X_c)) +
+ Y_F1*(Y_1*(X_F1 - X_c) - Y_2*(X_F1 - X_c)))/sqrt(pow(X_1, 2)*(pow(X_c,
+ 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 +
+ pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2,
+ 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c,
+ 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == p2y())
+ deriv += -2*(Y_1 - Y_2)*(sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))*sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) -
+ sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1,
+ 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c -
+ 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c
+ + pow(X_c, 2) + pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c +
+ pow(X_c, 2) + pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2)
+ + pow(Y_c, 2))) + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/pow(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2), 3.0/2.0) + 2*((Y_1 - Y_2)*sqrt(pow(X_F1, 2) -
+ 2*X_F1*X_c + pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) +
+ pow(b, 2))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2)) - (pow(X_1, 2)*Y_c - X_1*X_2*Y_c -
+ X_F1*(X_1*Y_c - X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2)
+ + pow(Y_c, 2)) - Y_2*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c,
+ 2)) + pow(Y_F1, 2)*(Y_1 - Y_2) + Y_F1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 -
+ X_2) - 2*Y_1*Y_c + 2*Y_2*Y_c))/sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c,
+ 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) -
+ 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1,
+ 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c, 2)) +
+ 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == f1x())
+ deriv += -2*((X_F1 - X_c)*sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))/sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) +
+ (pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2, 2)*X_c - X_F1*(pow(X_1, 2) -
+ 2*X_1*X_2 + pow(X_2, 2)) + Y_1*(X_1*Y_c - X_2*Y_c) - Y_2*(X_1*Y_c -
+ X_2*Y_c) - Y_F1*(Y_1*(X_1 - X_2) - Y_2*(X_1 - X_2)))/sqrt(pow(X_1,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) +
+ pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) -
+ 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c +
+ pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2)))
+ + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == f1y())
+ deriv +=-2*((Y_F1 - Y_c)*sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))/sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) +
+ (pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c) - Y_F1*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)))/sqrt(pow(X_1,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) +
+ pow(X_2, 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) -
+ 2*X_1*X_2 + pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c +
+ pow(X_2, 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c)) + pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) +
+ pow(Y_c, 2)) - 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c -
+ X_2*Y_c) + Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2)))
+ + pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) -
+ 2*Y_F1*(pow(Y_1, 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) +
+ pow(Y_2, 2)*Y_c + Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) -
+ 2*Y_1*Y_c))))/sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) -
+ 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == cx())
+ deriv += 2*((X_F1 - X_c)*sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))/sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) +
+ (pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2, 2)*X_c - X_F1*(pow(X_1, 2) -
+ 2*X_1*X_2 + pow(X_2, 2)) - pow(Y_1, 2)*(X_2 - X_c) + Y_1*Y_2*(X_1 + X_2
+ - 2*X_c) - pow(Y_2, 2)*(X_1 - X_c) - Y_F1*(Y_1*(X_1 - X_2) - Y_2*(X_1 -
+ X_2)))/sqrt(pow(X_1, 2)*(pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2, 2)*(pow(X_c, 2) +
+ pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2)) -
+ 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2, 2)*X_c) + pow(Y_1,
+ 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c, 2)) +
+ 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == cy())
+ deriv += 2*((Y_F1 - Y_c)*sqrt(pow(X_1, 2) - 2*X_1*X_2 + pow(X_2, 2) +
+ pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2))/sqrt(pow(X_F1, 2) - 2*X_F1*X_c +
+ pow(X_c, 2) + pow(Y_F1, 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2)) +
+ (pow(X_1, 2)*Y_c - 2*X_1*X_2*Y_c + pow(X_2, 2)*Y_c + pow(Y_1, 2)*Y_c +
+ Y_1*(X_1*X_2 - pow(X_2, 2) - X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c -
+ Y_2*(pow(X_1, 2) - X_1*X_2 - X_F1*(X_1 - X_2) + 2*Y_1*Y_c) -
+ Y_F1*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)))/sqrt(pow(X_1, 2)*(pow(X_c,
+ 2) + pow(Y_c, 2)) - 2*X_1*X_2*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_2,
+ 2)*(pow(X_c, 2) + pow(Y_c, 2)) + pow(X_F1, 2)*(pow(X_1, 2) - 2*X_1*X_2 +
+ pow(X_2, 2)) - 2*X_F1*(pow(X_1, 2)*X_c - 2*X_1*X_2*X_c + pow(X_2,
+ 2)*X_c) + pow(Y_1, 2)*(pow(X_2, 2) - 2*X_2*X_c + pow(X_c, 2) + pow(Y_c,
+ 2)) + 2*Y_1*(X_1*X_2*Y_c - pow(X_2, 2)*Y_c - X_F1*(X_1*Y_c - X_2*Y_c)) +
+ pow(Y_2, 2)*(pow(X_1, 2) - 2*X_1*X_c + pow(X_c, 2) + pow(Y_c, 2)) -
+ 2*Y_2*(pow(X_1, 2)*Y_c - X_1*X_2*Y_c - X_F1*(X_1*Y_c - X_2*Y_c) +
+ Y_1*(-X_1*X_c + X_2*(X_1 - X_c) + pow(X_c, 2) + pow(Y_c, 2))) +
+ pow(Y_F1, 2)*(pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2)) - 2*Y_F1*(pow(Y_1,
+ 2)*Y_c - Y_1*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2)) + pow(Y_2, 2)*Y_c +
+ Y_2*(-X_1*X_c + X_2*X_c + X_F1*(X_1 - X_2) - 2*Y_1*Y_c))))/sqrt(pow(X_1,
+ 2) - 2*X_1*X_2 + pow(X_2, 2) + pow(Y_1, 2) - 2*Y_1*Y_2 + pow(Y_2, 2));
+ if (param == rmin())
+ deriv += -2*b/sqrt(pow(X_F1, 2) - 2*X_F1*X_c + pow(X_c, 2) + pow(Y_F1,
+ 2) - 2*Y_F1*Y_c + pow(Y_c, 2) + pow(b, 2));
+ }
+ return scale * deriv;
+}
+
+// ConstraintInternalAlignmentPoint2Ellipse
+ConstraintInternalAlignmentPoint2Ellipse::ConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType)
+{
+ pvec.push_back(p1.x);
+ pvec.push_back(p1.y);
+ pvec.push_back(e.center.x);
+ pvec.push_back(e.center.y);
+ pvec.push_back(e.focus1.x);
+ pvec.push_back(e.focus1.y);
+ pvec.push_back(e.radmin);
+ origpvec = pvec;
+ rescale();
+ AlignmentType=alignmentType;
+}
+
+ConstraintInternalAlignmentPoint2Ellipse::ConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &p1, InternalAlignmentType alignmentType)
+{
+ pvec.push_back(p1.x);
+ pvec.push_back(p1.y);
+ pvec.push_back(a.center.x);
+ pvec.push_back(a.center.y);
+ pvec.push_back(a.focus1.x);
+ pvec.push_back(a.focus1.y);
+ pvec.push_back(a.radmin);
+ origpvec = pvec;
+ rescale();
+ AlignmentType=alignmentType;
+}
+
+ConstraintType ConstraintInternalAlignmentPoint2Ellipse::getTypeId()
+{
+ return InternalAlignmentPoint2Ellipse;
+}
+
+void ConstraintInternalAlignmentPoint2Ellipse::rescale(double coef)
+{
+ scale = coef * 1;
+}
+
+double ConstraintInternalAlignmentPoint2Ellipse::error()
+{
+ // so first is to select the point (X_0,Y_0) in line to calculate
+ double X_1 = *p1x();
+ double Y_1 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ return scale * (X_1 - X_c - (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipsePositiveMajorY:
+ return scale * (Y_1 - Y_c - (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipseNegativeMajorX:
+ return scale * (X_1 - X_c + (X_F1 - X_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipseNegativeMajorY:
+ return scale * (Y_1 - Y_c + (Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipsePositiveMinorX:
+ return scale * (X_1 - X_c + b*(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)));
+ break;
+ case EllipsePositiveMinorY:
+ return scale * (Y_1 - Y_c - b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)));
+ break;
+ case EllipseNegativeMinorX:
+ return scale * (X_1 - X_c - b*(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)));
+ break;
+ case EllipseNegativeMinorY:
+ return scale * (Y_1 - Y_c + b*(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2)));
+ break;
+ case EllipseFocus2X:
+ return scale * (X_1 + X_F1 - 2*X_c);
+ break;
+ case EllipseFocus2Y:
+ return scale * (Y_1 + Y_F1 - 2*Y_c);
+ break;
+ default:
+ return 0;
+ }
+}
+
+double ConstraintInternalAlignmentPoint2Ellipse::grad(double *param)
+{
+ double deriv=0.;
+ if (param == p1x() || param == p1y() ||
+ param == f1x() || param == f1y() ||
+ param == cx() || param == cy() ||
+ param == rmin()) {
+
+ double X_1 = *p1x();
+ double Y_1 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+
+ if (param == p1x())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += 1;
+ break;
+ case EllipsePositiveMajorY:
+ deriv += 0;
+ break;
+ case EllipseNegativeMajorX:
+ deriv += 1;
+ break;
+ case EllipseNegativeMajorY:
+ deriv += 0;
+ break;
+ case EllipsePositiveMinorX:
+ deriv += 1;
+ break;
+ case EllipsePositiveMinorY:
+ deriv += 0;
+ break;
+ case EllipseNegativeMinorX:
+ deriv += 1;
+ break;
+ case EllipseNegativeMinorY:
+ deriv += 0;
+ break;
+ case EllipseFocus2X:
+ deriv += 1;
+ break;
+ case EllipseFocus2Y:
+ deriv += 0;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == p1y())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += 0;
+ break;
+ case EllipsePositiveMajorY:
+ deriv += 1;
+ break;
+ case EllipseNegativeMajorX:
+ deriv += 0;
+ break;
+ case EllipseNegativeMajorY:
+ deriv += 1;
+ break;
+ case EllipsePositiveMinorX:
+ deriv += 0;
+ break;
+ case EllipsePositiveMinorY:
+ deriv += 1;
+ break;
+ case EllipseNegativeMinorX:
+ deriv += 0;
+ break;
+ case EllipseNegativeMinorY:
+ deriv += 1;
+ break;
+ case EllipseFocus2X:
+ deriv += 0;
+ break;
+ case EllipseFocus2Y:
+ deriv += 1;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == f1x())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += -pow(X_F1 - X_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ pow(X_F1 - X_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) -
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMajorY:
+ deriv += -(X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMajorX:
+ deriv += pow(X_F1 - X_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ pow(X_F1 - X_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) +
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMajorY:
+ deriv += (X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipsePositiveMinorX:
+ deriv += -b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipsePositiveMinorY:
+ deriv += b*pow(X_F1 - X_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) - b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorX:
+ deriv += b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMinorY:
+ deriv += -b*pow(X_F1 - X_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) + b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseFocus2X:
+ deriv += 1;
+ break;
+ case EllipseFocus2Y:
+ deriv+=0;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == f1y())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += -(X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipsePositiveMajorY:
+ deriv += -pow(Y_F1 - Y_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ pow(Y_F1 - Y_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) -
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMajorX:
+ deriv += (X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMajorY:
+ deriv += pow(Y_F1 - Y_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ pow(Y_F1 - Y_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) +
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMinorX:
+ deriv += -b*pow(Y_F1 - Y_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) + b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMinorY:
+ deriv += b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMinorX:
+ deriv += b*pow(Y_F1 - Y_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) - b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorY:
+ deriv += -b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseFocus2X:
+ deriv += 0;
+ break;
+ case EllipseFocus2Y:
+ deriv += 1;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == cx())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += pow(X_F1 - X_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ pow(X_F1 - X_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - 1 +
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMajorY:
+ deriv += (X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMajorX:
+ deriv += -pow(X_F1 - X_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ pow(X_F1 - X_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - 1 -
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMajorY:
+ deriv += -(X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipsePositiveMinorX:
+ deriv += b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L) - 1;
+ break;
+ case EllipsePositiveMinorY:
+ deriv += -b*pow(X_F1 - X_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) + b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorX:
+ deriv += -b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L) - 1;
+ break;
+ case EllipseNegativeMinorY:
+ deriv += b*pow(X_F1 - X_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) - b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseFocus2X:
+ deriv += -2;
+ break;
+ case EllipseFocus2Y:
+ deriv+=0;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == cy())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += (X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipsePositiveMajorY:
+ deriv += pow(Y_F1 - Y_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) -
+ pow(Y_F1 - Y_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - 1 +
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMajorX:
+ deriv += -(X_F1 - X_c)*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ (X_F1 - X_c)*(Y_F1 - Y_c)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L);
+ break;
+ case EllipseNegativeMajorY:
+ deriv += -pow(Y_F1 - Y_c, 2)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))) +
+ pow(Y_F1 - Y_c, 2)*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - 1 -
+ sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2))/sqrt(pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMinorX:
+ deriv += b*pow(Y_F1 - Y_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) - b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMinorY:
+ deriv += -b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L) - 1;
+ break;
+ case EllipseNegativeMinorX:
+ deriv += -b*pow(Y_F1 - Y_c, 2)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) + b/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorY:
+ deriv += b*(X_F1 - X_c)*(Y_F1 - Y_c)/pow(pow(X_F1 - X_c, 2) + pow(Y_F1
+ - Y_c, 2), 3.0L/2.0L) - 1;
+ break;
+ case EllipseFocus2X:
+ deriv += 0;
+ break;
+ case EllipseFocus2Y:
+ deriv += -2;
+ break;
+ default:
+ deriv+=0;
+ }
+ if (param == rmin())
+ switch(AlignmentType)
+ {
+ case EllipsePositiveMajorX:
+ deriv += -b*(X_F1 - X_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipsePositiveMajorY:
+ deriv += -b*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipseNegativeMajorX:
+ deriv += b*(X_F1 - X_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipseNegativeMajorY:
+ deriv += b*(Y_F1 - Y_c)/(sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2))*sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)));
+ break;
+ case EllipsePositiveMinorX:
+ deriv += (Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipsePositiveMinorY:
+ deriv += -(X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorX:
+ deriv += -(Y_F1 - Y_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseNegativeMinorY:
+ deriv += (X_F1 - X_c)/sqrt(pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2));
+ break;
+ case EllipseFocus2X:
+ deriv += 0;
+ break;
+ case EllipseFocus2Y:
+ deriv += 0;
+ break;
+ default:
+ deriv+=0;
+ }
+ }
+ return scale * deriv;
+}
+
+// ConstraintEqualMajorAxesEllipse
+ ConstraintEqualMajorAxesEllipse:: ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2)
+{
+ pvec.push_back(e1.center.x);
+ pvec.push_back(e1.center.y);
+ pvec.push_back(e1.focus1.x);
+ pvec.push_back(e1.focus1.y);
+ pvec.push_back(e1.radmin);
+ pvec.push_back(e2.center.x);
+ pvec.push_back(e2.center.y);
+ pvec.push_back(e2.focus1.x);
+ pvec.push_back(e2.focus1.y);
+ pvec.push_back(e2.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintType ConstraintEqualMajorAxesEllipse::getTypeId()
+{
+ return EqualMajorAxesEllipse;
+}
+
+void ConstraintEqualMajorAxesEllipse::rescale(double coef)
+{
+ scale = coef * 1;
+}
+
+double ConstraintEqualMajorAxesEllipse::error()
+{
+ double E1X_c = *e1cx();
+ double E1Y_c = *e1cy();
+ double E1X_F1 = *e1f1x();
+ double E1Y_F1 = *e1f1y();
+ double E1b = *e1rmin();
+ double E2X_c = *e2cx();
+ double E2Y_c = *e2cy();
+ double E2X_F1 = *e2f1x();
+ double E2Y_F1 = *e2f1y();
+ double E2b = *e2rmin();
+
+ double err=sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c + pow(E1X_c, 2) +
+ pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) + pow(E1b, 2)) -
+ sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c + pow(E2X_c, 2) + pow(E2Y_F1, 2) -
+ 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) + pow(E2b, 2));
+ return scale * err;
+}
+
+double ConstraintEqualMajorAxesEllipse::grad(double *param)
+{
+ double deriv=0.;
+ if (param == e1f1x() || param == e1f1y() ||
+ param == e1cx() || param == e1cy() ||
+ param == e1rmin() ||
+ param == e2f1x() || param == e2f1y() ||
+ param == e2cx() || param == e2cy() ||
+ param == e2rmin()) {
+
+ double E1X_c = *e1cx();
+ double E1Y_c = *e1cy();
+ double E1X_F1 = *e1f1x();
+ double E1Y_F1 = *e1f1y();
+ double E1b = *e1rmin();
+ double E2X_c = *e2cx();
+ double E2Y_c = *e2cy();
+ double E2X_F1 = *e2f1x();
+ double E2Y_F1 = *e2f1y();
+ double E2b = *e2rmin();
+
+ if (param == e1cx())
+ deriv += -(E1X_F1 - E1X_c)/sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c +
+ pow(E1X_c, 2) + pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) +
+ pow(E1b, 2));
+ if (param == e2cx())
+ deriv += (E2X_F1 - E2X_c)/sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c +
+ pow(E2X_c, 2) + pow(E2Y_F1, 2) - 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) +
+ pow(E2b, 2));
+ if (param == e1cy())
+ deriv += -(E1Y_F1 - E1Y_c)/sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c +
+ pow(E1X_c, 2) + pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) +
+ pow(E1b, 2));
+ if (param == e2cy())
+ deriv +=(E2Y_F1 - E2Y_c)/sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c +
+ pow(E2X_c, 2) + pow(E2Y_F1, 2) - 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) +
+ pow(E2b, 2));
+ if (param == e1f1x())
+ deriv += (E1X_F1 - E1X_c)/sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c +
+ pow(E1X_c, 2) + pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) +
+ pow(E1b, 2));
+ if (param == e2f1x())
+ deriv +=-(E2X_F1 - E2X_c)/sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c +
+ pow(E2X_c, 2) + pow(E2Y_F1, 2) - 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) +
+ pow(E2b, 2));
+ if (param == e1f1y())
+ deriv += (E1Y_F1 - E1Y_c)/sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c +
+ pow(E1X_c, 2) + pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) +
+ pow(E1b, 2));
+ if (param == e2f1y())
+ deriv +=-(E2Y_F1 - E2Y_c)/sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c +
+ pow(E2X_c, 2) + pow(E2Y_F1, 2) - 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) +
+ pow(E2b, 2));
+ if (param == e1rmin())
+ deriv += E1b/sqrt(pow(E1X_F1, 2) - 2*E1X_F1*E1X_c + pow(E1X_c, 2) +
+ pow(E1Y_F1, 2) - 2*E1Y_F1*E1Y_c + pow(E1Y_c, 2) + pow(E1b, 2));
+ if (param == e2rmin())
+ deriv += -E2b/sqrt(pow(E2X_F1, 2) - 2*E2X_F1*E2X_c + pow(E2X_c, 2) +
+ pow(E2Y_F1, 2) - 2*E2Y_F1*E2Y_c + pow(E2Y_c, 2) + pow(E2b, 2));
+ }
+ return scale * deriv;
+}
+
+// EllipticalArcRangeToEndPoints
+ConstraintEllipticalArcRangeToEndPoints::ConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle_t)
+{
+ pvec.push_back(p.x);
+ pvec.push_back(p.y);
+ pvec.push_back(angle_t);
+ pvec.push_back(a.center.x);
+ pvec.push_back(a.center.y);
+ pvec.push_back(a.focus1.x);
+ pvec.push_back(a.focus1.y);
+ pvec.push_back(a.radmin);
+ origpvec = pvec;
+ rescale();
+}
+
+ConstraintType ConstraintEllipticalArcRangeToEndPoints::getTypeId()
+{
+ return EllipticalArcRangeToEndPoints;
+}
+
+void ConstraintEllipticalArcRangeToEndPoints::rescale(double coef)
+{
+ scale = coef * 1;
+}
+
+double ConstraintEllipticalArcRangeToEndPoints::error()
+{
+ double X_0 = *p1x();
+ double Y_0 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+ double alpha_t = *angle();
+
+ double err=atan((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)/(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b));
+ return scale * err;
+}
+
+double ConstraintEllipticalArcRangeToEndPoints::grad(double *param)
+{
+ double deriv=0.;
+ if (param == p1x() || param == p1y() ||
+ param == f1x() || param == f1y() ||
+ param == cx() || param == cy() ||
+ param == rmin() || param == angle()) {
+
+ double X_0 = *p1x();
+ double Y_0 = *p1y();
+ double X_c = *cx();
+ double Y_c = *cy();
+ double X_F1 = *f1x();
+ double Y_F1 = *f1y();
+ double b = *rmin();
+ double alpha_t = *angle();
+
+ if (param == p1x())
+ deriv += -(-((X_F1 - X_c)*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (Y_F1 - Y_c)*cos(alpha_t)/b)/(((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b,
+ 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 -
+ Y_c) + (X_F1 - X_c)*(Y_0 - Y_c))*sin(alpha_t)/b) + ((X_F1 -
+ X_c)*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (Y_F1 - Y_c)*sin(alpha_t)/b)*(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1
+ - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == p1y())
+ deriv += -(-((Y_F1 - Y_c)*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) - (X_F1 - X_c)*cos(alpha_t)/b)/(((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b,
+ 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 -
+ Y_c) + (X_F1 - X_c)*(Y_0 - Y_c))*sin(alpha_t)/b) + ((Y_F1 -
+ Y_c)*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (X_F1 - X_c)*sin(alpha_t)/b)*(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1
+ - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == f1x())
+ deriv += -((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)*((X_0 - X_c)*cos(alpha_t)/sqrt(pow(b, 2) +
+ pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) - (X_F1 - X_c)*((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/pow(pow(b, 2)
+ + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (Y_0 -
+ Y_c)*sin(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) - ((X_0 - X_c)*sin(alpha_t)/sqrt(pow(b, 2) +
+ pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) - (X_F1 - X_c)*((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/pow(pow(b, 2)
+ + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - (Y_0 -
+ Y_c)*cos(alpha_t)/b)/(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == f1y())
+ deriv +=-((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)*((Y_0 - Y_c)*cos(alpha_t)/sqrt(pow(b, 2) +
+ pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) - (Y_F1 - Y_c)*((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/pow(pow(b, 2)
+ + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - (X_0 -
+ X_c)*sin(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) - ((Y_0 - Y_c)*sin(alpha_t)/sqrt(pow(b, 2) +
+ pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2)) - (Y_F1 - Y_c)*((X_0 -
+ X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/pow(pow(b, 2)
+ + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (X_0 -
+ X_c)*cos(alpha_t)/b)/(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == cx())
+ deriv += ((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)*(-(X_F1 - X_c)*((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/pow(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (X_0 + X_F1 -
+ 2*X_c)*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) + (Y_0 - Y_F1)*sin(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) +
+ (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*sin(alpha_t)/b, 2) - (-(X_F1 - X_c)*((X_0 - X_c)*(X_F1
+ - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/pow(pow(b, 2) + pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (X_0 + X_F1 -
+ 2*X_c)*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) - (Y_0 - Y_F1)*cos(alpha_t)/b)/(((X_0 - X_c)*(X_F1 - X_c) +
+ (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*sin(alpha_t)/b))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0
+ - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == cy())
+ deriv +=((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)*(-(Y_F1 - Y_c)*((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/pow(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (Y_0 + Y_F1 -
+ 2*Y_c)*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) - (X_0 - X_F1)*sin(alpha_t)/b)/pow(((X_0 - X_c)*(X_F1 - X_c) +
+ (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*sin(alpha_t)/b, 2) - (-(Y_F1 - Y_c)*((X_0 - X_c)*(X_F1
+ - X_c) + (Y_0 - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/pow(pow(b, 2) + pow(X_F1
+ - X_c, 2) + pow(Y_F1 - Y_c, 2), 3.0L/2.0L) + (Y_0 + Y_F1 -
+ 2*Y_c)*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 -
+ Y_c, 2)) + (X_0 - X_F1)*cos(alpha_t)/b)/(((X_0 - X_c)*(X_F1 - X_c) +
+ (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*sin(alpha_t)/b))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0
+ - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == rmin())
+ deriv += ((((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b)*(b*((X_0 - X_c)*(X_F1 - X_c) + (Y_0 - Y_c)*(Y_F1 -
+ Y_c))*cos(alpha_t)/pow(pow(b, 2) + pow(X_F1 - X_c, 2) + pow(Y_F1 - Y_c,
+ 2), 3.0L/2.0L) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/pow(b, 2))/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) - (b*((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/pow(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2), 3.0L/2.0L) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*cos(alpha_t)/pow(b, 2))/(((X_0 - X_c)*(X_F1 - X_c) +
+ (Y_0 - Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c,
+ 2) + pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 -
+ X_c)*(Y_0 - Y_c))*sin(alpha_t)/b))/(pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0
+ - Y_c)*(Y_F1 - Y_c))*sin(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) - (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*cos(alpha_t)/b, 2)/pow(((X_0 - X_c)*(X_F1 - X_c) + (Y_0 -
+ Y_c)*(Y_F1 - Y_c))*cos(alpha_t)/sqrt(pow(b, 2) + pow(X_F1 - X_c, 2) +
+ pow(Y_F1 - Y_c, 2)) + (-(X_0 - X_c)*(Y_F1 - Y_c) + (X_F1 - X_c)*(Y_0 -
+ Y_c))*sin(alpha_t)/b, 2) + 1);
+ if (param == angle())
+ deriv += 1;
+ }
+ return scale * deriv;
+}
+
+double ConstraintEllipticalArcRangeToEndPoints::maxStep(MAP_pD_D &dir, double lim)
+{
+ // step(angle()) <= pi/18 = 10°
+ MAP_pD_D::iterator it = dir.find(angle());
+ if (it != dir.end()) {
+ double step = std::abs(it->second);
+ if (step > M_PI/18.)
+ lim = std::min(lim, (M_PI/18.) / step);
+ }
+ return lim;
+}
+
} //namespace GCS
diff --git a/src/Mod/Sketcher/App/freegcs/Constraints.h b/src/Mod/Sketcher/App/freegcs/Constraints.h
index a4bfdd410b..e08e47bff0 100644
--- a/src/Mod/Sketcher/App/freegcs/Constraints.h
+++ b/src/Mod/Sketcher/App/freegcs/Constraints.h
@@ -46,7 +46,26 @@ namespace GCS
Perpendicular = 9,
L2LAngle = 10,
MidpointOnLine = 11,
- TangentCircumf = 12
+ TangentCircumf = 12,
+ P2OnEllipse = 13,
+ TangentEllipseLine = 14,
+ Point2EllipseDistance = 15,
+ InternalAlignmentPoint2Ellipse = 16,
+ EqualMajorAxesEllipse = 17,
+ EllipticalArcRangeToEndPoints = 18
+ };
+
+ enum InternalAlignmentType {
+ EllipsePositiveMajorX = 0,
+ EllipsePositiveMajorY = 1,
+ EllipseNegativeMajorX = 2,
+ EllipseNegativeMajorY = 3,
+ EllipsePositiveMinorX = 4,
+ EllipsePositiveMinorY = 5,
+ EllipseNegativeMinorX = 6,
+ EllipseNegativeMinorY = 7,
+ EllipseFocus2X = 8,
+ EllipseFocus2Y = 9
};
class Constraint
@@ -159,6 +178,7 @@ namespace GCS
virtual double error();
virtual double grad(double *);
virtual double maxStep(MAP_pD_D &dir, double lim=1.);
+ double abs(double darea);
};
// PointOnLine
@@ -304,6 +324,110 @@ namespace GCS
virtual double error();
virtual double grad(double *);
};
+ // PointOnEllipse
+ class ConstraintPointOnEllipse : public Constraint
+ {
+ private:
+ inline double* p1x() { return pvec[0]; }
+ inline double* p1y() { return pvec[1]; }
+ inline double* cx() { return pvec[2]; }
+ inline double* cy() { return pvec[3]; }
+ inline double* f1x() { return pvec[4]; }
+ inline double* f1y() { return pvec[5]; }
+ inline double* rmin() { return pvec[6]; }
+ public:
+ ConstraintPointOnEllipse(Point &p, Ellipse &e);
+ ConstraintPointOnEllipse(Point &p, ArcOfEllipse &a);
+ virtual ConstraintType getTypeId();
+ virtual void rescale(double coef=1.);
+ virtual double error();
+ virtual double grad(double *);
+ };
+
+ class ConstraintEllipseTangentLine : public Constraint
+ {
+ private:
+ inline double* p1x() { return pvec[0]; }
+ inline double* p1y() { return pvec[1]; }
+ inline double* p2x() { return pvec[2]; }
+ inline double* p2y() { return pvec[3]; }
+ inline double* cx() { return pvec[4]; }
+ inline double* cy() { return pvec[5]; }
+ inline double* f1x() { return pvec[6]; }
+ inline double* f1y() { return pvec[7]; }
+ inline double* rmin() { return pvec[8]; }
+ public:
+ ConstraintEllipseTangentLine(Line &l, Ellipse &e);
+ ConstraintEllipseTangentLine(Line &l, ArcOfEllipse &a);
+ virtual ConstraintType getTypeId();
+ virtual void rescale(double coef=1.);
+ virtual double error();
+ virtual double grad(double *);
+ };
+
+ class ConstraintInternalAlignmentPoint2Ellipse : public Constraint
+ {
+ private:
+ inline double* p1x() { return pvec[0]; }
+ inline double* p1y() { return pvec[1]; }
+ inline double* cx() { return pvec[2]; }
+ inline double* cy() { return pvec[3]; }
+ inline double* f1x() { return pvec[4]; }
+ inline double* f1y() { return pvec[5]; }
+ inline double* rmin() { return pvec[6]; }
+ public:
+ ConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType);
+ ConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &e, Point &p1, InternalAlignmentType alignmentType);
+ virtual ConstraintType getTypeId();
+ virtual void rescale(double coef=1.);
+ virtual double error();
+ virtual double grad(double *);
+ private:
+ InternalAlignmentType AlignmentType;
+ };
+
+ class ConstraintEqualMajorAxesEllipse : public Constraint
+ {
+ private:
+ inline double* e1cx() { return pvec[0]; }
+ inline double* e1cy() { return pvec[1]; }
+ inline double* e1f1x() { return pvec[2]; }
+ inline double* e1f1y() { return pvec[3]; }
+ inline double* e1rmin() { return pvec[4]; }
+ inline double* e2cx() { return pvec[5]; }
+ inline double* e2cy() { return pvec[6]; }
+ inline double* e2f1x() { return pvec[7]; }
+ inline double* e2f1y() { return pvec[8]; }
+ inline double* e2rmin() { return pvec[9]; }
+ public:
+ ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2);
+ virtual ConstraintType getTypeId();
+ virtual void rescale(double coef=1.);
+ virtual double error();
+ virtual double grad(double *);
+ };
+
+ // EllipticalArcRangeToEndPoints
+ class ConstraintEllipticalArcRangeToEndPoints : public Constraint
+ {
+ private:
+ inline double* p1x() { return pvec[0]; }
+ inline double* p1y() { return pvec[1]; }
+ inline double* angle() { return pvec[2]; }
+ inline double* cx() { return pvec[3]; }
+ inline double* cy() { return pvec[4]; }
+ inline double* f1x() { return pvec[5]; }
+ inline double* f1y() { return pvec[6]; }
+ inline double* rmin() { return pvec[7]; }
+ public:
+ ConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle_t);
+ virtual ConstraintType getTypeId();
+ virtual void rescale(double coef=1.);
+ virtual double error();
+ virtual double grad(double *);
+ virtual double maxStep(MAP_pD_D &dir, double lim=1.);
+ };
+
} //namespace GCS
diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp
index 7c6625a7ec..477b94bf0d 100644
--- a/src/Mod/Sketcher/App/freegcs/GCS.cpp
+++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp
@@ -27,6 +27,16 @@
#include "qp_eq.h"
#include
+#define _GCS_DEBUG 1
+
+#ifdef _GCS_DEBUG
+#include
+#include
+#include
+#include
+#include
+#endif // _GCS_DEBUG
+
#include
#include
@@ -481,6 +491,42 @@ int System::addConstraintPointOnCircle(Point &p, Circle &c, int tagId)
return addConstraintP2PDistance(p, c.center, c.rad, tagId);
}
+int System::addConstraintPointOnEllipse(Point &p, Ellipse &e, int tagId)
+{
+ // TODO: Implement real constraint => Done
+
+ Constraint *constr = new ConstraintPointOnEllipse(p, e);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+int System::addConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle, int tagId)
+{
+ Constraint *constr = new ConstraintEllipticalArcRangeToEndPoints(p,a,angle);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+
+int System::addConstraintArcOfEllipseRules(ArcOfEllipse &a, int tagId)
+{
+ /* addConstraintP2PAngle(a.center, a.start, a.startAngle, tagId);
+ return addConstraintP2PAngle(a.center, a.end, a.endAngle, tagId);*/
+
+ addConstraintEllipticalArcRangeToEndPoints(a.start,a,a.startAngle, tagId);
+ addConstraintEllipticalArcRangeToEndPoints(a.end,a,a.endAngle, tagId);
+
+ addConstraintPointOnArcOfEllipse(a.start, a, tagId);
+ return addConstraintPointOnArcOfEllipse(a.end, a, tagId);
+}
+
+int System::addConstraintPointOnArcOfEllipse(Point &p, ArcOfEllipse &a, int tagId)
+{
+ Constraint *constr = new ConstraintPointOnEllipse(p, a);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
int System::addConstraintPointOnArc(Point &p, Arc &a, int tagId)
{
return addConstraintP2PDistance(p, a.center, a.rad, tagId);
@@ -552,6 +598,39 @@ int System::addConstraintTangent(Line &l, Circle &c, int tagId)
return addConstraintP2LDistance(c.center, l, c.rad, tagId);
}
+int System::addConstraintTangent(Line &l, Ellipse &e, int tagId)
+{
+ // TODO: real ellipse implementation => Done
+ Constraint *constr = new ConstraintEllipseTangentLine(l, e);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+int System::addConstraintTangent(Line &l, ArcOfEllipse &a, int tagId)
+{
+ // TODO: real ellipse implementation => Done
+ Constraint *constr = new ConstraintEllipseTangentLine(l, a);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+int System::addConstraintTangent(Ellipse &e, Circle &c, int tagId)
+{
+ // TODO: elipse
+ /*double dx = *(c.center.x) - *(e.center.x);
+ double dy = *(c.center.y) - *(e.center.y);
+ double d = sqrt(dx*dx + dy*dy);*/
+
+ /*Constraint *constr = new ConstraintPoint2EllipseDistance(c.center,e,c.rad);
+ constr->setTag(tagId);
+ return addConstraint(constr); */
+
+
+ //return addConstraintTangentCircumf(e.center, c.center, e.radmaj, c.rad,
+ // (d < *e.radmaj || d < *c.rad), tagId);
+ return 0;
+}
+
int System::addConstraintTangent(Line &l, Arc &a, int tagId)
{
return addConstraintP2LDistance(a.center, l, a.rad, tagId);
@@ -584,6 +663,19 @@ int System::addConstraintTangent(Circle &c, Arc &a, int tagId)
(d < *c.rad || d < *a.rad), tagId);
}
+int System::addConstraintTangent(Ellipse &e, Arc &a, int tagId)
+{
+ // TODO: elipse
+ /*double dx = *(a.center.x) - *(e.center.x);
+ double dy = *(a.center.y) - *(e.center.y);
+ double d = sqrt(dx*dx + dy*dy);Constraint *constr = new ConstraintEllipseTangentLine(l, e);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+ return addConstraintTangentCircumf(e.center, a.center, e.radmaj, a.rad,
+ (d < *e.radmaj || d < *a.rad), tagId);*/
+ return 0;
+}
+
int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId)
{
addConstraintP2PCoincident(p2, a.start, tagId);
@@ -598,6 +690,18 @@ int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId
return addConstraintP2PAngle(p1, p2, a.endAngle, incrAngle, tagId);
}
+int System::addConstraintTangentLine2ArcOfEllipse(Point &p1, Point &p2, Line &l, ArcOfEllipse &a, int tagId)
+{
+ addConstraintP2PCoincident(p2, a.start, tagId);
+ return addConstraintTangent(l, a, tagId);
+}
+
+int System::addConstraintTangentArcOfEllipse2Line(ArcOfEllipse &a, Line &l, Point &p1, Point &p2, int tagId)
+{
+ addConstraintP2PCoincident(p1, a.end, tagId);
+ return addConstraintTangent(l, a, tagId);
+}
+
int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId)
{
addConstraintPointOnCircle(a.start, c, tagId);
@@ -609,6 +713,19 @@ int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId)
return addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId);
}
+int System::addConstraintTangentEllipse2Arc(Ellipse &e, Arc &a, int tagId)
+{
+ // TODO: Ellipse
+ /*addConstraintPointOnEllipse(a.start, e, tagId);
+ double dx = *(a.start.x) - *(e.center.x);
+ double dy = *(a.start.y) - *(e.center.y);
+ if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0)
+ return addConstraintP2PAngle(e.center, a.start, a.startAngle, 0, tagId);
+ else
+ return addConstraintP2PAngle(e.center, a.start, a.startAngle, M_PI, tagId);*/
+ return 0;
+}
+
int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId)
{
addConstraintPointOnCircle(a.end, c, tagId);
@@ -620,6 +737,19 @@ int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId)
return addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId);
}
+int System::addConstraintTangentArc2Ellipse(Arc &a, Ellipse &e, int tagId)
+{
+ // TODO: Ellipse
+ /*addConstraintPointOnEllipse(a.end, e, tagId);
+ double dx = *(a.end.x) - *(e.center.x);
+ double dy = *(a.end.y) - *(e.center.y);
+ if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0)
+ return addConstraintP2PAngle(e.center, a.end, a.endAngle, 0, tagId);
+ else
+ return addConstraintP2PAngle(e.center, a.end, a.endAngle, M_PI, tagId);*/
+ return 0;
+}
+
int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId)
{
@@ -656,6 +786,17 @@ int System::addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId)
return addConstraintEqual(c1.rad, c2.rad, tagId);
}
+int System::addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId)
+{
+ // TODO: Ellipse
+ //addConstraintEqual(e1.radmaj, e2.radmaj, tagId);
+ addConstraintEqual(e1.radmin, e2.radmin, tagId);
+
+ Constraint *constr = new ConstraintEqualMajorAxesEllipse(e1,e2);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
int System::addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId)
{
return addConstraintEqual(c1.rad, a2.rad, tagId);
@@ -678,6 +819,74 @@ int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId)
return addConstraintPointOnLine(p, p1, p2, tagId);
}
+int System::addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId)
+{
+ Constraint *constr = new ConstraintInternalAlignmentPoint2Ellipse(e, p1, alignmentType);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+int System::addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorX,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorY,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorX,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorY,tagId);
+}
+
+int System::addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorX,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorY,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorX,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorY,tagId);
+}
+
+int System::addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId)
+{
+ return addConstraintP2PCoincident(e.focus1,p1);
+}
+
+int System::addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseFocus2X,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseFocus2Y,tagId);
+}
+
+int System::addConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &p1, InternalAlignmentType alignmentType, int tagId)
+{
+ Constraint *constr = new ConstraintInternalAlignmentPoint2Ellipse(a, p1, alignmentType);
+ constr->setTag(tagId);
+ return addConstraint(constr);
+}
+
+int System::addConstraintInternalAlignmentEllipseMajorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorX,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorY,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorX,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorY,tagId);
+}
+
+int System::addConstraintInternalAlignmentEllipseMinorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorX,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorY,tagId);
+ addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorX,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorY,tagId);
+}
+
+int System::addConstraintInternalAlignmentEllipseFocus1(ArcOfEllipse &a, Point &p1, int tagId)
+{
+ return addConstraintP2PCoincident(a.focus1,p1);
+}
+
+int System::addConstraintInternalAlignmentEllipseFocus2(ArcOfEllipse &a, Point &p1, int tagId)
+{
+ addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseFocus2X,tagId);
+ return addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseFocus2Y,tagId);
+}
+
void System::rescaleConstraint(int id, double coeff)
{
if (id >= clist.size() || id < 0)
@@ -1465,12 +1674,27 @@ int System::diagnose()
J(count-1,j) = (*constr)->grad(plist[j]);
}
}
-
+
+ #ifdef _GCS_DEBUG
+ // Debug code starts
+ std::stringstream stream;
+
+ stream << "[";
+ stream << J ;
+ stream << "]";
+
+ const std::string tmp = stream.str();
+
+ Base::Console().Warning(tmp.c_str());
+ // Debug code ends
+ #endif
+
if (J.rows() > 0) {
Eigen::FullPivHouseholderQR qrJT(J.topRows(count).transpose());
Eigen::MatrixXd Q = qrJT.matrixQ ();
int paramsNum = qrJT.rows();
int constrNum = qrJT.cols();
+ //qrJT.setThreshold(0);
int rank = qrJT.rank();
Eigen::MatrixXd R;
diff --git a/src/Mod/Sketcher/App/freegcs/GCS.h b/src/Mod/Sketcher/App/freegcs/GCS.h
index f592b92ea0..3d99da2c9b 100644
--- a/src/Mod/Sketcher/App/freegcs/GCS.h
+++ b/src/Mod/Sketcher/App/freegcs/GCS.h
@@ -125,6 +125,10 @@ namespace GCS
int addConstraintCoordinateY(Point &p, double *y, int tagId=0);
int addConstraintArcRules(Arc &a, int tagId=0);
int addConstraintPointOnCircle(Point &p, Circle &c, int tagId=0);
+ int addConstraintPointOnEllipse(Point &p, Ellipse &e, int tagId=0);
+ int addConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle, int tagId=0);
+ int addConstraintArcOfEllipseRules(ArcOfEllipse &a, int tagId=0);
+ int addConstraintPointOnArcOfEllipse(Point &p, ArcOfEllipse &a, int tagId=0);
int addConstraintPointOnArc(Point &p, Arc &a, int tagId=0);
int addConstraintPerpendicularLine2Arc(Point &p1, Point &p2, Arc &a,
int tagId=0);
@@ -137,24 +141,47 @@ namespace GCS
int addConstraintPerpendicularArc2Arc(Arc &a1, bool reverse1,
Arc &a2, bool reverse2, int tagId=0);
int addConstraintTangent(Line &l, Circle &c, int tagId=0);
+ int addConstraintTangent(Line &l, Ellipse &e, int tagId=0);
+ int addConstraintTangent(Line &l, ArcOfEllipse &a, int tagId=0);
+ int addConstraintTangent(Ellipse &e, Circle &c, int tagId=0);
int addConstraintTangent(Line &l, Arc &a, int tagId=0);
int addConstraintTangent(Circle &c1, Circle &c2, int tagId=0);
int addConstraintTangent(Arc &a1, Arc &a2, int tagId=0);
int addConstraintTangent(Circle &c, Arc &a, int tagId=0);
+ int addConstraintTangent(Ellipse &e, Arc &a, int tagId=0);
+ int addConstraintTangentLine2ArcOfEllipse(Point &p1, Point &p2, Line &l, ArcOfEllipse &a, int tagId=0);
+ int addConstraintTangentArcOfEllipse2Line(ArcOfEllipse &a, Line &l, Point &p1, Point &p2, int tagId=0);
int addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId=0);
int addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId=0);
int addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId=0);
+ int addConstraintTangentEllipse2Arc(Ellipse &e, Arc &a, int tagId=0);
int addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId=0);
+ int addConstraintTangentArc2Ellipse(Arc &a, Ellipse &e, int tagId=0);
int addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId=0);
int addConstraintCircleRadius(Circle &c, double *radius, int tagId=0);
+ int addConstraintEllipseAngleXU(Ellipse &e, double *angle, int tagId=0);
int addConstraintArcRadius(Arc &a, double *radius, int tagId=0);
int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId=0);
+ int addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId=0);
int addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId=0);
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
int addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId=0);
+
+ // internal alignment constraints
+ int addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId=0);
+ int addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0);
+ int addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0);
+ int addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId=0);
+ int addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, int tagId=0);
+ int addConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &p1, InternalAlignmentType alignmentType, int tagId=0);
+ int addConstraintInternalAlignmentEllipseMajorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId=0);
+ int addConstraintInternalAlignmentEllipseMinorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId=0);
+ int addConstraintInternalAlignmentEllipseFocus1(ArcOfEllipse &a, Point &p1, int tagId=0);
+ int addConstraintInternalAlignmentEllipseFocus2(ArcOfEllipse &a, Point &p1, int tagId=0);
+
void rescaleConstraint(int id, double coeff);
void declareUnknowns(VEC_pD ¶ms);
diff --git a/src/Mod/Sketcher/App/freegcs/Geo.h b/src/Mod/Sketcher/App/freegcs/Geo.h
index 24ed45f1b6..b44daa73ce 100644
--- a/src/Mod/Sketcher/App/freegcs/Geo.h
+++ b/src/Mod/Sketcher/App/freegcs/Geo.h
@@ -65,6 +65,28 @@ namespace GCS
Point center;
double *rad;
};
+
+ class Ellipse
+ {
+ public:
+ Ellipse(){ radmin = 0;}
+ Point center;
+ Point focus1; //+x
+ double *radmin;
+ };
+
+ class ArcOfEllipse
+ {
+ public:
+ ArcOfEllipse(){startAngle=0;endAngle=0;radmin = 0;}
+ double *startAngle;
+ double *endAngle;
+ double *radmin;
+ Point start;
+ Point end;
+ Point center;
+ Point focus1; //+x
+ };
} //namespace GCS
diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp
index 4dc2d0a25c..347067c800 100644
--- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp
+++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp
@@ -147,8 +147,8 @@ bool isSimpleVertex(const Sketcher::SketchObject* Obj, int GeoId, PointPos PosId
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId())
return true;
else if (PosId == Sketcher::mid &&
- (geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
- geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()))
+ (geo->getTypeId() == Part::GeomCircle::getClassTypeId() || // TODO: ellipse
+ geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()))
return true;
else
return false;
@@ -802,8 +802,10 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
// Currently only accepts line segments and circles
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
- geom->getTypeId() == Part::GeomCircle::getClassTypeId() ||
- geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) {
+ geom->getTypeId() == Part::GeomCircle::getClassTypeId() || // TODO: ellipse
+ geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
+ geom->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
+ geom->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ) {
openCommand("add point on object constraint");
Gui::Command::doCommand(
@@ -1287,7 +1289,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
}
else if (geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId() &&
- geo2->getTypeId() != Part::GeomCircle::getClassTypeId()) {
+ geo2->getTypeId() != Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected edge should be an arc, line or circle."));
return;
@@ -1490,7 +1492,7 @@ void CmdSketcherConstrainRadius::activated(int iMsg)
double radius = arc->getRadius();
geoIdRadiusMap.push_back(std::make_pair(GeoId, radius));
}
- else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geom);
double radius = circle->getRadius();
geoIdRadiusMap.push_back(std::make_pair(GeoId, radius));
@@ -1615,7 +1617,6 @@ bool CmdSketcherConstrainRadius::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
-
DEF_STD_CMD_A(CmdSketcherConstrainAngle);
CmdSketcherConstrainAngle::CmdSketcherConstrainAngle()
@@ -1764,7 +1765,6 @@ bool CmdSketcherConstrainAngle::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
-
DEF_STD_CMD_A(CmdSketcherConstrainEqual);
CmdSketcherConstrainEqual::CmdSketcherConstrainEqual()
@@ -1838,7 +1838,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
lineSel = true;
else if (geo->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())
arcSel = true;
- else if (geo->getTypeId() != Part::GeomCircle::getClassTypeId())
+ else if (geo->getTypeId() != Part::GeomCircle::getClassTypeId()) // TODO: ellipse
circSel = true;
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@@ -2027,7 +2027,412 @@ bool CmdSketcherConstrainSymmetric::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
+DEF_STD_CMD_A(CmdSketcherConstrainInternalAlignment);
+CmdSketcherConstrainInternalAlignment::CmdSketcherConstrainInternalAlignment()
+ :Command("Sketcher_ConstrainInternalAlignment")
+{
+ sAppModule = "Sketcher";
+ sGroup = QT_TR_NOOP("Sketcher");
+ sMenuText = QT_TR_NOOP("Constrain InternalAlignment");
+ sToolTipText = QT_TR_NOOP("Constraint an element to be aligned with the internal geometry of another element");
+ sWhatsThis = sToolTipText;
+ sStatusTip = sToolTipText;
+ sPixmap = "Constraint_InternalAlignment";
+ sAccel = "Ctrl+A";
+ eType = ForEdit;
+}
+
+void CmdSketcherConstrainInternalAlignment::activated(int iMsg)
+{
+ // get the selection
+ std::vector selection = getSelection().getSelectionEx();
+
+ // only one sketch with its subelements are allowed to be selected
+ if (selection.size() != 1) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Select at least one ellipse and one edge from the sketch."));
+ return;
+ }
+
+ // get the needed lists and objects
+ const std::vector &SubNames = selection[0].getSubNames();
+ Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject());
+
+ // go through the selected subelements
+ if (SubNames.size() < 2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Select at least one ellipse and one edge from the sketch."));
+ return;
+ }
+
+ std::vector pointids;
+ std::vector lineids;
+ std::vector ellipseids;
+ std::vector arcsofellipseids;
+
+ bool hasAlreadyExternal = false;
+
+ for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
+
+ int GeoId;
+ Sketcher::PointPos PosId;
+ getIdsFromName(*it, Obj, GeoId, PosId);
+
+ if (GeoId < 0) {
+ if (GeoId == -1 || GeoId == -2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Sketch axes cannot be used in internal alignment constraint"));
+ return;
+ }
+ else if (hasAlreadyExternal) {
+ checkBothExternal(-1,-2); // just for printing the error message
+ return;
+ }
+ else
+ hasAlreadyExternal = true;
+ }
+
+ const Part::Geometry *geo = Obj->getGeometry(GeoId);
+
+ if (geo->getTypeId() == Part::GeomPoint::getClassTypeId())
+ pointids.push_back(GeoId);
+ else if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId())
+ lineids.push_back(GeoId);
+ else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId())
+ ellipseids.push_back(GeoId);
+ else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId())
+ arcsofellipseids.push_back(GeoId);
+ else {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Select two or more compatible edges"));
+ return;
+ }
+ }
+
+ int GeoId;
+ Sketcher::PointPos PosId;
+ getIdsFromName(SubNames[SubNames.size()-1], Obj, GeoId, PosId); // last selected element
+
+ const Part::Geometry *geo = Obj->getGeometry(GeoId);
+
+ // Currently it is only supported for ellipses
+ if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+
+ // Priority list
+ // EllipseMajorDiameter = 1,
+ // EllipseMinorDiameter = 2,
+ // EllipseFocus1 = 3,
+ // EllipseFocus2 = 4
+
+ if(ellipseids.size()>1){
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("You can not internally constraint an ellipse on other ellipse. Select only one ellipse."));
+ return;
+ }
+
+ if (pointids.size()>2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Maximum 2 points are supported."));
+ return;
+ }
+
+ if (lineids.size()>2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Maximum 2 lines are supported."));
+ return;
+ }
+
+ // look for which internal constraints are already applied
+ bool major=false;
+ bool minor=false;
+ bool focus1=false;
+ bool focus2=false;
+ bool extra_elements=false;
+
+ const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
+
+ for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
+ it != vals.end(); ++it) {
+ if((*it)->Type == Sketcher::InternalAlignment && (*it)->First == GeoId)
+ {
+ switch((*it)->AlignmentType){
+ case Sketcher::EllipseMajorDiameter:
+ major=true;
+ break;
+ case Sketcher::EllipseMinorDiameter:
+ minor=true;
+ break;
+ case Sketcher::EllipseFocus1:
+ focus1=true;
+ break;
+ case Sketcher::EllipseFocus2:
+ focus2=true;
+ break;
+ }
+ }
+ }
+
+ if(major && minor && focus1 && focus2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Nothing to constraint"),
+ QObject::tr("Currently all internal geometry of the ellipse is already exposed."));
+ return;
+ }
+
+ if((!(focus1 && focus2) && pointids.size()>=1) || // if some element is missing and we are adding an element of that type
+ (!(major && minor) && lineids.size()>=1) ){
+
+ openCommand("add internal alignment constraint");
+
+ if(pointids.size()>=1)
+ {
+ if(!focus1) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[0],Sketcher::start,ellipseids[0]);
+ }
+ else if(!focus2) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[0],Sketcher::start,ellipseids[0]);
+ focus2=true;
+ }
+ else
+ extra_elements=true;
+ }
+
+ if(pointids.size()==2)
+ {
+ if(!focus2) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[1],Sketcher::start,ellipseids[0]);
+ }
+ else
+ extra_elements=true;
+ }
+
+ if(lineids.size()>=1)
+ {
+ if(!major) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[0],ellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[0]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
+
+ }
+ else if(!minor) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[0],ellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[0]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
+
+ minor=true;
+ }
+ else
+ extra_elements=true;
+ }
+ if(lineids.size()==2)
+ {
+ if(!minor){
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[1],ellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[1]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[1]);
+ }
+ else
+ extra_elements=true;
+ }
+
+ // finish the transaction and update
+ commitCommand();
+ updateActive();
+
+ if(extra_elements){
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
+ QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
+ }
+
+ // clear the selection (convenience)
+ getSelection().clearSelection();
+ }
+ else {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
+ QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
+ }
+ }
+ else if(geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
+
+ // Priority list
+ // EllipseMajorDiameter = 1,
+ // EllipseMinorDiameter = 2,
+ // EllipseFocus1 = 3,
+ // EllipseFocus2 = 4
+
+ if(arcsofellipseids.size()>1){
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("You can not internally constraint an arc of ellipse on other arc of ellipse. Select only one arc of ellipse."));
+ return;
+ }
+
+ if(ellipseids.size()>0){
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("You can not internally constraint an ellipse on an arc of ellipse. Select only one ellipse or arc of ellipse."));
+ return;
+ }
+
+ if (pointids.size()>2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Maximum 2 points are supported."));
+ return;
+ }
+
+ if (lineids.size()>2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Maximum 2 lines are supported."));
+ return;
+ }
+
+ // look for which internal constraints are already applied
+ bool major=false;
+ bool minor=false;
+ bool focus1=false;
+ bool focus2=false;
+ bool extra_elements=false;
+
+ const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
+
+ for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
+ it != vals.end(); ++it) {
+ if((*it)->Type == Sketcher::InternalAlignment && (*it)->First == GeoId)
+ {
+ switch((*it)->AlignmentType){
+ case Sketcher::EllipseMajorDiameter:
+ major=true;
+ break;
+ case Sketcher::EllipseMinorDiameter:
+ minor=true;
+ break;
+ case Sketcher::EllipseFocus1:
+ focus1=true;
+ break;
+ case Sketcher::EllipseFocus2:
+ focus2=true;
+ break;
+ }
+ }
+ }
+
+ if(major && minor && focus1 && focus2) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Nothing to constraint"),
+ QObject::tr("Currently all internal geometry of the arc of ellipse is already exposed."));
+ return;
+ }
+
+ if((!(focus1 && focus2) && pointids.size()>=1) || // if some element is missing and we are adding an element of that type
+ (!(major && minor) && lineids.size()>=1) ){
+
+ openCommand("add internal alignment constraint");
+
+ if(pointids.size()>=1)
+ {
+ if(!focus1) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[0],Sketcher::start,arcsofellipseids[0]);
+ }
+ else if(!focus2) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[0],Sketcher::start,arcsofellipseids[0]);
+ focus2=true;
+ }
+ else
+ extra_elements=true;
+ }
+
+ if(pointids.size()==2)
+ {
+ if(!focus2) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
+ selection[0].getFeatName(),pointids[1],Sketcher::start,arcsofellipseids[0]);
+ }
+ else
+ extra_elements=true;
+ }
+
+ if(lineids.size()>=1)
+ {
+ if(!major) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[0],arcsofellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[0]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
+
+ }
+ else if(!minor) {
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[0],arcsofellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[0]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
+
+ minor=true;
+ }
+ else
+ extra_elements=true;
+ }
+ if(lineids.size()==2)
+ {
+ if(!minor){
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),lineids[1],arcsofellipseids[0]);
+
+ const Part::GeomLineSegment *geo = static_cast(Obj->getGeometry(lineids[1]));
+
+ if(!geo->Construction)
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[1]);
+ }
+ else
+ extra_elements=true;
+ }
+
+ // finish the transaction and update
+ commitCommand();
+ updateActive();
+
+ if(extra_elements){
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
+ QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
+ }
+
+ // clear the selection (convenience)
+ getSelection().clearSelection();
+ }
+ else {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
+ QObject::tr("More elements than possible for the given arc of ellipse were provided. These were ignored."));
+ }
+ }
+ else {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Currently internal geometry is only supported for ellipse or arc of ellipse. The last selected element must be an ellipse or an arc of ellipse."));
+ }
+}
+
+bool CmdSketcherConstrainInternalAlignment::isActive(void)
+{
+ return isCreateConstraintActive( getActiveGuiDocument() );
+}
void CreateSketcherCommandsConstraints(void)
{
@@ -2048,4 +2453,5 @@ void CreateSketcherCommandsConstraints(void)
rcCmdMgr.addCommand(new CmdSketcherConstrainEqual());
rcCmdMgr.addCommand(new CmdSketcherConstrainPointOnObject());
rcCmdMgr.addCommand(new CmdSketcherConstrainSymmetric());
+ rcCmdMgr.addCommand(new CmdSketcherConstrainInternalAlignment());
}
diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
index 82cb3de2aa..889baf358e 100644
--- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
+++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
@@ -1793,7 +1793,580 @@ bool CmdSketcherCreateCircle::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
+// ======================================================================================
+/* XPM */
+static const char *cursor_createellipse[]={
+"32 32 3 1",
+"+ c white",
+"# c red",
+". c None",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"................................",
+"+++++...+++++...................",
+"................................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+..............#####......",
+"..................###.....#.....",
+"...............###.......##.....",
+".............##..........##.....",
+"...........##............##.....",
+"..........##.....###....##......",
+".........##.....#.#.....#.......",
+"........##.....###....##........",
+"........##...........##.........",
+".......##..........###..........",
+"......##........####............",
+"......#.....####................",
+"......######....................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
+
+class DrawSketchHandlerEllipse : public DrawSketchHandler
+{
+public:
+ DrawSketchHandlerEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
+ virtual ~DrawSketchHandlerEllipse(){}
+ /// mode table
+ enum SelectMode {
+ STATUS_SEEK_First, /**< enum value ----. */
+ STATUS_SEEK_Second, /**< enum value ----. */
+ STATUS_SEEK_Third, /**< enum value ----. */
+ STATUS_Close
+ };
+
+ virtual void activated(ViewProviderSketch *sketchgui)
+ {
+ setCursor(QPixmap(cursor_createellipse),7,7);
+ }
+
+ virtual void mouseMove(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_SEEK_First) {
+ setPositionText(onSketchPos);
+ if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
+ renderSuggestConstraintsCursor(sugConstr1);
+ return;
+ }
+ }
+ else if (Mode==STATUS_SEEK_Second) {
+ double rx0 = onSketchPos.fX - EditCurve[0].fX;
+ double ry0 = onSketchPos.fY - EditCurve[0].fY;
+ for (int i=0; i < 16; i++) {
+ double angle = i*M_PI/16.0;
+ double rx = rx0 * cos(angle) + ry0 * sin(angle);
+ double ry = -rx0 * sin(angle) + ry0 * cos(angle);
+ EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
+ EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
+ }
+ EditCurve[33] = EditCurve[1];
+
+ // Display radius for user
+ float radius = (onSketchPos - EditCurve[0]).Length();
+
+ SbString text;
+ text.sprintf(" (%.1fR,%.1fR)", radius,radius);
+ setPositionText(onSketchPos, text);
+
+ sketchgui->drawEdit(EditCurve);
+ if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
+ AutoConstraint::CURVE)) {
+ renderSuggestConstraintsCursor(sugConstr2);
+ return;
+ }
+ }
+ else if (Mode==STATUS_SEEK_Third) {
+ double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
+ double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
+
+ // angle between the major axis of the ellipse and the X axis
+ double a = (EditCurve[1]-EditCurve[0]).Length();
+ double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
+
+ // This is the angle at cursor point
+ double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
+ double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
+
+ for (int i=1; i < 16; i++) {
+ double angle = i*M_PI/16.0;
+ double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
+ double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
+ EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
+ EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
+ }
+ EditCurve[33] = EditCurve[1];
+ EditCurve[17] = EditCurve[16];
+
+ // Display radius for user
+ SbString text;
+ text.sprintf(" (%.1fR,%.1fR)", a, b);
+ setPositionText(onSketchPos, text);
+
+ sketchgui->drawEdit(EditCurve);
+ if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
+ AutoConstraint::CURVE)) {
+ renderSuggestConstraintsCursor(sugConstr2);
+ return;
+ }
+ }
+ applyCursor();
+ }
+
+ virtual bool pressButton(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_SEEK_First){
+ EditCurve[0] = onSketchPos;
+ Mode = STATUS_SEEK_Second;
+ }
+ else if(Mode==STATUS_SEEK_Second) {
+ EditCurve[1] = onSketchPos;
+ Mode = STATUS_SEEK_Third;
+ }
+ else {
+ EditCurve[2] = onSketchPos;
+ Mode = STATUS_Close;
+ }
+ return true;
+ }
+
+ virtual bool releaseButton(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_Close) {
+ unsetCursor();
+ resetPositionText();
+
+ // angle between the major axis of the ellipse and the X axis
+ double a = (EditCurve[1]-EditCurve[0]).Length();
+ double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
+
+ // This is the angle at cursor point
+ double angleatpoint = acos((EditCurve[2].fX-EditCurve[0].fX+(EditCurve[2].fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
+ double b=(EditCurve[2].fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
+
+ Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
+ // We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
+ // Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
+
+ if(a>b)
+ {
+ // force second semidiameter to be perpendicular to first semidiamater
+ majAxisDir = EditCurve[1] - EditCurve[0];
+ Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
+ perp.Normalize();
+ perp.Scale(abs(b));
+ minAxisPoint = EditCurve[0]+perp;
+ majAxisPoint = EditCurve[0]+majAxisDir;
+ }
+ else {
+ // force second semidiameter to be perpendicular to first semidiamater
+ minAxisDir = EditCurve[1] - EditCurve[0];
+ Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
+ perp.Normalize();
+ perp.Scale(abs(b));
+ majAxisPoint = EditCurve[0]+perp;
+ minAxisPoint = EditCurve[0]+minAxisDir;
+ }
+
+ Gui::Command::openCommand("Add sketch ellipse");
+ Gui::Command::doCommand(Gui::Command::Doc,
+ "App.ActiveDocument.%s.addGeometry(Part.Ellipse"
+ "(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
+ sketchgui->getObject()->getNameInDocument(),
+ majAxisPoint.fX, majAxisPoint.fY,
+ minAxisPoint.fX, minAxisPoint.fY,
+ EditCurve[0].fX, EditCurve[0].fY);
+
+ Gui::Command::commitCommand();
+ Gui::Command::updateActive();
+
+ // add auto constraints for the center point
+ if (sugConstr1.size() > 0) {
+ createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
+ sugConstr1.clear();
+ }
+
+ // add suggested constraints for circumference
+ if (sugConstr2.size() > 0) {
+ //createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
+ sugConstr2.clear();
+ }
+
+ EditCurve.clear();
+ sketchgui->drawEdit(EditCurve);
+ sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
+ }
+ return true;
+ }
+protected:
+ SelectMode Mode;
+ std::vector EditCurve;
+ std::vector sugConstr1, sugConstr2;
+
+};
+
+DEF_STD_CMD_A(CmdSketcherCreateEllipse);
+
+CmdSketcherCreateEllipse::CmdSketcherCreateEllipse()
+ : Command("Sketcher_CreateEllipse")
+{
+ sAppModule = "Sketcher";
+ sGroup = QT_TR_NOOP("Sketcher");
+ sMenuText = QT_TR_NOOP("Create ellipse");
+ sToolTipText = QT_TR_NOOP("Create an ellipse in the sketch");
+ sWhatsThis = sToolTipText;
+ sStatusTip = sToolTipText;
+ sPixmap = "Sketcher_CreateEllipse";
+ eType = ForEdit;
+}
+
+void CmdSketcherCreateEllipse::activated(int iMsg)
+{
+ ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerEllipse() );
+}
+
+bool CmdSketcherCreateEllipse::isActive(void)
+{
+ return isCreateGeoActive(getActiveGuiDocument());
+}
+
+// ======================================================================================
+
+/* XPM */
+static const char *cursor_createarcofellipse[]={
+"32 32 3 1",
+"+ c white",
+"# c red",
+". c None",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"......+.........................",
+"................................",
+"+++++...+++++...................",
+"................................",
+"......+.........................",
+"......+.........................",
+"......+................##.......",
+"......+..............##.........",
+"......+............##...........",
+"......+...........##............",
+"................##..............",
+"...............##...............",
+"..............##................",
+".............###................",
+"............##.........###......",
+"...........##.........#.#.......",
+"...........##.........###.......",
+"..........##....................",
+".........##.....................",
+"........##......................",
+"........##......................",
+"........##......................",
+"........#.....####..............",
+"........######..................",
+"................................",
+"................................",
+"................................",
+"................................"};
+
+class DrawSketchHandlerArcOfEllipse : public DrawSketchHandler
+{
+public:
+ DrawSketchHandlerArcOfEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
+ virtual ~DrawSketchHandlerArcOfEllipse(){}
+ /// mode table
+ enum SelectMode {
+ STATUS_SEEK_First, /**< enum value ----. */
+ STATUS_SEEK_Second, /**< enum value ----. */
+ STATUS_SEEK_Third, /**< enum value ----. */
+ STATUS_SEEK_Fourth, /**< enum value ----. */
+ STATUS_Close
+ };
+
+ virtual void activated(ViewProviderSketch *sketchgui)
+ {
+ setCursor(QPixmap(cursor_createarcofellipse),7,7);
+ }
+
+ virtual void mouseMove(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_SEEK_First) {
+ setPositionText(onSketchPos);
+ if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
+ renderSuggestConstraintsCursor(sugConstr1);
+ return;
+ }
+ }
+ else if (Mode==STATUS_SEEK_Second) {
+ double rx0 = onSketchPos.fX - EditCurve[0].fX;
+ double ry0 = onSketchPos.fY - EditCurve[0].fY;
+ for (int i=0; i < 16; i++) {
+ double angle = i*M_PI/16.0;
+ double rx = rx0 * cos(angle) + ry0 * sin(angle);
+ double ry = -rx0 * sin(angle) + ry0 * cos(angle);
+ EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
+ EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
+ }
+ EditCurve[33] = EditCurve[1];
+
+ // Display radius for user
+ float radius = (onSketchPos - EditCurve[0]).Length();
+
+ SbString text;
+ text.sprintf(" (%.1fR,%.1fR)", radius,radius);
+ setPositionText(onSketchPos, text);
+
+ sketchgui->drawEdit(EditCurve);
+ if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
+ AutoConstraint::CURVE)) {
+ renderSuggestConstraintsCursor(sugConstr2);
+ return;
+ }
+ }
+ else if (Mode==STATUS_SEEK_Third) {
+ double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
+ double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
+
+ // angle between the major axis of the ellipse and the X axis
+ double a = (EditCurve[1]-EditCurve[0]).Length();
+ double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
+
+ // This is the angle at cursor point
+ double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
+ double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
+
+ for (int i=1; i < 16; i++) {
+ double angle = i*M_PI/16.0;
+ double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
+ double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
+ EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
+ EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
+ }
+ EditCurve[33] = EditCurve[1];
+ EditCurve[17] = EditCurve[16];
+
+ // Display radius for user
+ SbString text;
+ text.sprintf(" (%.1fR,%.1fR)", a, b);
+ setPositionText(onSketchPos, text);
+
+ sketchgui->drawEdit(EditCurve);
+ if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f),
+ AutoConstraint::CURVE)) {
+ renderSuggestConstraintsCursor(sugConstr3);
+ return;
+ }
+ }
+ else if (Mode==STATUS_SEEK_Fourth) { // here we differ from ellipse creation
+
+ double rx0 = axisPoint.fX - centerPoint.fX; // first semidiameter
+ double ry0 = axisPoint.fY - centerPoint.fY; // first semidiameter
+
+ // angle between the major axis of the ellipse and the X axis
+ double a = (axisPoint-centerPoint).Length();
+ double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
+
+ // This is the angle at cursor point
+ double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
+ double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
+
+ double rxs = startingPoint.fX - centerPoint.fX;
+ double rys = startingPoint.fY - centerPoint.fY;
+ startAngle = atan2(a*(rys*cos(phi)-rxs*sin(phi)), b*(rxs*cos(phi)+rys*sin(phi))); // eccentric anomaly angle
+
+ double angle1 = atan2(a*((onSketchPos.fY - centerPoint.fY)*cos(phi)-(onSketchPos.fX - centerPoint.fX)*sin(phi)),
+ b*((onSketchPos.fX - centerPoint.fX)*cos(phi)+(onSketchPos.fY - centerPoint.fY)*sin(phi)))- startAngle;
+
+ double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
+ arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
+
+ for (int i=0; i < 34; i++) {
+ double angle = startAngle+i*arcAngle/34.0;
+ double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
+ double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
+ EditCurve[i] = Base::Vector2D(centerPoint.fX + rx, centerPoint.fY + ry);
+ }
+// EditCurve[33] = EditCurve[1];
+// EditCurve[17] = EditCurve[16];
+
+ // Display radii and angle for user
+ SbString text;
+ text.sprintf(" (%.1fR,%.1fR,%.1fdeg)", a, b, arcAngle * 180 / M_PI);
+ setPositionText(onSketchPos, text);
+
+ sketchgui->drawEdit(EditCurve);
+ if (seekAutoConstraint(sugConstr4, onSketchPos, Base::Vector2D(0.f,0.f),
+ AutoConstraint::CURVE)) {
+ renderSuggestConstraintsCursor(sugConstr4);
+ return;
+ }
+ }
+
+
+
+ applyCursor();
+ }
+
+ virtual bool pressButton(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_SEEK_First){
+ EditCurve[0] = onSketchPos;
+ centerPoint = onSketchPos;
+ Mode = STATUS_SEEK_Second;
+ }
+ else if(Mode==STATUS_SEEK_Second) {
+ EditCurve[1] = onSketchPos;
+ axisPoint = onSketchPos;
+ Mode = STATUS_SEEK_Third;
+ }
+ else if(Mode==STATUS_SEEK_Third) {
+ startingPoint = onSketchPos;
+ arcAngle = 0.;
+ arcAngle_t= 0.;
+ Mode = STATUS_SEEK_Fourth;
+ }
+ else { // Fourth
+ endPoint = onSketchPos;
+
+ Mode = STATUS_Close;
+ }
+ return true;
+ }
+
+ virtual bool releaseButton(Base::Vector2D onSketchPos)
+ {
+ if (Mode==STATUS_Close) {
+ unsetCursor();
+ resetPositionText();
+
+ // angle between the major axis of the ellipse and the X axis
+ double a = (axisPoint-centerPoint).Length();
+ double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
+
+ // This is the angle at cursor point
+ double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
+ double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
+
+ double angle1 = atan2(a*((endPoint.fY - centerPoint.fY)*cos(phi)-(endPoint.fX - centerPoint.fX)*sin(phi)),
+ b*((endPoint.fX - centerPoint.fX)*cos(phi)+(endPoint.fY - centerPoint.fY)*sin(phi)))- startAngle;
+
+ double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
+ arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
+
+ if (arcAngle > 0)
+ endAngle = startAngle + arcAngle;
+ else {
+ endAngle = startAngle;
+ startAngle += arcAngle;
+ }
+
+ Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
+ // We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
+ // Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
+
+ if(a>b)
+ {
+ // force second semidiameter to be perpendicular to first semidiamater
+ majAxisDir = axisPoint - centerPoint;
+ Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
+ perp.Normalize();
+ perp.Scale(abs(b));
+ minAxisPoint = centerPoint+perp;
+ majAxisPoint = centerPoint+majAxisDir;
+ }
+ else {
+ // force second semidiameter to be perpendicular to first semidiamater
+ minAxisDir = axisPoint - centerPoint;
+ Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
+ perp.Normalize();
+ perp.Scale(abs(b));
+ majAxisPoint = centerPoint+perp;
+ minAxisPoint = centerPoint+minAxisDir;
+ endAngle += M_PI/2;
+ startAngle += M_PI/2;
+ }
+
+ //startAngle=-M_PI/4;
+ //endAngle=M_PI/4;
+
+ Gui::Command::openCommand("Add sketch arc of ellipse");
+ Gui::Command::doCommand(Gui::Command::Doc,
+ "App.ActiveDocument.%s.addGeometry(Part.ArcOfEllipse"
+ "(Part.Ellipse(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)),"
+ "%f,%f))",
+ sketchgui->getObject()->getNameInDocument(),
+ majAxisPoint.fX, majAxisPoint.fY,
+ minAxisPoint.fX, minAxisPoint.fY,
+ centerPoint.fX, centerPoint.fY,
+ startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
+
+ Gui::Command::commitCommand();
+ Gui::Command::updateActive();
+
+ // add auto constraints for the center point
+ if (sugConstr1.size() > 0) {
+ createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
+ sugConstr1.clear();
+ }
+
+ // add suggested constraints for circumference
+ if (sugConstr2.size() > 0) {
+ //createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
+ sugConstr2.clear();
+ }
+
+ EditCurve.clear();
+ sketchgui->drawEdit(EditCurve);
+ sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
+ }
+ return true;
+ }
+protected:
+ SelectMode Mode;
+ std::vector EditCurve;
+ Base::Vector2D centerPoint, axisPoint, startingPoint, endPoint;
+ double rx, ry, startAngle, endAngle, arcAngle, arcAngle_t;
+ std::vector sugConstr1, sugConstr2, sugConstr3, sugConstr4;
+
+};
+
+DEF_STD_CMD_A(CmdSketcherCreateArcOfEllipse);
+
+CmdSketcherCreateArcOfEllipse::CmdSketcherCreateArcOfEllipse()
+ : Command("Sketcher_CreateArcOfEllipse")
+{
+ sAppModule = "Sketcher";
+ sGroup = QT_TR_NOOP("Sketcher");
+ sMenuText = QT_TR_NOOP("Create an arc of ellipse");
+ sToolTipText = QT_TR_NOOP("Create an arc of ellipse in the sketch");
+ sWhatsThis = sToolTipText;
+ sStatusTip = sToolTipText;
+ sPixmap = "Sketcher_Elliptical_Arc";
+ eType = ForEdit;
+}
+
+void CmdSketcherCreateArcOfEllipse::activated(int iMsg)
+{
+ ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerArcOfEllipse() );
+}
+
+bool CmdSketcherCreateArcOfEllipse::isActive(void)
+{
+ return isCreateGeoActive(getActiveGuiDocument());
+}
// ======================================================================================
@@ -2548,6 +3121,7 @@ namespace SketcherGui {
geom->getTypeId() == Part::GeomCircle::getClassTypeId()||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
return true;
+ // TODO: ellipse
}
return false;
}
@@ -2628,6 +3202,7 @@ public:
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId()
+ // TODO: ellipse
) {
try {
Gui::Command::openCommand("Trim edge");
@@ -3548,6 +4123,8 @@ void CreateSketcherCommandsCreateGeo(void)
rcCmdMgr.addCommand(new CmdSketcherCreateCircle());
rcCmdMgr.addCommand(new CmdSketcherCreate3PointCircle());
rcCmdMgr.addCommand(new CmdSketcherCompCreateCircle());
+ rcCmdMgr.addCommand(new CmdSketcherCreateEllipse());
+ rcCmdMgr.addCommand(new CmdSketcherCreateArcOfEllipse());
rcCmdMgr.addCommand(new CmdSketcherCreateLine());
rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
rcCmdMgr.addCommand(new CmdSketcherCreateRectangle());
diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp
index e189b19857..c4d7a19446 100644
--- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp
+++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp
@@ -679,6 +679,285 @@ bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive(void)
return isSketcherAcceleratorActive( getActiveGuiDocument(), true );
}
+DEF_STD_CMD_A(CmdSketcherRestoreInternalAlignmentGeometry);
+
+CmdSketcherRestoreInternalAlignmentGeometry::CmdSketcherRestoreInternalAlignmentGeometry()
+ :Command("Sketcher_RestoreInternalAlignmentGeometry")
+{
+ sAppModule = "Sketcher";
+ sGroup = QT_TR_NOOP("Sketcher");
+ sMenuText = QT_TR_NOOP("Show/hide internal geometry");
+ sToolTipText = QT_TR_NOOP("Show all internal geometry / hide unused internal geometry");
+ sWhatsThis = sToolTipText;
+ sStatusTip = sToolTipText;
+ sPixmap = "Sketcher_Element_Ellipse_All";
+ sAccel = "CTRL+SHIFT+E";
+ eType = ForEdit;
+}
+
+void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg)
+{
+ // get the selection
+ std::vector selection = getSelection().getSelectionEx();
+ Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject());
+
+ // only one sketch with its subelements are allowed to be selected
+ if (selection.size() != 1) {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Select elements from a single sketch."));
+ return;
+ }
+
+ // get the needed lists and objects
+ const std::vector &SubNames = selection[0].getSubNames();
+ const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
+
+ std::string doc_name = Obj->getDocument()->getName();
+ std::string obj_name = Obj->getNameInDocument();
+ std::stringstream ss;
+
+ getSelection().clearSelection();
+
+ // go through the selected subelements
+ for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
+ // only handle edges
+ if (it->size() > 4 && it->substr(0,4) == "Edge") {
+ int GeoId = std::atoi(it->substr(4,4000).c_str()) - 1;
+ const Part::Geometry *geo = Obj->getGeometry(GeoId);
+ // Only for supported types
+ if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
+ // First we search what has to be restored
+ bool major=false;
+ bool minor=false;
+ bool focus1=false;
+ bool focus2=false;
+ bool extra_elements=false;
+
+ int majorelementindex=-1;
+ int minorelementindex=-1;
+ int focus1elementindex=-1;
+ int focus2elementindex=-1;
+
+ const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
+
+ for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
+ it != vals.end(); ++it) {
+ if((*it)->Type == Sketcher::InternalAlignment && (*it)->Second == GeoId)
+ {
+ switch((*it)->AlignmentType){
+ case Sketcher::EllipseMajorDiameter:
+ major=true;
+ majorelementindex=(*it)->First;
+ break;
+ case Sketcher::EllipseMinorDiameter:
+ minor=true;
+ minorelementindex=(*it)->First;
+ break;
+ case Sketcher::EllipseFocus1:
+ focus1=true;
+ focus1elementindex=(*it)->First;
+ break;
+ case Sketcher::EllipseFocus2:
+ focus2=true;
+ focus2elementindex=(*it)->First;
+ break;
+ }
+ }
+ }
+
+ if(major && minor && focus1 && focus2)
+ {
+ // Hide unused geometry here
+ int majorconstraints=0; // number of constraints associated to the geoid of the major axis
+ int minorconstraints=0;
+ int focus1constraints=0;
+ int focus2constraints=0;
+
+ for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
+ it != vals.end(); ++it) {
+
+ if((*it)->Second == majorelementindex || (*it)->First == majorelementindex || (*it)->Third == majorelementindex)
+ majorconstraints++;
+ else if((*it)->Second == minorelementindex || (*it)->First == minorelementindex || (*it)->Third == minorelementindex)
+ minorconstraints++;
+ else if((*it)->Second == focus1elementindex || (*it)->First == focus1elementindex || (*it)->Third == focus1elementindex)
+ focus1constraints++;
+ else if((*it)->Second == focus2elementindex || (*it)->First == focus2elementindex || (*it)->Third == focus2elementindex)
+ focus2constraints++;
+ }
+ // those with less than 2 constraints must be removed
+ if(majorconstraints>=2 && minorconstraints>=2 && focus1constraints>=2 && focus2constraints>=2)
+ return; // nothing to delete
+
+ App::Document* doc = App::GetApplication().getActiveDocument();
+
+ if (!doc) return;
+
+ doc->openTransaction("Delete");
+
+ if(majorconstraints<2) {
+ ss.str(std::string());
+ ss << "Edge" << majorelementindex + 1;
+ Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
+ }
+
+ if(minorconstraints<2) {
+ ss.str(std::string());
+ ss << "Edge" << minorelementindex + 1;
+ Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
+ }
+
+ if(focus1constraints<2) {
+ ss.str(std::string());
+ int vertex = Obj->getVertexIndexGeoPos(focus1elementindex,Sketcher::start);
+ if(vertex>-1){
+ ss << "Vertex" << vertex + 1;
+ Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
+ }
+ }
+
+ if(focus2constraints<2) {
+ ss.str(std::string());
+ int vertex = Obj->getVertexIndexGeoPos(focus2elementindex,Sketcher::start);
+ if(vertex>-1){
+ ss << "Vertex" << vertex + 1;
+ Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
+ }
+ }
+
+ SketcherGui::ViewProviderSketch* vp = dynamic_cast(getActiveGuiDocument()->getInEdit());
+
+ if (vp) {
+ std::vector sel = Gui::Selection().getSelectionEx(doc->getName());
+ vp->onDelete(sel[0].getSubNames());
+ }
+
+
+ doc->commitTransaction();
+ return;
+ }
+
+ Gui::Command::openCommand("Expose ellipse internal geometry");
+
+ int currentgeoid= Obj->getHighestCurveIndex();
+ int incrgeo= 0;
+ int majorindex=-1;
+ int minorindex=-1;
+
+ Base::Vector3d center;
+ double majord;
+ double minord;
+ double phi;
+
+ if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()){
+ const Part::GeomEllipse *ellipse = static_cast(geo);
+
+ center=ellipse->getCenter();
+ majord=ellipse->getMajorRadius();
+ minord=ellipse->getMinorRadius();
+ phi=ellipse->getAngleXU();
+ }
+ else {
+ const Part::GeomArcOfEllipse *aoe = static_cast(geo);
+
+ center=aoe->getCenter();
+ majord=aoe->getMajorRadius();
+ minord=aoe->getMinorRadius();
+ phi=aoe->getAngleXU();
+ }
+
+ majord*=0.99;
+ minord*=0.99;
+
+
+ Base::Vector3d majorpositiveend = center + majord * Base::Vector3d(cos(phi),sin(phi),0);
+ Base::Vector3d majornegativeend = center - majord * Base::Vector3d(cos(phi),sin(phi),0);
+ Base::Vector3d minorpositiveend = center + minord * Base::Vector3d(-sin(phi),cos(phi),0);
+ Base::Vector3d minornegativeend = center - minord * Base::Vector3d(-sin(phi),cos(phi),0);
+
+ double df= sqrt(majord*majord-minord*minord);
+
+ Base::Vector3d focus1P = center + df * Base::Vector3d(cos(phi),sin(phi),0);
+ Base::Vector3d focus2P = center - df * Base::Vector3d(cos(phi),sin(phi),0);
+
+ try{
+ if(!major)
+ {
+ Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
+ Obj->getNameInDocument(),
+ majornegativeend.x,majornegativeend.y,majorpositiveend.x,majorpositiveend.y); // create line for major axis
+
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),currentgeoid+incrgeo+1,GeoId); // constrain major axis
+ majorindex=currentgeoid+incrgeo+1;
+ incrgeo++;
+ }
+ if(!minor)
+ {
+ Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
+ Obj->getNameInDocument(),
+ minorpositiveend.x,minorpositiveend.y,minornegativeend.x,minornegativeend.y); // create line for minor axis
+
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
+ selection[0].getFeatName(),currentgeoid+incrgeo+1,GeoId); // constrain minor axis
+ minorindex=currentgeoid+incrgeo+1;
+ incrgeo++;
+ }
+ if(!focus1)
+ {
+ Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
+ Obj->getNameInDocument(),
+ focus1P.x,focus1P.y);
+
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
+ selection[0].getFeatName(),currentgeoid+incrgeo+1,Sketcher::start,GeoId); // constrain major axis
+ incrgeo++;
+ }
+ if(!focus2)
+ {
+ Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
+ Obj->getNameInDocument(),
+ focus2P.x,focus2P.y);
+
+ Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
+ Obj->getNameInDocument(),currentgeoid+incrgeo+1,Sketcher::start,GeoId); // constrain major axis
+ }
+
+ // Make lines construction lines
+ if(majorindex!=-1){
+ doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",Obj->getNameInDocument(),majorindex);
+ }
+
+ if(minorindex!=-1){
+ doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",Obj->getNameInDocument(),minorindex);
+ }
+
+ Gui::Command::commitCommand();
+ Gui::Command::updateActive();
+
+ }
+ catch (const Base::Exception& e) {
+ Base::Console().Error("%s\n", e.what());
+ Gui::Command::abortCommand();
+ Gui::Command::updateActive();
+ }
+
+ } // if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId())
+ else {
+ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+ QObject::tr("Currently internal geometry is only supported for ellipse and arc of ellipse. The last selected element must be an ellipse or an arc of ellipse."));
+ }
+
+ }
+ }
+}
+
+bool CmdSketcherRestoreInternalAlignmentGeometry::isActive(void)
+{
+ return isSketcherAcceleratorActive( getActiveGuiDocument(), true );
+}
+
+
void CreateSketcherCommandsConstraintAccel(void)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
@@ -692,4 +971,5 @@ void CreateSketcherCommandsConstraintAccel(void)
rcCmdMgr.addCommand(new CmdSketcherSelectRedundantConstraints());
rcCmdMgr.addCommand(new CmdSketcherSelectConflictingConstraints());
rcCmdMgr.addCommand(new CmdSketcherSelectElementsAssociatedWithConstraints());
+ rcCmdMgr.addCommand(new CmdSketcherRestoreInternalAlignmentGeometry());
}
diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp
index 1559de143e..681eeb7b31 100644
--- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp
+++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp
@@ -241,6 +241,27 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &suggested
tangDeviation = projDist;
}
+ } else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ // TODO: Ellipse
+ const Part::GeomEllipse *ellipse = dynamic_cast((*it));
+
+ Base::Vector3d center = ellipse->getCenter();
+ Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
+
+ double radius = ellipse->getMajorRadius();
+
+ Base::Vector3d projPnt(0.f, 0.f, 0.f);
+ projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
+ double projDist = projPnt.Length();
+
+ if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation)) {
+ //Find if nearest
+ if (projDist < tangDeviation) {
+ tangId = i;
+ tangDeviation = projDist;
+ }
+ }
+
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast((*it));
diff --git a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp
index 359504f23f..10bc918bc1 100644
--- a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp
+++ b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp
@@ -72,8 +72,10 @@ void EditDatumDialog::exec(bool atCursor)
{
// Return if constraint doesn't have editable value
if (Constr->Type == Sketcher::Distance ||
- Constr->Type == Sketcher::DistanceX || Constr->Type == Sketcher::DistanceY ||
- Constr->Type == Sketcher::Radius || Constr->Type == Sketcher::Angle) {
+ Constr->Type == Sketcher::DistanceX ||
+ Constr->Type == Sketcher::DistanceY ||
+ Constr->Type == Sketcher::Radius ||
+ Constr->Type == Sketcher::Angle) {
if (sketch->hasConflicts()) {
QMessageBox::critical(qApp->activeWindow(), QObject::tr("Distance constraint"),
diff --git a/src/Mod/Sketcher/Gui/PropertyConstraintListItem.cpp b/src/Mod/Sketcher/Gui/PropertyConstraintListItem.cpp
index 4ff1629957..7ea6dad2db 100644
--- a/src/Mod/Sketcher/Gui/PropertyConstraintListItem.cpp
+++ b/src/Mod/Sketcher/Gui/PropertyConstraintListItem.cpp
@@ -73,7 +73,7 @@ void PropertyConstraintListItem::initialize()
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
- (*it)->Type == Sketcher::Angle) {
+ (*it)->Type == Sketcher::Angle ) {
PropertyUnitItem* item = static_cast(PropertyUnitItem::create());
@@ -146,10 +146,10 @@ QVariant PropertyConstraintListItem::value(const App::Property* prop) const
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
- (*it)->Type == Sketcher::Angle) {
+ (*it)->Type == Sketcher::Angle ) {
Base::Quantity quant;
- if ((*it)->Type == Sketcher::Angle) {
+ if ((*it)->Type == Sketcher::Angle ) {
double datum = Base::toDegrees((*it)->Value);
quant.setUnit(Base::Unit::Angle);
quant.setValue(datum);
@@ -220,7 +220,7 @@ bool PropertyConstraintListItem::event (QEvent* ev)
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
- (*it)->Type == Sketcher::Angle) {
+ (*it)->Type == Sketcher::Angle ) {
// Get the internal name
QString internalName = QString::fromLatin1("Constraint%1").arg(id+1);
diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp
index cfc6b266c8..1a0eb7d219 100644
--- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp
+++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp
@@ -319,14 +319,8 @@ void TaskSketcherConstrains::on_listWidgetConstraints_itemChanged(QListWidgetIte
QString unitStr;
switch(v->Type) {
case Sketcher::Distance:
- unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
- break;
case Sketcher::DistanceX:
- unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
- break;
case Sketcher::DistanceY:
- unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
- break;
case Sketcher::Radius:
unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
break;
@@ -360,10 +354,18 @@ void TaskSketcherConstrains::slotConstraintsChanged(void)
QIcon tang ( Gui::BitmapFactory().pixmap("Constraint_Tangent") );
QIcon dist ( Gui::BitmapFactory().pixmap("Constraint_Length") );
QIcon radi ( Gui::BitmapFactory().pixmap("Constraint_Radius") );
+ QIcon majradi ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Major_Radius") );
+ QIcon minradi ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Minor_Radius") );
QIcon angl ( Gui::BitmapFactory().pixmap("Constraint_InternalAngle") );
+ QIcon ellipseXUAngl ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Axis_Angle") );
QIcon equal( Gui::BitmapFactory().pixmap("Constraint_EqualLength") );
QIcon pntoo( Gui::BitmapFactory().pixmap("Constraint_PointOnObject") );
QIcon symm ( Gui::BitmapFactory().pixmap("Constraint_Symmetric") );
+ QIcon iaellipseminoraxis ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_MinorAxis") );
+ QIcon iaellipsemajoraxis ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_MajorAxis") );
+ QIcon iaellipsefocus1 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus1") );
+ QIcon iaellipsefocus2 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus2") );
+ QIcon iaellipseother ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment") );
assert(sketchView);
// Build up ListView with the constraints
@@ -464,6 +466,27 @@ void TaskSketcherConstrains::slotConstraintsChanged(void)
ui->listWidgetConstraints->addItem(item);
}
break;
+ case Sketcher::InternalAlignment:
+ if (Filter<2 || (Filter==3 && !(*it)->Name.empty()))
+ switch((*it)->AlignmentType){
+ case Sketcher::EllipseMajorDiameter:
+ ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsemajoraxis,name,i-1,(*it)->Type));
+ break;
+ case Sketcher::EllipseMinorDiameter:
+ ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipseminoraxis,name,i-1,(*it)->Type));
+ break;
+ case Sketcher::EllipseFocus1:
+ ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsefocus1,name,i-1,(*it)->Type));
+ break;
+ case Sketcher::EllipseFocus2:
+ ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsefocus2,name,i-1,(*it)->Type));
+ break;
+ case Sketcher::Undef:
+ default:
+ ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipseother,name,i-1,(*it)->Type));
+ break;
+ }
+ break;
default:
ui->listWidgetConstraints->addItem(new ConstraintItem(name,i-1,(*it)->Type));
break;
diff --git a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp
index d4585eefeb..1859888607 100644
--- a/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp
+++ b/src/Mod/Sketcher/Gui/TaskSketcherElements.cpp
@@ -148,7 +148,7 @@ void ElementView::contextMenuEvent (QContextMenuEvent* event)
CONTEXT_ITEM("Constraint_Length","Length Constraint","Sketcher_ConstrainDistance",doLengthConstraint,true)
CONTEXT_ITEM("Constraint_Radius","Radius Constraint","Sketcher_ConstrainRadius",doRadiusConstraint,true)
CONTEXT_ITEM("Constraint_InternalAngle","Angle Constraint","Sketcher_ConstrainAngle",doAngleConstraint,true)
-
+
menu.addSeparator();
CONTEXT_ITEM("Sketcher_AlterConstruction","Toggle construction line","Sketcher_ToggleConstruction",doToggleConstruction,true)
@@ -638,7 +638,12 @@ void TaskSketcherElements::slotElementsChanged(void)
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Point_StartingPoint") );
-
+ QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_Edge_2") );
+ QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_CentrePoint") );
+ QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Edge") );
+ QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Centre_Point") );
+ QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Start_Point") );
+ QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon none( Gui::BitmapFactory().pixmap("Sketcher_Element_SelectionTypeInvalid") );
assert(sketchView);
@@ -654,29 +659,41 @@ void TaskSketcherElements::slotElementsChanged(void)
Base::Type type = (*it)->getTypeId();
ui->listWidgetElements->addItem(new ElementItem(
- (type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
- (type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
- (type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
- (type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
- (type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
- (type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
+ (type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
+ (type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
+ (type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
+ (type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
+ (type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
none,
- type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
- (tr("Point") + QString::fromLatin1("(Edge%1)").arg(i)):
- (QString::fromLatin1("%1-").arg(i)+tr("Point"))) :
- type == Part::GeomLineSegment::getClassTypeId() ? ( isNamingBoxChecked ?
- (tr("Line") + QString::fromLatin1("(Edge%1)").arg(i)):
- (QString::fromLatin1("%1-").arg(i)+tr("Line"))) :
- type == Part::GeomArcOfCircle::getClassTypeId() ? ( isNamingBoxChecked ?
- (tr("Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
- (QString::fromLatin1("%1-").arg(i)+tr("Arc"))) :
- type == Part::GeomCircle::getClassTypeId() ? ( isNamingBoxChecked ?
- (tr("Circle") + QString::fromLatin1("(Edge%1)").arg(i)):
- (QString::fromLatin1("%1-").arg(i)+tr("Circle"))) :
+ type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Point") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Point"))) :
+ type == Part::GeomLineSegment::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Line") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Line"))) :
+ type == Part::GeomArcOfCircle::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Arc"))) :
+ type == Part::GeomCircle::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Circle") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Circle"))) :
+ type == Part::GeomEllipse::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Ellipse") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Ellipse"))) :
+ type == Part::GeomArcOfEllipse::getClassTypeId() ? ( isNamingBoxChecked ?
+ (tr("Elliptical Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
+ (QString::fromLatin1("%1-").arg(i)+tr("Elliptical Arc"))) :
( isNamingBoxChecked ?
(tr("Other") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Other"))),
@@ -749,16 +766,17 @@ void TaskSketcherElements::on_listWidgetElements_filterShortcutPressed()
switch(element)
{
+
case 0: // Edge
- element = ( type == Part::GeomCircle::getClassTypeId() ) ? 3 : 1;
+ element = ( type == Part::GeomCircle::getClassTypeId() || type == Part::GeomEllipse::getClassTypeId() ) ? 3 : 1;
break;
case 1: // StartingPoint
- element = ( type == Part::GeomCircle::getClassTypeId() ) ? 3 :
- ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 2;
+ element = ( type == Part::GeomCircle::getClassTypeId() || type == Part::GeomEllipse::getClassTypeId() ) ? 3 :
+ ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 2;
break;
case 2: // EndPoint
element = ( type == Part::GeomLineSegment::getClassTypeId() ) ? 0 :
- ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 3;
+ ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 3;
break;
case 3: // MidPoint
element = ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 0;
@@ -850,22 +868,34 @@ void TaskSketcherElements::updateIcons(int element)
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Point_StartingPoint") );
+ QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_Edge_2") );
+ QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_CentrePoint") );
+ QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Edge") );
+ QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Centre_Point") );
+ QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Start_Point") );
+ QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon none( Gui::BitmapFactory().pixmap("Sketcher_Element_SelectionTypeInvalid") );
for (int i=0;ilistWidgetElements->count(); i++) {
Base::Type type = static_cast(ui->listWidgetElements->item(i))->GeometryType;
ui->listWidgetElements->item(i)->setIcon(
- (type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
- (type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
- (type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
- (type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
- (type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
- (type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
- (type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
+ (type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
+ (type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
+ (type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
+ (type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
+ (type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
+ (type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
+ (type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
+ (type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
none);
}
}
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
index 145aa11998..589897de39 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
@@ -28,6 +28,7 @@
# include
# include
# include
+# include
# include
# include
# include
@@ -715,7 +716,9 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
- geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
+ geo->getTypeId() == Part::GeomEllipse::getClassTypeId()||
+ geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { // TODO: ellipse
Gui::Command::openCommand("Drag Curve");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.movePoint(%i,%i,App.Vector(%f,%f,0),%i)"
,getObject()->getNameInDocument()
@@ -912,8 +915,10 @@ void ViewProviderSketch::editDoubleClicked(void)
// if its the right constraint
if (Constr->Type == Sketcher::Distance ||
- Constr->Type == Sketcher::DistanceX || Constr->Type == Sketcher::DistanceY ||
- Constr->Type == Sketcher::Radius || Constr->Type == Sketcher::Angle) {
+ Constr->Type == Sketcher::DistanceX ||
+ Constr->Type == Sketcher::DistanceY ||
+ Constr->Type == Sketcher::Radius ||
+ Constr->Type == Sketcher::Angle) {
// Coin's SoIdleSensor causes problems on some platform while Qt seems to work properly (#0001517)
EditDatumDialog *editDatumDialog = new EditDatumDialog(this, *it);
@@ -1161,14 +1166,15 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
p1 = arc->getCenter();
p2 = p1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
}
- else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast(geo);
double radius = circle->getRadius();
p1 = circle->getCenter();
Base::Vector3d tmpDir = Base::Vector3d(toPos.fX, toPos.fY, 0) - p1;
double angle = atan2(tmpDir.y, tmpDir.x);
p2 = p1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
- } else
+ }
+ else
return;
} else
return;
@@ -1815,7 +1821,7 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
}
- } else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ } else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
// ----- Check if circle lies inside box selection -----/
const Part::GeomCircle *circle = dynamic_cast(*it);
pnt0 = circle->getCenter();
@@ -1850,6 +1856,50 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
}
}
+ if (bpolyInside) {
+ ss.clear();
+ ss.str("");
+ ss << "Edge" << GeoId + 1;
+ Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(),ss.str().c_str());
+ }
+ }
+ } else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ // ----- Check if circle lies inside box selection -----/
+ const Part::GeomEllipse *ellipse = dynamic_cast(*it);
+ pnt0 = ellipse->getCenter();
+ VertexId += 1;
+
+ Plm.multVec(pnt0, pnt0);
+ pnt0 = proj(pnt0);
+
+ if (polygon.Contains(Base::Vector2D(pnt0.x, pnt0.y))) {
+ std::stringstream ss;
+ ss << "Vertex" << VertexId + 1;
+ Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
+
+ int countSegments = 12;
+ float segment = float(2 * M_PI) / countSegments;
+
+ // circumscribed polygon radius
+ float a = float(ellipse->getMajorRadius()) / cos(segment/2);
+ float b = float(ellipse->getMinorRadius()) / cos(segment/2);
+ float phi = float(ellipse->getAngleXU());
+
+ bool bpolyInside = true;
+ pnt0 = ellipse->getCenter();
+ float angle = 0.f;
+ for (int i = 0; i < countSegments; ++i, angle += segment) {
+ pnt = Base::Vector3d(pnt0.x + a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi),
+ pnt0.y + a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi),
+ 0.f);
+ Plm.multVec(pnt, pnt);
+ pnt = proj(pnt);
+ if (!polygon.Contains(Base::Vector2D(pnt.x, pnt.y))) {
+ bpolyInside = false;
+ break;
+ }
+ }
+
if (bpolyInside) {
ss.clear();
ss.str("");
@@ -2082,7 +2132,7 @@ void ViewProviderSketch::updateColor(void)
bool hasMaterial = false;
SoMaterial *m;
- if (!hasDatumLabel && type != Sketcher::Coincident) {
+ if (!hasDatumLabel && type != Sketcher::Coincident && type !=InternalAlignment) {
hasMaterial = true;
m = dynamic_cast(s->getChild(CONSTRAINT_SEPARATOR_INDEX_MATERIAL_OR_DATUMLABEL));
}
@@ -2095,9 +2145,9 @@ void ViewProviderSketch::updateColor(void)
m->diffuseColor = SelectColor;
} else if (type == Sketcher::Coincident) {
int index;
- index = edit->ActSketch.getPointId(constraint->First, constraint->FirstPos) + 1;
+ index = edit->ActSketch.getVisiblePointId(constraint->First, constraint->FirstPos) + 1;
if (index >= 0 && index < PtNum) pcolor[index] = SelectColor;
- index = edit->ActSketch.getPointId(constraint->Second, constraint->SecondPos) + 1;
+ index = edit->ActSketch.getVisiblePointId(constraint->Second, constraint->SecondPos) + 1;
if (index >= 0 && index < PtNum) pcolor[index] = SelectColor;
}
} else if (edit->PreselectConstraintSet.count(i)) {
@@ -2735,6 +2785,25 @@ void ViewProviderSketch::draw(bool temp)
edit->CurvIdToGeoId.push_back(GeoId);
Points.push_back(center);
}
+ else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) { // add an ellipse
+ const Part::GeomEllipse *ellipse = dynamic_cast(*it);
+ Handle_Geom_Ellipse curve = Handle_Geom_Ellipse::DownCast(ellipse->handle());
+
+ int countSegments = 50;
+ Base::Vector3d center = ellipse->getCenter();
+ double segment = (2 * M_PI) / countSegments;
+ for (int i=0; i < countSegments; i++) {
+ gp_Pnt pnt = curve->Value(i*segment);
+ Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
+ }
+
+ gp_Pnt pnt = curve->Value(0);
+ Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
+
+ Index.push_back(countSegments+1);
+ edit->CurvIdToGeoId.push_back(GeoId);
+ Points.push_back(center);
+ }
else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { // add an arc
const Part::GeomArcOfCircle *arc = dynamic_cast(*it);
Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle());
@@ -2768,6 +2837,39 @@ void ViewProviderSketch::draw(bool temp)
Points.push_back(end);
Points.push_back(center);
}
+ else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { // add an arc
+ const Part::GeomArcOfEllipse *arc = dynamic_cast(*it);
+ Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle());
+
+ double startangle, endangle;
+ arc->getRange(startangle, endangle);
+ if (startangle > endangle) // if arc is reversed
+ std::swap(startangle, endangle);
+
+ double range = endangle-startangle;
+ int countSegments = std::max(6, int(50.0 * range / (2 * M_PI)));
+ double segment = range / countSegments;
+
+ Base::Vector3d center = arc->getCenter();
+ Base::Vector3d start = arc->getStartPoint();
+ Base::Vector3d end = arc->getEndPoint();
+
+ for (int i=0; i < countSegments; i++) {
+ gp_Pnt pnt = curve->Value(startangle);
+ Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
+ startangle += segment;
+ }
+
+ // end point
+ gp_Pnt pnt = curve->Value(endangle);
+ Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
+
+ Index.push_back(countSegments+1);
+ edit->CurvIdToGeoId.push_back(GeoId);
+ Points.push_back(start);
+ Points.push_back(end);
+ Points.push_back(center);
+ }
else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a bspline
const Part::GeomBSplineCurve *spline = dynamic_cast(*it);
Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast(spline->handle());
@@ -2875,7 +2977,8 @@ Restart:
// root separator for this constraint
SoSeparator *sep = dynamic_cast(edit->constrGroup->getChild(i));
const Constraint *Constr = *it;
-
+
+ bool major_radius = false; // this is checked in the radius to reuse code
// distinquish different constraint types to build up
switch (Constr->Type) {
case Horizontal: // write the new position of the Horizontal constraint Same as vertical position.
@@ -2929,7 +3032,7 @@ Restart:
norm1 = Base::Vector3d(cos(midangle),sin(midangle),0);
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
midpos1 = arc->getCenter() + arc->getRadius() * norm1;
- } else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ } else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo1);
norm1 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
@@ -2950,7 +3053,7 @@ Restart:
norm2 = Base::Vector3d(cos(midangle),sin(midangle),0);
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
midpos2 = arc->getCenter() + arc->getRadius() * norm2;
- } else if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ } else if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo2);
norm2 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
@@ -2996,7 +3099,7 @@ Restart:
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
if (Constr->Type == Equal) {
double r1,r2,angle1,angle2;
- if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo1);
r1 = circle->getRadius();
angle1 = M_PI/4;
@@ -3008,10 +3111,16 @@ Restart:
arc->getRange(startangle, endangle);
angle1 = (startangle + endangle)/2;
midpos1 = arc->getCenter();
+ } else if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ // TODO: ellipse
+ const Part::GeomEllipse *ellipse = dynamic_cast(geo1);
+ r1 = ellipse->getMajorRadius();
+ angle1 = -ellipse->getAngleXU();
+ midpos1 = ellipse->getCenter();
} else
break;
- if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo2);
r2 = circle->getRadius();
angle2 = M_PI/4;
@@ -3023,7 +3132,14 @@ Restart:
arc->getRange(startangle, endangle);
angle2 = (startangle + endangle)/2;
midpos2 = arc->getCenter();
- } else
+ } else if (geo2->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
+ // TODO: ellipse
+ const Part::GeomEllipse *ellipse = dynamic_cast(geo2);
+ r2 = ellipse->getMajorRadius();
+ angle2 = -ellipse->getAngleXU();
+ midpos2 = ellipse->getCenter();
+ }
+ else
break;
norm1 = Base::Vector3d(cos(angle1),sin(angle1),0);
@@ -3196,7 +3312,7 @@ Restart:
const Part::GeomLineSegment *lineSeg = dynamic_cast(geo1);
Base::Vector3d dir = (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Normalize();
Base::Vector3d norm(-dir.y, dir.x, 0);
- if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
+ if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo2);
// tangency between a line and a circle
float length = (circle->getCenter() - lineSeg->getStartPoint())*dir;
@@ -3204,6 +3320,24 @@ Restart:
pos = lineSeg->getStartPoint() + dir * length;
relPos = norm * 1; //TODO Huh?
}
+ else if (geo2->getTypeId()== Part::GeomEllipse::getClassTypeId() ||
+ geo2->getTypeId()== Part::GeomArcOfEllipse::getClassTypeId()) { // TODO: ellipse
+
+ Base::Vector3d center;
+ if(geo2->getTypeId()== Part::GeomEllipse::getClassTypeId()){
+ const Part::GeomEllipse *ellipse = dynamic_cast(geo2);
+ center=ellipse->getCenter();
+ } else {
+ const Part::GeomArcOfEllipse *aoc = dynamic_cast(geo2);
+ center=aoc->getCenter();
+ }
+
+ // tangency between a line and an ellipse
+ float length = (center - lineSeg->getStartPoint())*dir;
+
+ pos = lineSeg->getStartPoint() + dir * length;
+ relPos = norm * 1;
+ }
else if (geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast(geo2);
// tangency between a line and an arc
@@ -3214,7 +3348,7 @@ Restart:
}
}
- if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() &&
+ if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() && // TODO: ellipse
geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle1 = dynamic_cast(geo1);
const Part::GeomCircle *circle2 = dynamic_cast(geo2);
@@ -3223,12 +3357,12 @@ Restart:
pos = circle1->getCenter() + dir * circle1->getRadius();
relPos = dir * 1;
}
- else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
+ else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
std::swap(geo1,geo2);
}
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() &&
- geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
+ geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast(geo1);
const Part::GeomArcOfCircle *arc = dynamic_cast(geo2);
// tangency between a circle and an arc
@@ -3368,7 +3502,7 @@ Restart:
asciiText->pnts.finishEditing();
}
- break;
+ break;
case Radius:
{
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
@@ -3386,13 +3520,14 @@ Restart:
pnt1 = arc->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
}
- else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
+ else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast(geo);
double radius = circle->getRadius();
double angle = (double) Constr->LabelPosition;
pnt1 = circle->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
- } else
+ }
+ else
break;
} else
break;
@@ -3584,6 +3719,12 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
edit->vConstrType.push_back((*it)->Type);
}
break;
+ case InternalAlignment:
+ {
+ // TODO: Implement visual representation (if any)
+ edit->vConstrType.push_back((*it)->Type);
+ }
+ break;
default:
edit->vConstrType.push_back(None);
}
diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp
index c0cd8c3c0e..b49d10be64 100644
--- a/src/Mod/Sketcher/Gui/Workbench.cpp
+++ b/src/Mod/Sketcher/Gui/Workbench.cpp
@@ -136,12 +136,16 @@ inline void SketcherAddWorkspaceArcs(Gui::MenuItem& geom){
geom << "Sketcher_CreateArc"
<< "Sketcher_Create3PointArc"
<< "Sketcher_CreateCircle"
- << "Sketcher_Create3PointCircle";
+ << "Sketcher_Create3PointCircle"
+ << "Sketcher_CreateEllipse"
+ << "Sketcher_CreateArcOfEllipse";
}
template <>
inline void SketcherAddWorkspaceArcs(Gui::ToolBarItem& geom){
geom << "Sketcher_CompCreateArc"
- << "Sketcher_CompCreateCircle";
+ << "Sketcher_CompCreateCircle"
+ << "Sketcher_CreateEllipse"
+ << "Sketcher_CreateArcOfEllipse";
}
template
void SketcherAddWorkspaceRegularPolygon(T& geom);
@@ -177,9 +181,32 @@ inline void SketcherAddWorkbenchGeometries(T& geom){
/*<< "Sketcher_CreateDraftLine"*/;
}
-
template
-inline void SketcherAddWorkbenchConstraints(T& cons){
+inline void SketcherAddWorkbenchConstraints(T& cons);
+
+template <>
+inline void SketcherAddWorkbenchConstraints(Gui::MenuItem& cons){
+ cons << "Sketcher_ConstrainCoincident"
+ << "Sketcher_ConstrainPointOnObject"
+ << "Sketcher_ConstrainVertical"
+ << "Sketcher_ConstrainHorizontal"
+ << "Sketcher_ConstrainParallel"
+ << "Sketcher_ConstrainPerpendicular"
+ << "Sketcher_ConstrainTangent"
+ << "Sketcher_ConstrainEqual"
+ << "Sketcher_ConstrainSymmetric"
+ << "Separator"
+ << "Sketcher_ConstrainLock"
+ << "Sketcher_ConstrainDistanceX"
+ << "Sketcher_ConstrainDistanceY"
+ << "Sketcher_ConstrainDistance"
+ << "Sketcher_ConstrainRadius"
+ << "Sketcher_ConstrainAngle"
+ << "Sketcher_ConstrainInternalAlignment";
+}
+
+template <>
+inline void SketcherAddWorkbenchConstraints(Gui::ToolBarItem& cons){
cons << "Sketcher_ConstrainCoincident"
<< "Sketcher_ConstrainPointOnObject"
<< "Sketcher_ConstrainVertical"
@@ -196,7 +223,6 @@ inline void SketcherAddWorkbenchConstraints(T& cons){
<< "Sketcher_ConstrainDistance"
<< "Sketcher_ConstrainRadius"
<< "Sketcher_ConstrainAngle";
-
}
template
@@ -212,13 +238,15 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel){
<< "Sketcher_SelectHorizontalAxis"
<< "Sketcher_SelectRedundantConstraints"
<< "Sketcher_SelectConflictingConstraints"
- << "Sketcher_SelectElementsAssociatedWithConstraints";
+ << "Sketcher_SelectElementsAssociatedWithConstraints"
+ << "Sketcher_RestoreInternalAlignmentGeometry";
}
template <>
inline void SketcherAddWorkbenchTools(Gui::ToolBarItem& consaccel){
consaccel << "Sketcher_CloseShape"
<< "Sketcher_ConnectLines"
- << "Sketcher_SelectConstraints";
+ << "Sketcher_SelectConstraints"
+ << "Sketcher_RestoreInternalAlignmentGeometry";
}
template