Fix handling of BezierCurves
Replace custom bbox code with OCC/Base code Refactor duplicate code Geometry/DrawProjectSplit
This commit is contained in:
@@ -54,8 +54,9 @@
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Tools2D.h>
|
||||
//#include <Base/Vector3D.h>
|
||||
|
||||
#include "Geometry.h"
|
||||
#include "DrawUtil.h"
|
||||
|
||||
using namespace TechDrawGeometry;
|
||||
|
||||
@@ -64,7 +65,6 @@ Wire::Wire()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Wire::Wire(const TopoDS_Wire &w)
|
||||
{
|
||||
TopExp_Explorer edges(w, TopAbs_EDGE);
|
||||
@@ -72,10 +72,8 @@ Wire::Wire(const TopoDS_Wire &w)
|
||||
const auto edge( TopoDS::Edge(edges.Current()) );
|
||||
geoms.push_back( BaseGeom::baseFactory(edge) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Wire::~Wire()
|
||||
{
|
||||
for(auto it : geoms) {
|
||||
@@ -84,7 +82,6 @@ Wire::~Wire()
|
||||
geoms.clear();
|
||||
}
|
||||
|
||||
|
||||
Face::~Face()
|
||||
{
|
||||
for(auto it : wires) {
|
||||
@@ -93,14 +90,13 @@ Face::~Face()
|
||||
wires.clear();
|
||||
}
|
||||
|
||||
|
||||
BaseGeom::BaseGeom() :
|
||||
geomType(NOTDEF),
|
||||
extractType(Plain),
|
||||
extractType(Plain), //obs
|
||||
classOfEdge(ecNONE),
|
||||
visible(true),
|
||||
reversed(false),
|
||||
ref3D(-1)
|
||||
ref3D(-1) //obs?
|
||||
{
|
||||
}
|
||||
|
||||
@@ -137,13 +133,7 @@ double BaseGeom::minDist(Base::Vector2D p)
|
||||
double minDist = -1.0;
|
||||
gp_Pnt pnt(p.fX,p.fY,0.0);
|
||||
TopoDS_Vertex v = BRepBuilderAPI_MakeVertex(pnt);
|
||||
BRepExtrema_DistShapeShape extss(occEdge, v);
|
||||
if (extss.IsDone()) {
|
||||
int count = extss.NbSolution();
|
||||
if (count != 0) {
|
||||
minDist = extss.Value();
|
||||
}
|
||||
}
|
||||
minDist = TechDraw::DrawUtil::simpleMinDist(occEdge,v);
|
||||
return minDist;
|
||||
}
|
||||
|
||||
@@ -181,13 +171,22 @@ Base::Vector2D BaseGeom::nearPoint(Base::Vector2D p)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string BaseGeom::dump()
|
||||
{
|
||||
Base::Vector2D start = getStartPoint();
|
||||
Base::Vector2D end = getEndPoint();
|
||||
std::stringstream ss;
|
||||
ss << "BaseGeom: s:(" << start.fX << "," << start.fY << ") e:(" << end.fX << "," << end.fY << ") ";
|
||||
ss << "type: " << geomType << " class: " << classOfEdge << " viz: " << visible << " rev: " << reversed;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
//! Convert 1 OCC edge into 1 BaseGeom (static factory method)
|
||||
BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
{
|
||||
BaseGeom* result = NULL;
|
||||
BRepAdaptor_Curve adapt(edge);
|
||||
|
||||
switch(adapt.GetType()) {
|
||||
case GeomAbs_Circle: {
|
||||
double f = adapt.FirstParameter();
|
||||
@@ -197,11 +196,9 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
|
||||
if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
Circle *circle = new Circle(edge);
|
||||
//circle->extractType = extractionType;
|
||||
result = circle;
|
||||
} else {
|
||||
AOC *aoc = new AOC(edge);
|
||||
//aoc->extractType = extractionType;
|
||||
result = aoc;
|
||||
}
|
||||
} break;
|
||||
@@ -212,40 +209,47 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
Ellipse *ellipse = new Ellipse(edge);
|
||||
//ellipse->extractType = extractionType;
|
||||
result = ellipse;
|
||||
} else {
|
||||
AOE *aoe = new AOE(edge);
|
||||
//aoe->extractType = extractionType;
|
||||
result = aoe;
|
||||
}
|
||||
} break;
|
||||
case GeomAbs_BezierCurve: {
|
||||
Handle_Geom_BezierCurve bez = adapt.Bezier();
|
||||
//if (bez->Degree() < 4) {
|
||||
result = new BezierSegment(edge);
|
||||
//}
|
||||
// OCC is quite happy with Degree > 3 but QtGui handles only 2,3
|
||||
} break;
|
||||
case GeomAbs_BSplineCurve: {
|
||||
BSpline *bspline = 0;
|
||||
Generic* gen = NULL;
|
||||
try {
|
||||
bspline = new BSpline(edge);
|
||||
//bspline->extractType = extractionType;
|
||||
if (bspline->isLine()) {
|
||||
gen = new Generic(edge);
|
||||
//gen->extractType = extractionType;
|
||||
result = gen;
|
||||
delete bspline;
|
||||
bspline = nullptr;
|
||||
} else {
|
||||
result = bspline;
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
delete bspline;
|
||||
delete gen;
|
||||
bspline = 0;
|
||||
// Move onto generating a primitive
|
||||
if (bspline != nullptr) {
|
||||
delete bspline;
|
||||
bspline = nullptr;
|
||||
}
|
||||
if (gen != nullptr) {
|
||||
delete gen;
|
||||
gen = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
Generic *primitive = new Generic(edge);
|
||||
//primitive->extractType = extractionType;
|
||||
result = primitive;
|
||||
} break;
|
||||
}
|
||||
@@ -306,8 +310,6 @@ Circle::Circle(const TopoDS_Edge &e)
|
||||
|
||||
gp_Circ circ = c.Circle();
|
||||
const gp_Pnt& p = circ.Location();
|
||||
//const gp_Ax2& p1 = circ.Position();
|
||||
//const gp_Pnt& l = p1.Location();
|
||||
|
||||
radius = circ.Radius();
|
||||
center = Base::Vector2D(p.X(), p.Y());
|
||||
@@ -364,17 +366,6 @@ double AOC::distToArc(Base::Vector3d p)
|
||||
Base::Vector2D p2(p.x,p.y);
|
||||
double result = minDist(p2);
|
||||
return result;
|
||||
// double minDist = -1.0;
|
||||
// gp_Pnt pnt(p.x,p.y,p.z);
|
||||
// TopoDS_Vertex v = BRepBuilderAPI_MakeVertex(pnt);
|
||||
// BRepExtrema_DistShapeShape extss(occEdge, v);
|
||||
// if (extss.IsDone()) {
|
||||
// int count = extss.NbSolution();
|
||||
// if (count != 0) {
|
||||
// minDist = extss.Value();
|
||||
// }
|
||||
// }
|
||||
// return minDist;
|
||||
}
|
||||
|
||||
|
||||
@@ -443,6 +434,8 @@ BSpline::BSpline(const TopoDS_Edge &e)
|
||||
double f,l;
|
||||
gp_Pnt s,m,ePt;
|
||||
//if startpoint == endpoint conversion to BSpline will fail
|
||||
//Base::Console().Message("TRACE - Geometry::BSpline - start(%.3f,%.3f,%.3f) end(%.3f,%.3f,%.3f)\n",
|
||||
// s.X(),s.Y(),s.Z(),ePt.X(),ePt.Y(),ePt.Z());
|
||||
|
||||
if (spline->Degree() > 3) { //if spline is too complex, approximate it
|
||||
Standard_Real tol3D = 0.001; //1/1000 of a mm? screen can't resolve this
|
||||
@@ -464,36 +457,36 @@ BSpline::BSpline(const TopoDS_Edge &e)
|
||||
s = c.Value(f);
|
||||
m = c.Value((l+f)/2.0);
|
||||
ePt = c.Value(l);
|
||||
Base::Console().Log("Error - Geometry::BSpline - from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
|
||||
Base::Console().Log("Error - Geometry::BSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
|
||||
s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles());
|
||||
//throw Base::Exception("Geometry::BSpline - could not approximate curve");
|
||||
throw Base::Exception("Geometry::BSpline - could not approximate curve");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GeomConvert_BSplineCurveToBezierCurve crt(spline);
|
||||
|
||||
BezierSegment tempSegment;
|
||||
gp_Pnt controlPoint;
|
||||
if (fail) {
|
||||
BezierSegment tempSegment;
|
||||
tempSegment.poles = 3;
|
||||
tempSegment.pnts[0] = Base::Vector2D(s.X(),s.Y());
|
||||
tempSegment.pnts[1] = Base::Vector2D(m.X(),m.Y());
|
||||
tempSegment.pnts[2] = Base::Vector2D(ePt.X(),ePt.Y());
|
||||
tempSegment.degree = 2;
|
||||
tempSegment.pnts.push_back(Base::Vector2D(s.X(),s.Y()));
|
||||
tempSegment.pnts.push_back(Base::Vector2D(m.X(),m.Y()));
|
||||
tempSegment.pnts.push_back(Base::Vector2D(ePt.X(),ePt.Y()));
|
||||
segments.push_back(tempSegment);
|
||||
} else {
|
||||
for (Standard_Integer i = 1; i <= crt.NbArcs(); ++i) {
|
||||
BezierSegment tempSegment;
|
||||
Handle_Geom_BezierCurve bezier = crt.Arc(i);
|
||||
if (bezier->Degree() > 3) {
|
||||
throw Base::Exception("Geometry::BSpline - converted curve degree > 3");
|
||||
Base::Console().Log("Geometry::BSpline - converted curve degree > 3\n");
|
||||
}
|
||||
tempSegment.poles = bezier->NbPoles();
|
||||
// Note: We really only need to keep the pnts[0] for the first Bezier segment,
|
||||
// assuming this only gets used as in QGIViewPart::drawPainterPath
|
||||
// ...it also gets used in GeometryObject::calcBoundingBox(), similar note applies
|
||||
tempSegment.degree = bezier->Degree();
|
||||
for (int pole = 1; pole <= tempSegment.poles; ++pole) {
|
||||
controlPoint = bezier->Pole(pole);
|
||||
tempSegment.pnts[pole - 1] = Base::Vector2D(controlPoint.X(), controlPoint.Y());
|
||||
tempSegment.pnts.push_back(Base::Vector2D(controlPoint.X(), controlPoint.Y()));
|
||||
}
|
||||
segments.push_back(tempSegment);
|
||||
}
|
||||
@@ -513,6 +506,23 @@ bool BSpline::isLine()
|
||||
return result;
|
||||
}
|
||||
|
||||
BezierSegment::BezierSegment(const TopoDS_Edge &e)
|
||||
{
|
||||
geomType = BEZIER;
|
||||
occEdge = e;
|
||||
BRepAdaptor_Curve c(e);
|
||||
Handle_Geom_BezierCurve bez = c.Bezier();
|
||||
poles = bez->NbPoles();
|
||||
degree = bez->Degree();
|
||||
if (poles > 4) {
|
||||
Base::Console().Log("Warning - BezierSegment has degree > 3: %d\n",degree);
|
||||
}
|
||||
for (int i = 1; i <= poles; ++i) {
|
||||
gp_Pnt controlPoint = bez->Pole(i);
|
||||
pnts.push_back(Base::Vector2D(controlPoint.X(), controlPoint.Y()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//**** Vertex
|
||||
Vertex::Vertex(double x, double y)
|
||||
|
||||
Reference in New Issue
Block a user