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:
Abdullah Tahiri 2014-10-17 14:50:39 +02:00 committed by wmayer
parent fde9bded28
commit 590e3fbec6
10 changed files with 1004 additions and 14 deletions

View File

@ -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 *> &params = 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 *> &params = 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 *> &params = 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 &center = 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 &center = 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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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;

View File

@ -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());

View File

@ -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){