[TD]add ability to filter obvious geometry errors
- also add checks for geometry errors
This commit is contained in:
@@ -229,11 +229,6 @@ void BaseGeom::Restore(Base::XMLReader &reader)
|
||||
m_sourceIndex = reader.getAttributeAsInteger("value");
|
||||
reader.readElement("CosmeticTag");
|
||||
cosmeticTag = reader.getAttribute("value");
|
||||
// reader.readElement("Tag");
|
||||
// std::string temp = reader.getAttribute("value");
|
||||
// boost::uuids::string_generator gen;
|
||||
// boost::uuids::uuid u1 = gen(temp);
|
||||
// tag = u1;
|
||||
}
|
||||
|
||||
std::vector<Base::Vector3d> BaseGeom::findEndPoints()
|
||||
@@ -393,6 +388,14 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
if (edge.IsNull()) {
|
||||
Base::Console().Message("BG::baseFactory - input edge is NULL \n");
|
||||
}
|
||||
//weed out rubbish edges before making geometry
|
||||
if (!validateEdge(edge)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Generic *primitive = new Generic(edge);
|
||||
result = primitive;
|
||||
|
||||
BRepAdaptor_Curve adapt(edge);
|
||||
switch(adapt.GetType()) {
|
||||
case GeomAbs_Circle: {
|
||||
@@ -401,6 +404,9 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
gp_Pnt s = adapt.Value(f);
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
|
||||
//don't understand this test.
|
||||
//if first to last is > 1 radian? are circles parameterize by rotation angle?
|
||||
//if start and end points are close?
|
||||
if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
Circle *circle = new Circle(edge);
|
||||
result = circle;
|
||||
@@ -430,7 +436,6 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
result->reversed = true;
|
||||
}
|
||||
|
||||
//}
|
||||
// OCC is quite happy with Degree > 3 but QtGui handles only 2,3
|
||||
} break;
|
||||
case GeomAbs_BSplineCurve: {
|
||||
@@ -438,6 +443,8 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
Generic* gen = NULL;
|
||||
Circle* circ = nullptr;
|
||||
AOC* aoc = nullptr;
|
||||
TopoDS_Edge circEdge;
|
||||
|
||||
bool isArc = false;
|
||||
try {
|
||||
bspline = new BSpline(edge);
|
||||
@@ -447,7 +454,7 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
delete bspline;
|
||||
bspline = nullptr;
|
||||
} else {
|
||||
TopoDS_Edge circEdge = bspline->asCircle(isArc);
|
||||
circEdge = bspline->asCircle(isArc);
|
||||
if (!circEdge.IsNull()) {
|
||||
if (isArc) {
|
||||
aoc = new AOC(circEdge);
|
||||
@@ -461,12 +468,15 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
bspline = nullptr;
|
||||
}
|
||||
} else {
|
||||
// Base::Console().Message("Geom::baseFactory - circEdge is Null\n");
|
||||
result = bspline;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (Standard_Failure&) {
|
||||
catch (const Standard_Failure& e) {
|
||||
Base::Console().Error("Geom::baseFactory - OCC error - %s - while making spline\n",
|
||||
e.GetMessageString());
|
||||
if (bspline != nullptr) {
|
||||
delete bspline;
|
||||
bspline = nullptr;
|
||||
@@ -475,16 +485,39 @@ BaseGeom* BaseGeom::baseFactory(TopoDS_Edge edge)
|
||||
delete gen;
|
||||
gen = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Error("Geom::baseFactory - unknown error occurred while making spline\n");
|
||||
if (bspline != nullptr) {
|
||||
delete bspline;
|
||||
bspline = nullptr;
|
||||
}
|
||||
if (gen != nullptr) {
|
||||
delete gen;
|
||||
gen = nullptr;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
} // end bspline case
|
||||
default: {
|
||||
Generic *primitive = new Generic(edge);
|
||||
primitive = new Generic(edge);
|
||||
result = primitive;
|
||||
} break;
|
||||
}
|
||||
|
||||
if ( (primitive != nullptr) &&
|
||||
(primitive != result) ) {
|
||||
delete primitive;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BaseGeom::validateEdge(TopoDS_Edge edge)
|
||||
{
|
||||
return !DrawUtil::isCrazy(edge);
|
||||
}
|
||||
|
||||
Ellipse::Ellipse(const TopoDS_Edge &e)
|
||||
{
|
||||
@@ -515,10 +548,17 @@ AOE::AOE(const TopoDS_Edge &e) : Ellipse(e)
|
||||
gp_Pnt m = c.Value((l+f)/2.0);
|
||||
gp_Pnt ePt = c.Value(l);
|
||||
|
||||
gp_Vec v1(m,s);
|
||||
gp_Vec v2(m,ePt);
|
||||
gp_Vec v3(0,0,1);
|
||||
double a = v3.DotCross(v1,v2);
|
||||
double a;
|
||||
try {
|
||||
gp_Vec v1(m,s);
|
||||
gp_Vec v2(m,ePt);
|
||||
gp_Vec v3(0,0,1);
|
||||
a = v3.DotCross(v1,v2);
|
||||
}
|
||||
catch (const Standard_Failure& e) {
|
||||
Base::Console().Error("Geom::AOE::AOE - OCC error - %s - while making AOE in ctor\n",
|
||||
e.GetMessageString());
|
||||
}
|
||||
|
||||
startAngle = fmod(f,2.0*M_PI);
|
||||
endAngle = fmod(l,2.0*M_PI);
|
||||
@@ -564,34 +604,6 @@ std::string Circle::toString(void) const
|
||||
return baseCSV + ",$$$," + ss.str();
|
||||
}
|
||||
|
||||
//bool Circle::fromCSV(std::string lineSpec)
|
||||
//{
|
||||
// if (lineSpec.length() == 0) {
|
||||
// Base::Console().Message( "Circle::fromCSV - lineSpec empty\n");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// std::vector<std::string> tokens = DrawUtil::tokenize(lineSpec);
|
||||
// //"baseCSV,$$$,circleCSV"
|
||||
// if (tokens.size() != 2) {
|
||||
// Base::Console().Message("CosmeticEdge::fromCSV - tokenize failed - size: %d\n",tokens.size());
|
||||
// }
|
||||
|
||||
// BaseGeom::fromCSV(tokens[0]);
|
||||
// unsigned int maxCells = 4;
|
||||
// std::vector<std::string> values = DrawUtil::split(tokens[1]);
|
||||
// if (values.size() < maxCells) {
|
||||
// Base::Console().Message( "Circle::fromCSV(%s) invalid CSV entry\n",lineSpec.c_str() );
|
||||
// return false;
|
||||
// }
|
||||
// double x = atof(values[0].c_str());
|
||||
// double y = atof(values[1].c_str());
|
||||
// double z = atof(values[2].c_str());
|
||||
// center = Base::Vector3d(x,y,z);
|
||||
// radius = atof(values[3].c_str());
|
||||
// return true;
|
||||
//}
|
||||
|
||||
void Circle::Save(Base::Writer &writer) const
|
||||
{
|
||||
BaseGeom::Save(writer);
|
||||
@@ -627,11 +639,11 @@ AOC::AOC(const TopoDS_Edge &e) : Circle(e)
|
||||
double l = c.LastParameter();
|
||||
gp_Pnt s = c.Value(f);
|
||||
gp_Pnt m = c.Value((l+f)/2.0);
|
||||
gp_Pnt ePt = c.Value(l);
|
||||
gp_Pnt ePt = c.Value(l); //if start == end, it isn't an arc!
|
||||
gp_Vec v1(m,s); //vector mid to start
|
||||
gp_Vec v2(m,ePt); //vector mid to end
|
||||
gp_Vec v3(0,0,1); //stdZ
|
||||
double a = v3.DotCross(v1,v2);
|
||||
double a = v3.DotCross(v1,v2); //error if v1 = v2?
|
||||
|
||||
startAngle = fmod(f,2.0*M_PI);
|
||||
endAngle = fmod(l,2.0*M_PI);
|
||||
@@ -733,46 +745,6 @@ std::string AOC::toString(void) const
|
||||
return result;
|
||||
}
|
||||
|
||||
//bool AOC::fromCSV(std::string lineSpec)
|
||||
//{
|
||||
//// Base::Console().Message( "AOC::fromCSV(%s)\n", lineSpec.c_str());
|
||||
// if (lineSpec.length() == 0) {
|
||||
// Base::Console().Message( "AOC::fromCSV - lineSpec empty\n");
|
||||
// return false;
|
||||
// }
|
||||
// std::vector<std::string> tokens = DrawUtil::tokenize(lineSpec);
|
||||
// //"(baseCSV,$$$,circleCSV),$$$,AOCCSV"
|
||||
// // [0] [1] [2]
|
||||
// if (tokens.size() != 3) {
|
||||
// Base::Console().Message("CosmeticEdge::fromCSV - tokenize failed - size: %d\n",tokens.size());
|
||||
// }
|
||||
|
||||
// Circle::fromCSV(tokens[0] + ",$$$," + tokens[1]); //extra work here.
|
||||
// unsigned int maxCells = 13;
|
||||
// std::vector<std::string> values = DrawUtil::split(tokens[2]); // we are only interested in last token
|
||||
// if (values.size() < maxCells) {
|
||||
// Base::Console().Message( "AOC::fromCSV(%s) invalid CSV entry\n",lineSpec.c_str() );
|
||||
// return false;
|
||||
// }
|
||||
// double x = atof(values[0].c_str());
|
||||
// double y = atof(values[1].c_str());
|
||||
// double z = atof(values[2].c_str());
|
||||
// startPnt = Base::Vector3d(x,y,z);
|
||||
// x = atof(values[3].c_str());
|
||||
// y = atof(values[4].c_str());
|
||||
// z = atof(values[5].c_str());
|
||||
// endPnt = Base::Vector3d(x,y,z);
|
||||
// x = atof(values[6].c_str());
|
||||
// y = atof(values[7].c_str());
|
||||
// z = atof(values[8].c_str());
|
||||
// midPnt = Base::Vector3d(x,y,z);
|
||||
// startAngle = atof(values[9].c_str());
|
||||
// endAngle = atof(values[10].c_str());
|
||||
// cw = atoi(values[11].c_str());
|
||||
// largeArc = atoi(values[12].c_str());
|
||||
// return true;
|
||||
//}
|
||||
|
||||
void AOC::Save(Base::Writer &writer) const
|
||||
{
|
||||
Circle::Save(writer);
|
||||
@@ -873,35 +845,6 @@ std::string Generic::toString(void) const
|
||||
return baseCSV + ",$$$," + genericCSV;
|
||||
}
|
||||
|
||||
//bool Generic::fromCSV(std::string lineSpec)
|
||||
//{
|
||||
|
||||
// std::vector<std::string> tokens = DrawUtil::tokenize(lineSpec);
|
||||
// //"baseCSV,$$$,genericCSV"
|
||||
// if (tokens.size() != 2) {
|
||||
// Base::Console().Message("Generic::fromCSV - tokenize failed - size: %d\n",tokens.size());
|
||||
// }
|
||||
|
||||
// BaseGeom::fromCSV(tokens[0]);
|
||||
// if (lineSpec.length() == 0) {
|
||||
// Base::Console().Message( "Generic::fromCSV - lineSpec empty\n");
|
||||
// return false;
|
||||
// }
|
||||
// std::vector<std::string> values = DrawUtil::split(tokens[1]);
|
||||
// if (!values.empty()) {
|
||||
// double count = atoi(values[0].c_str());
|
||||
// points.clear();
|
||||
// int i = 0;
|
||||
// for ( ; i < count; i++) {
|
||||
// int idx = i * 3;
|
||||
// double x = atof(values[idx+1].c_str());
|
||||
// double y = atof(values[idx+2].c_str());
|
||||
// double z = atof(values[idx+3].c_str());
|
||||
// points.push_back(Base::Vector3d(x, y, z));
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
void Generic::Save(Base::Writer &writer) const
|
||||
{
|
||||
@@ -1189,99 +1132,105 @@ TopoDS_Edge BSpline::asCircle(bool& arc)
|
||||
gp_Pnt s = c.Value(f);
|
||||
gp_Pnt e = c.Value(l);
|
||||
|
||||
arc = !c.IsClosed();
|
||||
if (s.IsEqual(e, 0.001)) { //more reliable
|
||||
arc = false;
|
||||
} else {
|
||||
arc = true;
|
||||
}
|
||||
// arc = !c.IsClosed(); //reliable?
|
||||
|
||||
Handle(Geom_BSplineCurve) spline = c.BSpline();
|
||||
|
||||
if (spline->NbPoles() < 5) { //need 5 poles (s-p1-pm-p2-e) for algo
|
||||
return result; //how to do with fewer poles?
|
||||
}
|
||||
|
||||
// get three points on curve (non extreme poles)
|
||||
int nb_poles = spline->NbPoles();
|
||||
gp_Pnt p1 = spline->Pole(2); //OCC numbering starts at 1!!
|
||||
gp_Pnt p2 = spline->Pole(nb_poles-1);
|
||||
gp_Pnt pm;
|
||||
if (nb_poles == 5) {
|
||||
pm = spline->Pole(3); //5 poles => 2.5 => 2
|
||||
} else {
|
||||
pm = spline->Pole(nb_poles / 2);
|
||||
}
|
||||
|
||||
// project three poles onto the curve
|
||||
GeomAPI_ProjectPointOnCurve proj1;
|
||||
GeomAPI_ProjectPointOnCurve proj2;
|
||||
GeomAPI_ProjectPointOnCurve projm;
|
||||
try {
|
||||
// get three points on curve (non extreme poles)
|
||||
int nb_poles = spline->NbPoles();
|
||||
gp_Pnt p1 = spline->Pole(2); //OCC numbering starts at 1!!
|
||||
gp_Pnt p2 = spline->Pole(nb_poles-1);
|
||||
gp_Pnt pm;
|
||||
if (nb_poles == 5) {
|
||||
pm = spline->Pole(3); //5 poles => 2.5 => 2
|
||||
} else {
|
||||
pm = spline->Pole(nb_poles / 2);
|
||||
}
|
||||
|
||||
// project three poles onto the curve
|
||||
GeomAPI_ProjectPointOnCurve proj1;
|
||||
GeomAPI_ProjectPointOnCurve proj2;
|
||||
GeomAPI_ProjectPointOnCurve projm;
|
||||
proj1.Init(p1, curve, f, l);
|
||||
proj1.Perform(p1);
|
||||
proj2.Init(p2, curve, f, l);
|
||||
proj2.Perform(p2);
|
||||
projm.Init(pm, curve, f, l);
|
||||
projm.Perform(pm);
|
||||
}
|
||||
catch(const StdFail_NotDone &e) {
|
||||
Base::Console().Log("Geometry::asCircle - init: %s\n",e.GetMessageString());
|
||||
return result;
|
||||
}
|
||||
if ( (proj1.NbPoints() == 0) ||
|
||||
(proj2.NbPoints() == 0) ||
|
||||
(projm.NbPoints() == 0) ) {
|
||||
return result;
|
||||
}
|
||||
gp_Pnt pc1, pc2, pcm;
|
||||
if ( (proj1.NbPoints() == 0) ||
|
||||
(proj2.NbPoints() == 0) ||
|
||||
(projm.NbPoints() == 0) ) {
|
||||
return result;
|
||||
}
|
||||
gp_Pnt pc1, pc2, pcm;
|
||||
|
||||
// get projected points
|
||||
try {
|
||||
// get projected points
|
||||
pc1 = proj1.NearestPoint();
|
||||
pc2 = proj2.NearestPoint();
|
||||
pcm = projm.NearestPoint();
|
||||
}
|
||||
catch(const StdFail_NotDone &e) {
|
||||
Base::Console().Log("Geometry::asCircle - nearPoint: %s\n",e.GetMessageString());
|
||||
return result;
|
||||
}
|
||||
|
||||
// make 2 circles and find their radii
|
||||
gce_MakeCirc gce_circ1 = gce_MakeCirc(s,pc1,pcm); //3 point circle
|
||||
if (gce_circ1.Status() != gce_Done) {
|
||||
return result;
|
||||
}
|
||||
gp_Circ circle1 = gce_circ1.Value();
|
||||
double radius1 = circle1.Radius();
|
||||
gp_Pnt center1 = circle1.Location();
|
||||
Base::Vector3d vc1 = DrawUtil::gpPnt2V3(center1);
|
||||
// make 2 circles and find their radii
|
||||
gce_MakeCirc gce_circ1 = gce_MakeCirc(s,pc1,pcm); //3 point circle
|
||||
if (gce_circ1.Status() != gce_Done) {
|
||||
return result;
|
||||
}
|
||||
gp_Circ circle1 = gce_circ1.Value();
|
||||
double radius1 = circle1.Radius();
|
||||
gp_Pnt center1 = circle1.Location();
|
||||
Base::Vector3d vc1 = DrawUtil::gpPnt2V3(center1);
|
||||
|
||||
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm,pc2,e);
|
||||
if (gce_circ2.Status() != gce_Done) {
|
||||
return result;
|
||||
}
|
||||
gp_Circ circle2 = gce_circ2.Value();
|
||||
double radius2 = circle2.Radius();
|
||||
gp_Pnt center2 = circle2.Location();
|
||||
Base::Vector3d vc2 = DrawUtil::gpPnt2V3(center2);
|
||||
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm,pc2,e);
|
||||
if (gce_circ2.Status() != gce_Done) {
|
||||
return result;
|
||||
}
|
||||
gp_Circ circle2 = gce_circ2.Value();
|
||||
double radius2 = circle2.Radius();
|
||||
gp_Pnt center2 = circle2.Location();
|
||||
Base::Vector3d vc2 = DrawUtil::gpPnt2V3(center2);
|
||||
|
||||
// compare radii & centers
|
||||
double allowError = 0.001; //mm^-3 good enough for printing
|
||||
double radius;
|
||||
Base::Vector3d center;
|
||||
if ( (DrawUtil::fpCompare(radius2,radius1, allowError)) &&
|
||||
(vc1.IsEqual(vc2,allowError)) ) {
|
||||
if (arc) {
|
||||
GC_MakeArcOfCircle makeArc(s,pcm,e);
|
||||
Handle(Geom_TrimmedCurve) tCurve = makeArc.Value();
|
||||
BRepBuilderAPI_MakeEdge newEdge(tCurve);
|
||||
result = newEdge;
|
||||
} else {
|
||||
radius = (radius1 + radius2) / 2.0;
|
||||
center = (vc1 + vc2) / 2.0;
|
||||
gp_Pnt gCenter(center.x,center.y,center.z);
|
||||
gp_Ax2 stdZ(gCenter,gp_Dir(0,0,1));
|
||||
gp_Circ newCirc(stdZ,radius);
|
||||
BRepBuilderAPI_MakeEdge newEdge(newCirc);
|
||||
result = newEdge;
|
||||
// compare radii & centers
|
||||
double allowError = 0.001; //mm^-3 good enough for printing
|
||||
double radius;
|
||||
Base::Vector3d center;
|
||||
if ( (DrawUtil::fpCompare(radius2,radius1, allowError)) &&
|
||||
(vc1.IsEqual(vc2,allowError)) ) {
|
||||
if (arc) {
|
||||
GC_MakeArcOfCircle makeArc(s,pcm,e);
|
||||
Handle(Geom_TrimmedCurve) tCurve = makeArc.Value();
|
||||
BRepBuilderAPI_MakeEdge newEdge(tCurve);
|
||||
result = newEdge;
|
||||
} else {
|
||||
radius = (radius1 + radius2) / 2.0;
|
||||
center = (vc1 + vc2) / 2.0;
|
||||
gp_Pnt gCenter(center.x,center.y,center.z);
|
||||
gp_Ax2 stdZ(gCenter,gp_Dir(0,0,1));
|
||||
gp_Circ newCirc(stdZ,radius);
|
||||
BRepBuilderAPI_MakeEdge newEdge(newCirc);
|
||||
result = newEdge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (const Standard_Failure& e) {
|
||||
Base::Console().Log("Geom::asCircle - OCC error - %s - while approx spline as circle\n",
|
||||
e.GetMessageString());
|
||||
TopoDS_Edge nullReturn;
|
||||
result = nullReturn;
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Log("Geom::asCircle - unknown error occurred while approx spline as circle\n");
|
||||
TopoDS_Edge nullReturn;
|
||||
result = nullReturn;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1472,14 +1421,6 @@ std::string Vertex::getTagAsString(void) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//void Vertex::assignTag(const TechDraw::Vertex* v)
|
||||
//{
|
||||
// if(v->getTypeId() == this->getTypeId())
|
||||
// this->tag = v->tag;
|
||||
// else
|
||||
// throw Base::TypeError("Vertex tag can not be assigned as types do not match.");
|
||||
//}
|
||||
|
||||
void Vertex::dump(const char* title)
|
||||
{
|
||||
Base::Console().Message("TD::Vertex - %s - point: %s vis: %d cosmetic: %d cosLink: %d cosTag: %s\n",
|
||||
|
||||
Reference in New Issue
Block a user