Sketcher: New Feature: Hyperbola/ArcOfHyperbola
=============================================== - ArcOfHyperbola creation method - Solver representation (undefined moving) - SketchObjectPyImp (here we still miss the Part->Partdesign conversion) - Sketch validation for hyperbola - Hyperbola creation method: shows the "proof of concept", but it is very buggy!! Notes: - Missing icons, probably missing geo normal curve implementation - rebasing - - Fixes to adapt Hyperbola to Derivector implementation and make it compile
This commit is contained in:
parent
fde9bded28
commit
590e3fbec6
|
@ -43,6 +43,8 @@
|
|||
#include <Mod/Part/App/ArcOfEllipsePy.h>
|
||||
#include <Mod/Part/App/CirclePy.h>
|
||||
#include <Mod/Part/App/EllipsePy.h>
|
||||
#include <Mod/Part/App/HyperbolaPy.h>
|
||||
#include <Mod/Part/App/ArcOfHyperbolaPy.h>
|
||||
#include <Mod/Part/App/LinePy.h>
|
||||
|
||||
#include <TopoDS.hxx>
|
||||
|
@ -81,6 +83,7 @@ void Sketch::clear(void)
|
|||
Circles.clear();
|
||||
Ellipses.clear();
|
||||
ArcsOfEllipse.clear();
|
||||
ArcsOfHyperbola.clear();
|
||||
|
||||
// deleting the doubles allocated with new
|
||||
for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it)
|
||||
|
@ -172,6 +175,8 @@ const char* nameByType(Sketch::GeoType type)
|
|||
return "ellipse";
|
||||
case Sketch::ArcOfEllipse:
|
||||
return "arcofellipse";
|
||||
case Sketch::ArcOfHyperbola:
|
||||
return "arcofhyperbola";
|
||||
case Sketch::None:
|
||||
default:
|
||||
return "unknown";
|
||||
|
@ -206,6 +211,10 @@ int Sketch::addGeometry(const Part::Geometry *geo, bool fixed)
|
|||
const GeomArcOfEllipse *aoe = static_cast<const GeomArcOfEllipse*>(geo);
|
||||
// create the definition struct for that geom
|
||||
return addArcOfEllipse(*aoe, fixed);
|
||||
} else if (geo->getTypeId() == GeomArcOfHyperbola::getClassTypeId()) { // add an arc of hyperbola
|
||||
const GeomArcOfHyperbola *aoh = dynamic_cast<const GeomArcOfHyperbola*>(geo);
|
||||
// create the definition struct for that geom
|
||||
return addArcOfHyperbola(*aoh, fixed);
|
||||
} else {
|
||||
throw Base::TypeError("Sketch::addGeometry(): Unknown or unsupported type added to a sketch");
|
||||
}
|
||||
|
@ -377,8 +386,6 @@ 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 *> ¶ms = fixed ? FixParameters : Parameters;
|
||||
|
@ -435,8 +442,7 @@ int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool f
|
|||
|
||||
//Points.push_back(f1);
|
||||
|
||||
|
||||
// add the radius parameters
|
||||
// add the radius parameters
|
||||
params.push_back(new double(radmin));
|
||||
double *rmin = params[params.size()-1];
|
||||
params.push_back(new double(startAngle));
|
||||
|
@ -444,8 +450,6 @@ int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool f
|
|||
params.push_back(new double(endAngle));
|
||||
double *a2 = params[params.size()-1];
|
||||
|
||||
|
||||
|
||||
// set the arc for later constraints
|
||||
GCS::ArcOfEllipse a;
|
||||
a.start = p1;
|
||||
|
@ -470,6 +474,92 @@ int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool f
|
|||
return Geoms.size()-1;
|
||||
}
|
||||
|
||||
int Sketch::addArcOfHyperbola(const Part::GeomArcOfHyperbola &hyperbolaSegment, bool fixed)
|
||||
{
|
||||
std::vector<double *> ¶ms = fixed ? FixParameters : Parameters;
|
||||
|
||||
// create our own copy
|
||||
GeomArcOfHyperbola *aoh = static_cast<GeomArcOfHyperbola*>(hyperbolaSegment.clone());
|
||||
// create the definition struct for that geom
|
||||
GeoDef def;
|
||||
def.geo = aoh;
|
||||
def.type = ArcOfHyperbola;
|
||||
|
||||
Base::Vector3d center = aoh->getCenter();
|
||||
Base::Vector3d startPnt = aoh->getStartPoint();
|
||||
Base::Vector3d endPnt = aoh->getEndPoint();
|
||||
double radmaj = aoh->getMajorRadius();
|
||||
double radmin = aoh->getMinorRadius();
|
||||
double phi = aoh->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;
|
||||
aoh->getRange(startAngle, endAngle);
|
||||
|
||||
GCS::Point p1, p2, p3;
|
||||
|
||||
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));
|
||||
double *f1X = params[params.size()-2];
|
||||
double *f1Y = 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);
|
||||
|
||||
// add the radius parameters
|
||||
params.push_back(new double(radmaj));
|
||||
double *rmaj = 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::ArcOfHyperbola a;
|
||||
a.start = p1;
|
||||
a.end = p2;
|
||||
a.center = p3;
|
||||
a.focus.x = f1X;
|
||||
a.focus.y = f1Y;
|
||||
a.radmaj = rmaj;
|
||||
a.startAngle = a1;
|
||||
a.endAngle = a2;
|
||||
def.index = ArcsOfHyperbola.size();
|
||||
ArcsOfHyperbola.push_back(a);
|
||||
|
||||
// store complete set
|
||||
Geoms.push_back(def);
|
||||
|
||||
// arcs require an ArcRules constraint for the end points
|
||||
/*if (!fixed)
|
||||
GCSsys.addConstraintArcOfHyperbolaRules(a);*/
|
||||
|
||||
// return the position of the newly added geometry
|
||||
return Geoms.size()-1;
|
||||
}
|
||||
|
||||
int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
|
||||
{
|
||||
std::vector<double *> ¶ms = fixed ? FixParameters : Parameters;
|
||||
|
@ -607,8 +697,10 @@ Py::Tuple Sketch::getPyGeometry(void) const
|
|||
} else if (it->type == ArcOfEllipse) {
|
||||
GeomArcOfEllipse *ellipse = static_cast<GeomArcOfEllipse*>(it->geo->clone());
|
||||
tuple[i] = Py::asObject(new ArcOfEllipsePy(ellipse));
|
||||
}
|
||||
else {
|
||||
} else if (it->type == ArcOfHyperbola) {
|
||||
GeomArcOfHyperbola *aoh = dynamic_cast<GeomArcOfHyperbola*>(it->geo->clone());
|
||||
tuple[i] = Py::asObject(new ArcOfHyperbolaPy(aoh));
|
||||
} else {
|
||||
// not implemented type in the sketch!
|
||||
}
|
||||
}
|
||||
|
@ -2069,6 +2161,30 @@ bool Sketch::updateGeometry()
|
|||
ellipse->setMajorRadius(radmaj);
|
||||
}
|
||||
ellipse->setMajorAxisDir(fd);
|
||||
} else if (it->type == ArcOfHyperbola) {
|
||||
GCS::ArcOfHyperbola &myArc = ArcsOfHyperbola[it->index];
|
||||
|
||||
GeomArcOfHyperbola *aoh = dynamic_cast<GeomArcOfHyperbola*>(it->geo);
|
||||
|
||||
Base::Vector3d center = Vector3d(*Points[it->midPointId].x, *Points[it->midPointId].y, 0.0);
|
||||
Base::Vector3d f1 = Vector3d(*myArc.focus.x, *myArc.focus.y, 0.0);
|
||||
double radmaj = *myArc.radmaj;
|
||||
|
||||
Base::Vector3d fd=f1-center;
|
||||
double radmin = sqrt(fd*fd-radmaj*radmaj);
|
||||
|
||||
double phi = atan2(fd.y,fd.x);
|
||||
|
||||
aoh->setCenter(center);
|
||||
if ( radmaj >= aoh->getMinorRadius() ){
|
||||
aoh->setMajorRadius(radmaj);
|
||||
aoh->setMinorRadius(radmin);
|
||||
} else {
|
||||
aoh->setMinorRadius(radmin);
|
||||
aoh->setMajorRadius(radmaj);
|
||||
}
|
||||
aoh->setAngleXU(phi);
|
||||
aoh->setRange(*myArc.startAngle, *myArc.endAngle);
|
||||
}
|
||||
} catch (Base::Exception e) {
|
||||
Base::Console().Error("Updating geometry: Error build geometry(%d): %s\n",
|
||||
|
@ -2335,6 +2451,7 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
|||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0,center,-1);
|
||||
}
|
||||
} else if (Geoms[geoId].type == ArcOfEllipse) {
|
||||
|
@ -2348,6 +2465,7 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
|||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0,center,-1);
|
||||
|
||||
} else if (pos == start || pos == end) {
|
||||
|
||||
MoveParameters.resize(4); // x,y,cx,cy
|
||||
|
@ -2358,6 +2476,7 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
|||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0,p,-1);
|
||||
}
|
||||
|
||||
|
@ -2365,9 +2484,46 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
|||
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 == ArcOfHyperbola) {
|
||||
|
||||
GCS::Point ¢er = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0,p1;
|
||||
if (pos == mid || pos == none) {
|
||||
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) {
|
||||
|
||||
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);
|
||||
}
|
||||
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];
|
||||
|
@ -2466,7 +2622,12 @@ 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 == ArcOfHyperbola) {
|
||||
if (pos == start || pos == end || pos == mid || pos == none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
|
||||
return solve();
|
||||
}
|
||||
|
|
|
@ -128,6 +128,8 @@ public:
|
|||
int addEllipse(const Part::GeomEllipse &ellipse, bool fixed=false);
|
||||
/// add an arc of ellipse
|
||||
int addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed=false);
|
||||
/// add an arc of hyperbola
|
||||
int addArcOfHyperbola(const Part::GeomArcOfHyperbola &hyperbolaSegment, bool fixed=false);
|
||||
//@}
|
||||
|
||||
|
||||
|
@ -317,7 +319,7 @@ public:
|
|||
//icstr should be the value returned by addXXXXConstraint
|
||||
//see more info in respective function in GCS.
|
||||
double calculateConstraintError(int icstr) { return GCSsys.calculateConstraintErrorByTag(icstr);}
|
||||
|
||||
|
||||
/// Returns the size of the Geometry
|
||||
int getGeometrySize(void) const {return Geoms.size();}
|
||||
|
||||
|
@ -328,7 +330,8 @@ public:
|
|||
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, // 1 Point(mid), 5 Parameters(x,y,r1,r2,phi) phi=angle xaxis of elipse with respect of sketch xaxis
|
||||
ArcOfEllipse = 6
|
||||
ArcOfEllipse = 6,
|
||||
ArcOfHyperbola = 7
|
||||
};
|
||||
|
||||
float SolveTime;
|
||||
|
@ -375,6 +378,7 @@ protected:
|
|||
std::vector<GCS::Circle> Circles;
|
||||
std::vector<GCS::Ellipse> Ellipses;
|
||||
std::vector<GCS::ArcOfEllipse> ArcsOfEllipse;
|
||||
std::vector<GCS::ArcOfHyperbola> ArcsOfHyperbola;
|
||||
|
||||
bool isInitMove;
|
||||
bool isFine;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
# include <gp_Ax3.hxx>
|
||||
# include <gp_Circ.hxx>
|
||||
# include <gp_Elips.hxx>
|
||||
# include <gp_Hypr.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
|
@ -39,6 +40,7 @@
|
|||
# include <Geom_Plane.hxx>
|
||||
# include <Geom_Circle.hxx>
|
||||
# include <Geom_Ellipse.hxx>
|
||||
# include <Geom_Hyperbola.hxx>
|
||||
# include <Geom_TrimmedCurve.hxx>
|
||||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
# include <BRepOffsetAPI_NormalProjection.hxx>
|
||||
|
@ -494,6 +496,14 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
|
|||
return aoc->getEndPoint(/*emulateCCW=*/true);
|
||||
else if (PosId == mid)
|
||||
return aoc->getCenter();
|
||||
} else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
const Part::GeomArcOfHyperbola *aoh = dynamic_cast<const Part::GeomArcOfHyperbola*>(geo);
|
||||
if (PosId == start)
|
||||
return aoh->getStartPoint();
|
||||
else if (PosId == end)
|
||||
return aoh->getEndPoint();
|
||||
else if (PosId == mid)
|
||||
return aoh->getCenter();
|
||||
}
|
||||
|
||||
return Base::Vector3d();
|
||||
|
@ -1716,6 +1726,176 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
const Part::GeomArcOfHyperbola *aoh = dynamic_cast<const Part::GeomArcOfHyperbola*>(geo);
|
||||
Base::Vector3d center = aoh->getCenter();
|
||||
double startAngle, endAngle;
|
||||
aoh->getRange(startAngle, endAngle);
|
||||
double dir = (startAngle < endAngle) ? 1 : -1; // this is always == 1
|
||||
double arcLength = (endAngle - startAngle)*dir;
|
||||
double theta0 = Base::fmod(
|
||||
atan2(-aoh->getMajorRadius()*((point.x-center.x)*sin(aoh->getAngleXU())-(point.y-center.y)*cos(aoh->getAngleXU())),
|
||||
aoh->getMinorRadius()*((point.x-center.x)*cos(aoh->getAngleXU())+(point.y-center.y)*sin(aoh->getAngleXU()))
|
||||
)- startAngle, 2.f*M_PI); // x0
|
||||
if (GeoId1 >= 0 && GeoId2 >= 0) {
|
||||
double theta1 = Base::fmod(
|
||||
atan2(-aoh->getMajorRadius()*((point1.x-center.x)*sin(aoh->getAngleXU())-(point1.y-center.y)*cos(aoh->getAngleXU())),
|
||||
aoh->getMinorRadius()*((point1.x-center.x)*cos(aoh->getAngleXU())+(point1.y-center.y)*sin(aoh->getAngleXU()))
|
||||
)- startAngle, 2.f*M_PI) * dir; // x1
|
||||
double theta2 = Base::fmod(
|
||||
atan2(-aoh->getMajorRadius()*((point2.x-center.x)*sin(aoh->getAngleXU())-(point2.y-center.y)*cos(aoh->getAngleXU())),
|
||||
aoh->getMinorRadius()*((point2.x-center.x)*cos(aoh->getAngleXU())+(point2.y-center.y)*sin(aoh->getAngleXU()))
|
||||
)- startAngle, 2.f*M_PI) * dir; // x2
|
||||
|
||||
if (theta1 > theta2) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(point1,point2);
|
||||
std::swap(theta1,theta2);
|
||||
}
|
||||
if (theta1 >= 0.001*arcLength && theta2 <= 0.999*arcLength) {
|
||||
// Trim Point between intersection points
|
||||
if (theta1 < theta0 && theta2 > theta0) {
|
||||
int newGeoId = addGeometry(geo);
|
||||
// go through all constraints and replace the point (GeoId,end) with (newGeoId,end)
|
||||
transferConstraints(GeoId, end, newGeoId, end);
|
||||
|
||||
Part::GeomArcOfHyperbola *aoh1 = dynamic_cast<Part::GeomArcOfHyperbola*>(geomlist[GeoId]);
|
||||
Part::GeomArcOfHyperbola *aoh2 = dynamic_cast<Part::GeomArcOfHyperbola*>(geomlist[newGeoId]);
|
||||
aoh1->setRange(startAngle, startAngle + theta1);
|
||||
aoh2->setRange(startAngle + theta2, endAngle);
|
||||
|
||||
// constrain the trimming points on the corresponding geometries
|
||||
Sketcher::Constraint *newConstr = new Sketcher::Constraint();
|
||||
|
||||
// Build Constraints associated with new pair of arcs
|
||||
newConstr->Type = Sketcher::Equal;
|
||||
newConstr->First = GeoId;
|
||||
newConstr->Second = newGeoId;
|
||||
addConstraint(newConstr);
|
||||
|
||||
PointPos secondPos1 = Sketcher::none, secondPos2 = Sketcher::none;
|
||||
ConstraintType constrType1 = Sketcher::PointOnObject, constrType2 = Sketcher::PointOnObject;
|
||||
|
||||
for (std::vector<Constraint *>::const_iterator it=constraints.begin();
|
||||
it != constraints.end(); ++it) {
|
||||
Constraint *constr = *(it);
|
||||
if (secondPos1 == Sketcher::none &&
|
||||
(constr->First == GeoId1 && constr->Second == GeoId)) {
|
||||
constrType1= Sketcher::Coincident;
|
||||
secondPos1 = constr->FirstPos;
|
||||
} else if (secondPos2 == Sketcher::none &&
|
||||
(constr->First == GeoId2 && constr->Second == GeoId)) {
|
||||
constrType2 = Sketcher::Coincident;
|
||||
secondPos2 = constr->FirstPos;
|
||||
}
|
||||
}
|
||||
|
||||
newConstr->Type = constrType1;
|
||||
newConstr->First = GeoId;
|
||||
newConstr->FirstPos = end;
|
||||
newConstr->Second = GeoId1;
|
||||
|
||||
if (constrType1 == Sketcher::Coincident) {
|
||||
newConstr->SecondPos = secondPos1;
|
||||
delConstraintOnPoint(GeoId1, secondPos1, false);
|
||||
}
|
||||
|
||||
addConstraint(newConstr);
|
||||
|
||||
// Reset secondpos in case it was set previously
|
||||
newConstr->SecondPos = Sketcher::none;
|
||||
|
||||
newConstr->Type = constrType2;
|
||||
newConstr->First = newGeoId;
|
||||
newConstr->FirstPos = start;
|
||||
newConstr->Second = GeoId2;
|
||||
|
||||
if (constrType2 == Sketcher::Coincident) {
|
||||
newConstr->SecondPos = secondPos2;
|
||||
delConstraintOnPoint(GeoId2, secondPos2, false);
|
||||
}
|
||||
|
||||
addConstraint(newConstr);
|
||||
|
||||
newConstr->Type = Sketcher::Coincident;
|
||||
newConstr->First = GeoId;
|
||||
newConstr->FirstPos = Sketcher::mid;
|
||||
newConstr->Second = newGeoId;
|
||||
newConstr->SecondPos = Sketcher::mid;
|
||||
addConstraint(newConstr);
|
||||
|
||||
delete newConstr;
|
||||
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
} else if (theta1 < 0.001*arcLength) { // drop the second intersection point
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(point1,point2);
|
||||
} else if (theta2 > 0.999*arcLength) {
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (GeoId1 >= 0) {
|
||||
|
||||
ConstraintType constrType = Sketcher::PointOnObject;
|
||||
PointPos secondPos = Sketcher::none;
|
||||
for (std::vector<Constraint *>::const_iterator it=constraints.begin();
|
||||
it != constraints.end(); ++it) {
|
||||
Constraint *constr = *(it);
|
||||
if ((constr->First == GeoId1 && constr->Second == GeoId)) {
|
||||
constrType = Sketcher::Coincident;
|
||||
secondPos = constr->FirstPos;
|
||||
delConstraintOnPoint(GeoId1, constr->FirstPos, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double theta1 = Base::fmod(
|
||||
atan2(-aoh->getMajorRadius()*((point1.x-center.x)*sin(aoh->getAngleXU())-(point1.y-center.y)*cos(aoh->getAngleXU())),
|
||||
aoh->getMinorRadius()*((point1.x-center.x)*cos(aoh->getAngleXU())+(point1.y-center.y)*sin(aoh->getAngleXU()))
|
||||
)- startAngle, 2.f*M_PI) * dir; // x1
|
||||
|
||||
if (theta1 >= 0.001*arcLength && theta1 <= 0.999*arcLength) {
|
||||
if (theta1 > theta0) { // trim arc start
|
||||
delConstraintOnPoint(GeoId, start, false);
|
||||
Part::GeomArcOfHyperbola *aoe1 = dynamic_cast<Part::GeomArcOfHyperbola*>(geomlist[GeoId]);
|
||||
aoe1->setRange(startAngle + theta1, endAngle);
|
||||
// constrain the trimming point on the corresponding geometry
|
||||
Sketcher::Constraint *newConstr = new Sketcher::Constraint();
|
||||
newConstr->Type = constrType;
|
||||
newConstr->First = GeoId;
|
||||
newConstr->FirstPos = start;
|
||||
newConstr->Second = GeoId1;
|
||||
|
||||
if (constrType == Sketcher::Coincident)
|
||||
newConstr->SecondPos = secondPos;
|
||||
|
||||
addConstraint(newConstr);
|
||||
delete newConstr;
|
||||
return 0;
|
||||
}
|
||||
else { // trim arc end
|
||||
delConstraintOnPoint(GeoId, end, false);
|
||||
Part::GeomArcOfHyperbola *aoe1 = dynamic_cast<Part::GeomArcOfHyperbola*>(geomlist[GeoId]);
|
||||
aoe1->setRange(startAngle, startAngle + theta1);
|
||||
Sketcher::Constraint *newConstr = new Sketcher::Constraint();
|
||||
newConstr->Type = constrType;
|
||||
newConstr->First = GeoId;
|
||||
newConstr->FirstPos = end;
|
||||
newConstr->Second = GeoId1;
|
||||
|
||||
if (constrType == Sketcher::Coincident)
|
||||
newConstr->SecondPos = secondPos;
|
||||
|
||||
addConstraint(newConstr);
|
||||
delete newConstr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -3341,6 +3521,34 @@ void SketchObject::rebuildExternalGeometry(void)
|
|||
ExternalGeo.push_back(circle);
|
||||
} else {
|
||||
throw Base::Exception("BSpline: Not yet supported geometry for external geometry");
|
||||
}
|
||||
} else if (projCurve.GetType() == GeomAbs_Hyperbola) {
|
||||
gp_Hypr e = projCurve.Hyperbola();
|
||||
gp_Pnt p = e.Location();
|
||||
gp_Pnt P1 = projCurve.Value(projCurve.FirstParameter());
|
||||
gp_Pnt P2 = projCurve.Value(projCurve.LastParameter());
|
||||
|
||||
gp_Dir normal = e.Axis().Direction();
|
||||
gp_Dir xdir = e.XAxis().Direction();
|
||||
gp_Ax2 xdirref(p, normal);
|
||||
|
||||
if (P1.SquareDistance(P2) < Precision::Confusion()) {
|
||||
Part::GeomHyperbola* hyperbola = new Part::GeomHyperbola();
|
||||
hyperbola->setMajorRadius(e.MajorRadius());
|
||||
hyperbola->setMinorRadius(e.MinorRadius());
|
||||
hyperbola->setCenter(Base::Vector3d(p.X(),p.Y(),p.Z()));
|
||||
hyperbola->setAngleXU(-xdir.AngleWithRef(xdirref.XDirection(),normal));
|
||||
hyperbola->Construction = true;
|
||||
ExternalGeo.push_back(hyperbola);
|
||||
}
|
||||
else {
|
||||
Part::GeomArcOfHyperbola* aoh = new Part::GeomArcOfHyperbola();
|
||||
Handle_Geom_Curve curve = new Geom_Hyperbola(e);
|
||||
Handle_Geom_TrimmedCurve tCurve = new Geom_TrimmedCurve(curve, projCurve.FirstParameter(),
|
||||
projCurve.LastParameter());
|
||||
aoh->setHandle(tCurve);
|
||||
aoh->Construction = true;
|
||||
ExternalGeo.push_back(aoh);
|
||||
}
|
||||
}
|
||||
else if (projCurve.GetType() == GeomAbs_Ellipse) {
|
||||
|
@ -3447,6 +3655,13 @@ void SketchObject::rebuildVertexIndex(void)
|
|||
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);
|
||||
} else if ((*it)->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
VertexId2GeoId.push_back(i);
|
||||
VertexId2PosId.push_back(start);
|
||||
VertexId2GeoId.push_back(i);
|
||||
|
|
|
@ -112,6 +112,7 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
|
|||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
ret = this->getSketchObjectPtr()->addGeometry(geo,isConstruction);
|
||||
}
|
||||
|
@ -163,6 +164,7 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
|
|||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
geoList.push_back(geo);
|
||||
}
|
||||
|
|
|
@ -301,5 +301,59 @@ ArcOfEllipse* ArcOfEllipse::Copy()
|
|||
return crv;
|
||||
}
|
||||
|
||||
//---------------arc of hyperbola
|
||||
int ArcOfHyperbola::PushOwnParams(VEC_pD &pvec)
|
||||
{
|
||||
int cnt=0;
|
||||
// hyperbola
|
||||
pvec.push_back(center.x); cnt++;
|
||||
pvec.push_back(center.y); cnt++;
|
||||
pvec.push_back(focus.x); cnt++;
|
||||
pvec.push_back(focus.y); cnt++;
|
||||
pvec.push_back(radmaj); cnt++;
|
||||
// arc
|
||||
pvec.push_back(start.x); cnt++;
|
||||
pvec.push_back(start.y); cnt++;
|
||||
pvec.push_back(end.x); cnt++;
|
||||
pvec.push_back(end.y); cnt++;
|
||||
pvec.push_back(startAngle); cnt++;
|
||||
pvec.push_back(endAngle); cnt++;
|
||||
return cnt;
|
||||
|
||||
}
|
||||
void ArcOfHyperbola::ReconstructOnNewPvec(VEC_pD &pvec, int &cnt)
|
||||
{
|
||||
// hyperbola
|
||||
center.x=pvec[cnt]; cnt++;
|
||||
center.y=pvec[cnt]; cnt++;
|
||||
focus.x=pvec[cnt]; cnt++;
|
||||
focus.y=pvec[cnt]; cnt++;
|
||||
radmaj=pvec[cnt]; cnt++;
|
||||
//arc
|
||||
start.x=pvec[cnt]; cnt++;
|
||||
start.y=pvec[cnt]; cnt++;
|
||||
end.x=pvec[cnt]; cnt++;
|
||||
end.y=pvec[cnt]; cnt++;
|
||||
startAngle=pvec[cnt]; cnt++;
|
||||
endAngle=pvec[cnt]; cnt++;
|
||||
}
|
||||
ArcOfHyperbola* ArcOfHyperbola::Copy()
|
||||
{
|
||||
ArcOfHyperbola* crv = new ArcOfHyperbola(*this);
|
||||
return crv;
|
||||
}
|
||||
|
||||
DeriVector2 ArcOfHyperbola::CalculateNormal(Point &p, double* derivparam)
|
||||
{
|
||||
//fill some vectors in
|
||||
DeriVector2 cv (center, derivparam);
|
||||
DeriVector2 fv (focus, derivparam);
|
||||
DeriVector2 pv (p, derivparam);
|
||||
|
||||
DeriVector2 ret = fv;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}//namespace GCS
|
||||
|
|
|
@ -184,6 +184,27 @@ namespace GCS
|
|||
virtual ArcOfEllipse* Copy();
|
||||
};
|
||||
|
||||
class ArcOfHyperbola: public Curve
|
||||
{
|
||||
public:
|
||||
ArcOfHyperbola(){startAngle=0;endAngle=0;radmaj = 0;}
|
||||
virtual ~ArcOfHyperbola(){}
|
||||
// parameters
|
||||
double *startAngle;
|
||||
double *endAngle;
|
||||
double *radmaj;
|
||||
Point start;
|
||||
Point end;
|
||||
Point center;
|
||||
Point focus;
|
||||
// interface helpers
|
||||
virtual int PushOwnParams(VEC_pD &pvec);
|
||||
virtual void ReconstructOnNewPvec (VEC_pD &pvec, int &cnt);
|
||||
virtual ArcOfHyperbola* Copy();
|
||||
// Curve interface
|
||||
DeriVector2 CalculateNormal(Point &p, double* derivparam = 0);
|
||||
};
|
||||
|
||||
} //namespace GCS
|
||||
|
||||
#endif // PLANEGCS_GEO_H
|
||||
|
|
|
@ -3385,6 +3385,398 @@ bool CmdSketcherCreateArcOfEllipse::isActive(void)
|
|||
return isCreateGeoActive(getActiveGuiDocument());
|
||||
}
|
||||
|
||||
/* XPM */
|
||||
static const char *cursor_createarcofhyperbola[]={
|
||||
"32 32 3 1",
|
||||
"+ c white",
|
||||
"# c red",
|
||||
". c None",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"................................",
|
||||
"+++++...+++++...................",
|
||||
"................................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+................##.......",
|
||||
"......+..............##.........",
|
||||
"......+............##...........",
|
||||
"......+...........##............",
|
||||
"................##..............",
|
||||
"...............##...............",
|
||||
"..............##................",
|
||||
".............###................",
|
||||
"..###.......##..................",
|
||||
".#.#.......##...................",
|
||||
"..###......##...................",
|
||||
"..........##....................",
|
||||
".........##.....................",
|
||||
"........##......................",
|
||||
"........##......................",
|
||||
"........##......................",
|
||||
"........#.....####..............",
|
||||
"........######..................",
|
||||
"................................",
|
||||
"................................",
|
||||
"................................",
|
||||
"................................"};
|
||||
|
||||
class DrawSketchHandlerArcOfHyperbola : public DrawSketchHandler
|
||||
{
|
||||
public:
|
||||
DrawSketchHandlerArcOfHyperbola() : Mode(STATUS_SEEK_First),EditCurve(34){}
|
||||
virtual ~DrawSketchHandlerArcOfHyperbola(){}
|
||||
/// 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_createarcofhyperbola),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))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Mode==STATUS_SEEK_Second) {
|
||||
double rx0 = onSketchPos.fX - centerPoint.fX;
|
||||
double ry0 = onSketchPos.fY - centerPoint.fY;
|
||||
|
||||
EditCurve[1]= onSketchPos;
|
||||
|
||||
// Display radius for user
|
||||
float radius = (onSketchPos - centerPoint).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) {
|
||||
// angle between the major axis of the hyperbola 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 = acosh(((onSketchPos.fX-centerPoint.fX)*cos(phi)+(onSketchPos.fY-centerPoint.fY)*sin(phi))/a);
|
||||
double b=(onSketchPos.fY-centerPoint.fY-a*cosh(angleatpoint)*sin(phi))/(sinh(angleatpoint)*cos(phi));
|
||||
|
||||
if(!boost::math::isnan(b)){
|
||||
for (int i=15; i >= -15; i--) {
|
||||
// P(U) = O + MajRad*Cosh(U)*XDir + MinRad*Sinh(U)*YDir
|
||||
//double angle = i*M_PI/16.0;
|
||||
double angle=i*angleatpoint/15;
|
||||
double rx = a * cosh(angle) * cos(phi) - b * sinh(angle) * sin(phi);
|
||||
double ry = a * cosh(angle) * sin(phi) + b * sinh(angle) * cos(phi);
|
||||
EditCurve[15+i] = Base::Vector2D(centerPoint.fX + rx, centerPoint.fY + ry);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// angle between the major axis of the hyperbola 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 angleatstartingpoint = acosh(((startingPoint.fX-centerPoint.fX)*cos(phi)+(startingPoint.fY-centerPoint.fY)*sin(phi))/a);
|
||||
double b=(startingPoint.fY-centerPoint.fY-a*cosh(angleatstartingpoint)*sin(phi))/(sinh(angleatstartingpoint)*cos(phi));
|
||||
|
||||
double startAngle = angleatstartingpoint;
|
||||
|
||||
//double angleatpoint = acosh(((onSketchPos.fX-centerPoint.fX)*cos(phi)+(onSketchPos.fY-centerPoint.fY)*sin(phi))/a);
|
||||
|
||||
double angleatpoint = atanh( (((onSketchPos.fY-centerPoint.fY)*cos(phi)-(onSketchPos.fX-centerPoint.fX)*sin(phi))*a) /
|
||||
(((onSketchPos.fX-centerPoint.fX)*cos(phi)+(onSketchPos.fY-centerPoint.fY)*sin(phi))*b) );
|
||||
|
||||
/*double angle1 = angleatpoint - startAngle;
|
||||
|
||||
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
|
||||
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;*/
|
||||
|
||||
arcAngle = angleatpoint - startAngle;
|
||||
|
||||
//if(!boost::math::isnan(angle1) && !boost::math::isnan(angle2)){
|
||||
if(!boost::math::isnan(arcAngle)){
|
||||
for (int i=0; i < 33; i++) {
|
||||
// P(U) = O + MajRad*Cosh(U)*XDir + MinRad*Sinh(U)*YDir
|
||||
//double angle=i*angleatpoint/16;
|
||||
double angle = startAngle+i*arcAngle/32.0;
|
||||
double rx = a * cosh(angle) * cos(phi) - b * sinh(angle) * sin(phi);
|
||||
double ry = a * cosh(angle) * sin(phi) + b * sinh(angle) * cos(phi);
|
||||
EditCurve[i] = Base::Vector2D(centerPoint.fX + rx, centerPoint.fY + ry);
|
||||
}
|
||||
|
||||
// Display radius for user
|
||||
SbString text;
|
||||
text.sprintf(" (%.1fR,%.1fR)", a, b);
|
||||
setPositionText(onSketchPos, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
arcAngle=0.;
|
||||
}
|
||||
|
||||
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;
|
||||
EditCurve.resize(2);
|
||||
Mode = STATUS_SEEK_Second;
|
||||
}
|
||||
else if(Mode==STATUS_SEEK_Second) {
|
||||
EditCurve[1] = onSketchPos;
|
||||
axisPoint = onSketchPos;
|
||||
EditCurve.resize(31);
|
||||
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 hyperbola 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 angleatstartingpoint = acosh(((startingPoint.fX-centerPoint.fX)*cos(phi)+(startingPoint.fY-centerPoint.fY)*sin(phi))/a);
|
||||
double b=(startingPoint.fY-centerPoint.fY-a*cosh(angleatstartingpoint)*sin(phi))/(sinh(angleatstartingpoint)*cos(phi));
|
||||
|
||||
double startAngle = angleatstartingpoint;
|
||||
|
||||
//double angleatpoint = acosh(((onSketchPos.fX-centerPoint.fX)*cos(phi)+(onSketchPos.fY-centerPoint.fY)*sin(phi))/a);
|
||||
|
||||
double endAngle = atanh( (((endPoint.fY-centerPoint.fY)*cos(phi)-(endPoint.fX-centerPoint.fX)*sin(phi))*a) /
|
||||
(((endPoint.fX-centerPoint.fX)*cos(phi)+(endPoint.fY-centerPoint.fY)*sin(phi))*b) );
|
||||
|
||||
|
||||
|
||||
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;*/
|
||||
/*majAxisPoint.fX=20;
|
||||
majAxisPoint.fY=0;
|
||||
minAxisPoint.fX=0;
|
||||
minAxisPoint.fY=10;
|
||||
centerPoint.fX=0;
|
||||
centerPoint.fY=0;*/
|
||||
|
||||
|
||||
Base::Vector3d center = Base::Vector3d(centerPoint.fX,centerPoint.fY,0);
|
||||
|
||||
Base::Vector3d majorpositiveend = center + a * Base::Vector3d(cos(phi),sin(phi),0);
|
||||
Base::Vector3d majornegativeend = center - a * Base::Vector3d(cos(phi),sin(phi),0);
|
||||
Base::Vector3d minorpositiveend = center + b * Base::Vector3d(-sin(phi),cos(phi),0);
|
||||
Base::Vector3d minornegativeend = center - b * Base::Vector3d(-sin(phi),cos(phi),0);
|
||||
|
||||
double cf = sqrt( abs(a*a - b*b) );//using abs, avoided using different formula for a>b/a<b cases
|
||||
|
||||
Base::Vector3d focus1P = center + cf * Base::Vector3d(cos(phi),sin(phi),0);
|
||||
Base::Vector3d focus2P = center - cf * Base::Vector3d(cos(phi),sin(phi),0);
|
||||
|
||||
int currentgeoid = getHighestCurveIndex();
|
||||
|
||||
Gui::Command::openCommand("Add sketch arc of hyperbola");
|
||||
|
||||
//Add arc of hyperbola, point and constrain point as focus2. We add focus2 for it to balance
|
||||
//the intrinsic focus1, in order to balance out the intrinsic invisible focus1 when AOE is
|
||||
//dragged by its center
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.addGeometry(Part.ArcOfHyperbola"
|
||||
"(Part.Hyperbola(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);
|
||||
/*
|
||||
currentgeoid++;
|
||||
|
||||
try {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
|
||||
sketchgui->getObject()->getNameInDocument(),
|
||||
majorpositiveend.x,majorpositiveend.y,majornegativeend.x,majornegativeend.y); // create line for major axis
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+1);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+1,currentgeoid); // constrain major axis
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
|
||||
sketchgui->getObject()->getNameInDocument(),
|
||||
minorpositiveend.x,minorpositiveend.y,minornegativeend.x,minornegativeend.y); // create line for minor axis
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+2);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+2,currentgeoid); // constrain minor axis
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
|
||||
sketchgui->getObject()->getNameInDocument(),
|
||||
focus1P.x,focus1P.y);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+3,Sketcher::start,currentgeoid);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
|
||||
sketchgui->getObject()->getNameInDocument(),
|
||||
focus2P.x,focus2P.y);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
|
||||
sketchgui->getObject()->getNameInDocument(),currentgeoid+4,Sketcher::start,currentgeoid);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
Gui::Command::abortCommand();
|
||||
Gui::Command::updateActive();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
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<Base::Vector2D> EditCurve;
|
||||
Base::Vector2D centerPoint, axisPoint, startingPoint, endPoint;
|
||||
double rx, ry, startAngle, endAngle, arcAngle, arcAngle_t;
|
||||
std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3, sugConstr4;
|
||||
|
||||
};
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherCreateArcOfHyperbola);
|
||||
|
||||
CmdSketcherCreateArcOfHyperbola::CmdSketcherCreateArcOfHyperbola()
|
||||
: Command("Sketcher_CreateArcOfHyperbola")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = QT_TR_NOOP("Sketcher");
|
||||
sMenuText = QT_TR_NOOP("Create an arc of hyperbola");
|
||||
sToolTipText = QT_TR_NOOP("Create an arc of hyperbola in the sketch");
|
||||
sWhatsThis = sToolTipText;
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Sketcher_hyperbolic_Arc";
|
||||
eType = ForEdit;
|
||||
}
|
||||
|
||||
void CmdSketcherCreateArcOfHyperbola::activated(int iMsg)
|
||||
{
|
||||
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerArcOfHyperbola() );
|
||||
}
|
||||
|
||||
bool CmdSketcherCreateArcOfHyperbola::isActive(void)
|
||||
{
|
||||
return isCreateGeoActive(getActiveGuiDocument());
|
||||
}
|
||||
|
||||
/// @brief Macro that declares a new sketcher command class 'CmdSketcherCompCreateEllipse'
|
||||
DEF_STD_CMD_ACLU(CmdSketcherCompCreateConic);
|
||||
|
||||
|
@ -3415,6 +3807,8 @@ void CmdSketcherCompCreateConic::activated(int iMsg)
|
|||
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerEllipse(iMsg));
|
||||
} else if (iMsg == 2) {
|
||||
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerArcOfEllipse());
|
||||
} else if (iMsg == 3) {
|
||||
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerArcOfHyperbola());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -3442,6 +3836,9 @@ Gui::Action * CmdSketcherCompCreateConic::createAction(void)
|
|||
|
||||
QAction* arcofellipse = pcAction->addAction(QString());
|
||||
arcofellipse->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Elliptical_Arc"));
|
||||
|
||||
QAction* arcofhyperbola = pcAction->addAction(QString());
|
||||
arcofhyperbola->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Hyperbolic_Arc"));
|
||||
|
||||
_pcAction = pcAction;
|
||||
languageChange();
|
||||
|
@ -3467,12 +3864,14 @@ void CmdSketcherCompCreateConic::updateAction(int mode)
|
|||
a[0]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_CreateEllipse"));
|
||||
a[1]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_CreateEllipse_3points"));
|
||||
a[2]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Elliptical_Arc"));
|
||||
a[3]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Hyperbolic_Arc"));
|
||||
getAction()->setIcon(a[index]->icon());
|
||||
break;
|
||||
case Construction:
|
||||
a[0]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_CreateEllipse_Constr"));
|
||||
a[1]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_CreateEllipse_3points_Constr"));
|
||||
a[2]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Elliptical_Arc_Constr"));
|
||||
a[3]->setIcon(Gui::BitmapFactory().pixmap("Sketcher_Hyperbolic_Arc_Constr"));
|
||||
getAction()->setIcon(a[index]->icon());
|
||||
break;
|
||||
}
|
||||
|
@ -3499,6 +3898,10 @@ void CmdSketcherCompCreateConic::languageChange()
|
|||
arcofellipse->setText(QApplication::translate("CmdSketcherCompCreateConic","Arc of ellipse by center, major radius, endpoints"));
|
||||
arcofellipse->setToolTip(QApplication::translate("Sketcher_CreateArcOfEllipse","Create an arc of ellipse by its center, major radius, endpoints"));
|
||||
arcofellipse->setStatusTip(QApplication::translate("Sketcher_CreateArcOfEllipse","Create an arc of ellipse by its center, major radius, endpoints"));
|
||||
QAction* arcofhyperbola = a[3];
|
||||
arcofhyperbola->setText(QApplication::translate("CmdSketcherCompCreateConic","Arc of hyperbola by center, major radius, endpoints"));
|
||||
arcofhyperbola->setToolTip(QApplication::translate("Sketcher_CreateArcOfHyperbola","Create an arc of hyperbola by its center, major radius, endpoints"));
|
||||
arcofhyperbola->setStatusTip(QApplication::translate("Sketcher_CreateArcOfHyperbola","Create an arc of hyperbola by its center, major radius, endpoints"));
|
||||
}
|
||||
|
||||
bool CmdSketcherCompCreateConic::isActive(void)
|
||||
|
@ -4767,6 +5170,7 @@ bool CmdSketcherExternal::isActive(void)
|
|||
return isCreateGeoActive(getActiveGuiDocument());
|
||||
}
|
||||
|
||||
|
||||
/* Create Slot =======================================================*/
|
||||
|
||||
/* XPM */
|
||||
|
@ -5570,6 +5974,7 @@ void CreateSketcherCommandsCreateGeo(void)
|
|||
rcCmdMgr.addCommand(new CmdSketcherCreateEllipseBy3Points());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCompCreateConic());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateArcOfEllipse());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateArcOfHyperbola());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateLine());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateRectangle());
|
||||
|
|
|
@ -221,6 +221,18 @@ void SketcherValidation::on_findButton_clicked()
|
|||
id.v = segm->getEndPoint(/*emulateCCW=*/true);
|
||||
vertexIds.push_back(id);
|
||||
}
|
||||
else if (g->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
const Part::GeomArcOfHyperbola *segm = dynamic_cast<const Part::GeomArcOfHyperbola*>(g);
|
||||
VertexIds id;
|
||||
id.GeoId = (int)i;
|
||||
id.PosId = Sketcher::start;
|
||||
id.v = segm->getStartPoint();
|
||||
vertexIds.push_back(id);
|
||||
id.GeoId = (int)i;
|
||||
id.PosId = Sketcher::end;
|
||||
id.v = segm->getEndPoint();
|
||||
vertexIds.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<ConstraintIds, Constraint_Less> coincidences;
|
||||
|
|
|
@ -768,7 +768,8 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
|
|||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId()||
|
||||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
|
||||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()||
|
||||
geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
Gui::Command::openCommand("Drag Curve");
|
||||
try {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.movePoint(%i,%i,App.Vector(%f,%f,0),%i)"
|
||||
|
@ -2099,7 +2100,6 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
|
|||
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfEllipse *aoe = static_cast<const Part::GeomArcOfEllipse *>(*it);
|
||||
|
@ -2107,6 +2107,7 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
|
|||
pnt0 = aoe->getStartPoint(/*emulateCCW=*/true);
|
||||
pnt1 = aoe->getEndPoint(/*emulateCCW=*/true);
|
||||
pnt2 = aoe->getCenter();
|
||||
|
||||
VertexId += 3;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
|
@ -2139,11 +2140,13 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
|
|||
if (pnt0Inside && pnt1Inside) {
|
||||
double startangle, endangle;
|
||||
aoe->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
|
||||
if (startangle > endangle) // if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle-startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
|
||||
double segment = (range) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
|
@ -2157,6 +2160,85 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
|
|||
double angle = (startangle) + segment/2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = pnt0 + cos(angle)*a*majdir + sin(angle)*b*mindir;
|
||||
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2D(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((*it)->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfHyperbola *aoh = dynamic_cast<const Part::GeomArcOfHyperbola *>(*it);
|
||||
|
||||
pnt0 = aoh->getStartPoint();
|
||||
pnt1 = aoh->getEndPoint();
|
||||
pnt2 = aoh->getCenter();
|
||||
|
||||
VertexId += 3;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
Plm.multVec(pnt1, pnt1);
|
||||
Plm.multVec(pnt2, pnt2);
|
||||
pnt0 = proj(pnt0);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
|
||||
bool pnt0Inside = polygon.Contains(Base::Vector2D(pnt0.x, pnt0.y));
|
||||
if (pnt0Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId - 1;
|
||||
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
|
||||
}
|
||||
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2D(pnt1.x, pnt1.y));
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
|
||||
}
|
||||
|
||||
if (polygon.Contains(Base::Vector2D(pnt2.x, pnt2.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
|
||||
}
|
||||
|
||||
if (pnt0Inside && pnt1Inside) {
|
||||
double startangle, endangle;
|
||||
|
||||
aoh->getRange(startangle, endangle);
|
||||
|
||||
if (startangle > endangle) // if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle-startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
|
||||
float segment = float(range) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
float a = float(aoh->getMajorRadius()) / cos(segment/2);
|
||||
float b = float(aoh->getMinorRadius()) / cos(segment/2);
|
||||
float phi = float(aoh->getAngleXU());
|
||||
|
||||
bool bpolyInside = true;
|
||||
pnt0 = aoh->getCenter();
|
||||
float angle = float(startangle) + segment/2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = Base::Vector3d(pnt0.x + a * cosh(angle) * cos(phi) - b * sinh(angle) * sin(phi),
|
||||
pnt0.y + a * cosh(angle) * sin(phi) + b * sinh(angle) * cos(phi),
|
||||
0.f);
|
||||
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
|
@ -3104,6 +3186,39 @@ void ViewProviderSketch::draw(bool temp)
|
|||
Points.push_back(end);
|
||||
Points.push_back(center);
|
||||
}
|
||||
else if ((*it)->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
|
||||
const Part::GeomArcOfHyperbola *aoh = dynamic_cast<const Part::GeomArcOfHyperbola *>(*it);
|
||||
Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(aoh->handle());
|
||||
|
||||
double startangle, endangle;
|
||||
aoh->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 = aoh->getCenter();
|
||||
Base::Vector3d start = aoh->getStartPoint();
|
||||
Base::Vector3d end = aoh->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 = static_cast<const Part::GeomBSplineCurve *>(*it);
|
||||
Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast(spline->handle());
|
||||
|
|
|
@ -139,7 +139,8 @@ inline void SketcherAddWorkspaceArcs<Gui::MenuItem>(Gui::MenuItem& geom){
|
|||
<< "Sketcher_Create3PointCircle"
|
||||
<< "Sketcher_CreateEllipseByCenter"
|
||||
<< "Sketcher_CreateEllipseBy3Points"
|
||||
<< "Sketcher_CreateArcOfEllipse";
|
||||
<< "Sketcher_CreateArcOfEllipse"
|
||||
<< "Sketcher_CreateArcOfHyperbola";
|
||||
}
|
||||
template <>
|
||||
inline void SketcherAddWorkspaceArcs<Gui::ToolBarItem>(Gui::ToolBarItem& geom){
|
||||
|
|
Loading…
Reference in New Issue
Block a user