[TD]add ability to filter obvious geometry errors

- also add checks for geometry errors
This commit is contained in:
wandererfan
2019-12-08 20:34:47 -05:00
committed by WandererFan
parent 17b61adf16
commit e1e9c7e7bd
6 changed files with 218 additions and 197 deletions

View File

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