Fix handling of BezierCurves

Replace custom bbox code with OCC/Base code
Refactor duplicate code Geometry/DrawProjectSplit
This commit is contained in:
WandererFan
2016-11-18 09:52:55 -05:00
committed by wmayer
parent 2dfd521c87
commit dd13cb2534
9 changed files with 152 additions and 370 deletions

View File

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