Sketcher New Feature: Ellipse support

- Ellipse introduction button via (center,majaxis extreme, a point in edge), ellipse is always CCW so that Z axis goes in the positive direction of the sketch
- Backwards compatibility with files of previous versions of ellipse not defining a phi angle
- Art by Jim (all the icons you see and the XPMs shown on creation of an ellipse)
- Element Widget support for ellipses
- Box selection for ellipses
- Point on Ellipse constraint based on the gardener's method based on Ulrich's function proposal (radcan simplified, i.e. with simplify_radical sage function)
- Tangent: Ellipse to Line based on DeepSOIC's geometric formulation (radcan simplified)

Sketcher New Feature: Internal Alignment Constraint
- The element to which internal alignment is applied has to be selected last.
- All other elements are added in the order of priority, taking into account existing elements
- Art by Jim (beautiful icons).

Sketcher New Feature: Tool to show/hide/restore the internal geometry of an element
- New functionality for show/hide internal geometry:
  toggles between hiding all unused internal geometry elements and showing all internal geometry.
  The restore function is implicit to the showing all internal geometry

Sketcher New Feature: Arc of Ellipse support
- Part::Geometry + Python implementation
- ArcOfEllipse creation method
- Art by Jim (all the icons you see and the XPMs shown on creation of arc of ellipse elements)
- Sketcher Element widget for ArcOfEllipse.

Bug fix: Select elements associated to constraints works now for foci internal alignment constraints
This commit is contained in:
Abdullah Tahiri
2014-11-11 19:29:45 +01:00
committed by wmayer
parent 193ad19ddb
commit 4946eddc6b
33 changed files with 5024 additions and 147 deletions

View File

@@ -40,6 +40,7 @@
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/GeometryCurvePy.h>
#include <Mod/Part/App/ArcOfCirclePy.h>
#include <Mod/Part/App/ArcOfEllipsePy.h>
#include <Mod/Part/App/CirclePy.h>
#include <Mod/Part/App/EllipsePy.h>
#include <Mod/Part/App/LinePy.h>
@@ -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<double*>::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<const GeomCircle*>(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<const GeomEllipse*>(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<const GeomArcOfCircle*>(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<const GeomArcOfEllipse*>(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<double *> &params = fixed ? FixParameters : Parameters;
// create our own copy
GeomArcOfEllipse *aoe = static_cast<GeomArcOfEllipse*>(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<double *> &params = 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<double *> &params = fixed ? FixParameters : Parameters;
// create our own copy
GeomEllipse *elips = static_cast<GeomEllipse*>(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<GeomEllipse*>(it->geo->clone());
tuple[i] = Py::asObject(new EllipsePy(ellipse));
} else {
} else if (it->type == ArcOfEllipse) {
GeomArcOfEllipse *ellipse = dynamic_cast<GeomArcOfEllipse*>(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 &center = 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<GeomArcOfEllipse*>(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<GeomCircle*>(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<GeomEllipse*>(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 &center = 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 &center = 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 &center = 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<geoId;i++)
if(Geoms[i].type == Ellipse || Geoms[i].type == ArcOfEllipse)
invisiblepoints++;
switch (pos) {
case start:
return Geoms[geoId].startPointId-invisiblepoints;
case end:
return Geoms[geoId].endPointId-invisiblepoints;
case mid:
return Geoms[geoId].midPointId-invisiblepoints;
case none:
break;
}
return -1;
}
Base::Vector3d Sketch::getPoint(int geoId, PointPos pos)
{
geoId = checkGeoId(geoId);