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

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