Improve handling of duplicate edges in projection

This commit is contained in:
WandererFan 2016-11-14 17:03:32 -05:00 committed by wmayer
parent 3797f7ebc3
commit 1f0899ef3d
7 changed files with 233 additions and 16 deletions

View File

@ -124,8 +124,8 @@ std::vector<TopoDS_Edge> DrawProjectSplit::getEdgesForWalker(TopoDS_Shape shape,
TechDrawGeometry::GeometryObject* DrawProjectSplit::buildGeometryObject(
TopoDS_Shape shape,
gp_Pnt& inputCenter,
TopoDS_Shape shape,
gp_Pnt& inputCenter,
Base::Vector3d direction)
{
TechDrawGeometry::GeometryObject* geometryObject = new TechDrawGeometry::GeometryObject("DrawProjectSplit");
@ -156,7 +156,7 @@ std::vector<TopoDS_Edge> DrawProjectSplit::getEdges(TechDrawGeometry::GeometryOb
if (!DrawUtil::isZeroEdge(e)) {
nonZero.push_back(e);
} else {
Base::Console().Message("INFO - DPS::extractFaces found ZeroEdge!\n");
Base::Console().Message("INFO - DPS::getEdges found ZeroEdge!\n");
}
}
faceEdges = nonZero;
@ -230,6 +230,8 @@ std::vector<TopoDS_Edge> DrawProjectSplit::getEdges(TechDrawGeometry::GeometryOb
if (newEdges.empty()) {
Base::Console().Log("LOG - DPS::extractFaces - no newEdges\n");
}
newEdges = removeDuplicateEdges(newEdges);
return newEdges;
}
@ -426,3 +428,103 @@ std::vector<splitPoint> DrawProjectSplit::sortSplits(std::vector<splitPoint>& s,
}
std::vector<TopoDS_Edge> DrawProjectSplit::removeDuplicateEdges(std::vector<TopoDS_Edge>& inEdges)
{
std::vector<TopoDS_Edge> result;
std::vector<edgeSortItem> temp;
unsigned int idx = 0;
for (auto& e: inEdges) {
edgeSortItem item;
TopoDS_Vertex v1 = TopExp::FirstVertex(e);
TopoDS_Vertex v2 = TopExp::LastVertex(e);
item.start = DrawUtil::vertex2Vector(v1);
item.end = DrawUtil::vertex2Vector(v2);
item.startAngle = DrawUtil::angleWithX(e,v1);
item.endAngle = DrawUtil::angleWithX(e,v2);
//catch reverse-duplicates
if (DrawUtil::vectorCompare(item.start,item.end) > 0) {
Base::Vector3d vTemp = item.start;
item.start = item.end;
item.end = vTemp;
double aTemp = item.startAngle;
item.startAngle = item.endAngle;
item.endAngle = aTemp;
}
item.idx = idx;
temp.push_back(item);
idx++;
}
std::vector<edgeSortItem> sorted = sortEdges(temp,true);
auto last = std::unique(sorted.begin(), sorted.end(), edgeSortItem::edgeEqual); //duplicates to back
sorted.erase(last, sorted.end()); //remove dupls
for (auto& e: sorted) {
result.push_back(inEdges.at(e.idx));
}
return result;
}
std::vector<edgeSortItem> DrawProjectSplit::sortEdges(std::vector<edgeSortItem>& e, bool ascend)
{
std::vector<edgeSortItem> sorted = e;
std::sort(sorted.begin(), sorted.end(), edgeSortItem::edgeCompare);
if (ascend) {
std::reverse(sorted.begin(),sorted.end());
}
return sorted;
}
//*************************
//* edgeSortItem Methods
//*************************
std::string edgeSortItem::dump(void)
{
std::string result;
std::stringstream builder;
builder << "edgeSortItem - s: " << DrawUtil::formatVector(start) << " e: " << DrawUtil::formatVector(end) <<
" sa: " << startAngle * 180.0/M_PI << " ea: " << endAngle* 180.0/M_PI << " idx: " << idx;
result = builder.str();
return result;
}
//true if "e1 < e2" - for sorting
/*static*/bool edgeSortItem::edgeCompare(const edgeSortItem& e1, const edgeSortItem& e2)
{
bool result = false;
int vCompare = DrawUtil::vectorCompare(e1.start, e2.start);
if ( vCompare == -1) {
result = true;
} else if (vCompare == 0) {
if (e1.startAngle < e2.startAngle) {
result = true;
} else if (DrawUtil::fpCompare(e1.startAngle, e2.startAngle)) {
if (e1.endAngle < e2.startAngle) {
result = true;
} else if (DrawUtil::fpCompare(e1.endAngle, e2.endAngle)) {
if (e1.idx < e2.idx) {
result = true;
}
}
}
}
return result;
}
//true if "e1 = e2" - for sorting/unique test
/*static*/bool edgeSortItem::edgeEqual(const edgeSortItem& e1, const edgeSortItem& e2)
{
bool result = false;
if ( (e1.start == e2.start) &&
(e1.end == e2.end) &&
(DrawUtil::fpCompare(e1.startAngle,e2.startAngle)) &&
(DrawUtil::fpCompare(e1.endAngle,e2.endAngle)) ) {
result = true;
}
return result;
}
//

View File

@ -46,12 +46,31 @@ class BaseGeom;
namespace TechDraw
{
struct splitPoint {
struct splitPoint
{
int i;
Base::Vector3d v;
double param;
};
class edgeSortItem
{
public:
edgeSortItem() {}
~edgeSortItem() {}
Base::Vector3d start;
Base::Vector3d end;
double startAngle;
double endAngle;
unsigned int idx;
static bool edgeCompare(const edgeSortItem& e1, const edgeSortItem& e2);
static bool edgeEqual(const edgeSortItem& e1, const edgeSortItem& e2);
std::string dump(void);
};
class TechDrawExport DrawProjectSplit
{
public:
@ -65,12 +84,16 @@ public:
static bool isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, double& param, bool allowEnds = false);
static std::vector<TopoDS_Edge> splitEdges(std::vector<TopoDS_Edge> orig, std::vector<splitPoint> splits);
static std::vector<TopoDS_Edge> split1Edge(TopoDS_Edge e, std::vector<splitPoint> splitPoints);
static double simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2); //const; //probably sb static or DrawUtil
static double simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2);
static std::vector<splitPoint> sortSplits(std::vector<splitPoint>& s, bool ascend);
static bool splitCompare(const splitPoint& p1, const splitPoint& p2);
static bool splitEqual(const splitPoint& p1, const splitPoint& p2);
static std::vector<TopoDS_Edge> removeDuplicateEdges(std::vector<TopoDS_Edge>& inEdges);
static std::vector<edgeSortItem> sortEdges(std::vector<edgeSortItem>& e, bool ascend);
protected:
static std::vector<TopoDS_Edge> getEdges(TechDrawGeometry::GeometryObject* geometryObject);

View File

@ -27,6 +27,7 @@
# include <sstream>
# include <cstring>
# include <cstdlib>
#include <cmath>
# include <exception>
# include <boost/regex.hpp>
# include <QString>
@ -155,6 +156,10 @@ double DrawUtil::angleWithX(TopoDS_Edge e, bool reverse)
u = end - start;
}
result = atan2(u.y,u.x);
if (result < 0) {
result += 2.0 * M_PI;
}
return result;
}
@ -200,6 +205,9 @@ double DrawUtil::angleWithX(TopoDS_Edge e, TopoDS_Vertex v)
}
}
result = atan2(uVec.y,uVec.x);
if (result < 0) { //map from [-PI:PI] to [0:2PI]
result += 2.0 * M_PI;
}
return result;
}
@ -224,6 +232,59 @@ bool DrawUtil::isLastVert(TopoDS_Edge e, TopoDS_Vertex v)
return result;
}
bool DrawUtil::fpCompare(const double& d1, const double& d2)
{
bool result = false;
if (std::fabs(d1 - d2) < FLT_EPSILON) {
result = true;
}
return result;
}
Base::Vector3d DrawUtil::vertex2Vector(const TopoDS_Vertex& v)
{
gp_Pnt gp = BRep_Tool::Pnt(v);
Base::Vector3d result(gp.X(),gp.Y(),gp.Z());
return result;
}
std::string DrawUtil::formatVector(const Base::Vector3d& v)
{
std::string result;
std::stringstream builder;
builder << " (" << v.x << "," << v.y << "," << v.z << ") ";
result = builder.str();
return result;
}
//! compare 2 vectors for sorting purposes ( -1 -> v1<v2, 0 -> v1 == v2, 1 -> v1 > v2)
int DrawUtil::vectorCompare(const Base::Vector3d& v1, const Base::Vector3d& v2)
{
int result = 0;
if (v1 == v2) {
return result;
}
if (v1.x < v2.x) {
result = -1;
} else if (DrawUtil::fpCompare(v1.x, v2.x)) {
if (v1.y < v2.y) {
result = -1;
} else if (DrawUtil::fpCompare(v1.y, v2.y)) {
if (v1.z < v2.z) {
result = -1;
} else {
result = 1;
}
} else {
result = 1; //v2y > v1y
}
} else {
result = 1; //v1x > v2x
}
return result;
}
//based on Function provided by Joe Dowsett, 2014
double DrawUtil::sensibleScale(double working_scale)

View File

@ -34,6 +34,8 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <Base/Vector3D.h>
namespace TechDraw
{
@ -50,6 +52,11 @@ class TechDrawExport DrawUtil {
static double angleWithX(TopoDS_Edge e, TopoDS_Vertex v);
static bool isFirstVert(TopoDS_Edge e, TopoDS_Vertex v);
static bool isLastVert(TopoDS_Edge e, TopoDS_Vertex v);
static bool fpCompare(const double& d1, const double& d2);
static Base::Vector3d vertex2Vector(const TopoDS_Vertex& v);
static std::string formatVector(const Base::Vector3d& v);
static int vectorCompare(const Base::Vector3d& v1, const Base::Vector3d& v2);
//debugging routines
static void dumpVertexes(const char* text, const TopoDS_Shape& s);

View File

@ -266,7 +266,7 @@ TechDrawGeometry::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape
void DrawViewPart::extractFaces()
{
geometryObject->clearFaceGeom();
const std::vector<TechDrawGeometry::BaseGeom*>& goEdges =
const std::vector<TechDrawGeometry::BaseGeom*>& goEdges =
geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin();
std::vector<TopoDS_Edge> origEdges;
@ -349,7 +349,7 @@ void DrawViewPart::extractFaces()
std::vector<splitPoint> sorted = DrawProjectSplit::sortSplits(splits,true);
auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back
sorted.erase(last, sorted.end()); //remove dupls
sorted.erase(last, sorted.end()); //remove dupl splits
std::vector<TopoDS_Edge> newEdges = DrawProjectSplit::splitEdges(faceEdges,sorted);
if (newEdges.empty()) {
@ -357,6 +357,8 @@ void DrawViewPart::extractFaces()
return;
}
newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges);
//find all the wires in the pile of faceEdges
EdgeWalker ew;
ew.loadEdges(newEdges);

View File

@ -536,6 +536,14 @@ bool WalkerEdge::isEqual(WalkerEdge w)
return (i.idx < j.idx);
}
std::string WalkerEdge::dump(void)
{
std::string result;
std::stringstream builder;
builder << "WalkerEdge - v1: " << v1 << " v2: " << v2 << " idx: " << idx << " ed: " << ed;
result = builder.str();
return result;
}
//*****************************************
// ewWire Methods
@ -615,24 +623,37 @@ std::string embedItem::dump(void)
std::stringstream builder;
builder << "embedItem - vertex: " << iVertex << " incidenceList: ";
for (auto& ii : incidenceList) {
builder << "e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/M_PI)) << "/ed: " << ii.eDesc;
builder << " e:" << ii.iEdge << "/a:" << (ii.angle * (180.0/M_PI)) << "/ed:" << ii.eDesc;
}
result = builder.str();
return result;
}
/*static*/ bool embedItem::iiCompare(incidenceItem i1, incidenceItem i2)
{
return (i1.angle > i2.angle);
}
std::vector<incidenceItem> embedItem::sortIncidenceList (std::vector<incidenceItem> &list, bool ascend)
{
//Base::Console().Message("TRACE - eI::sortIncidenceList()\n");
std::vector< incidenceItem > tempList = list;
std::sort(tempList.begin(), tempList.end(), embedItem::iiCompare);
std::sort(tempList.begin(), tempList.end(), incidenceItem::iiCompare);
if (ascend) {
std::reverse(tempList.begin(),tempList.end());
}
return tempList;
}
//*************************************
//* incidenceItem Methods
//*************************************
/*static*/ bool incidenceItem::iiCompare(const incidenceItem& i1, const incidenceItem& i2)
{
return (i1.angle > i2.angle);
}
/*static*/bool incidenceItem::iiEqual(const incidenceItem& i1, const incidenceItem& i2)
{
//TODO: this should compare edges also but eDesc comparision is by address
bool result = false;
if (i1.angle == i2.angle) {
}
return result;
}

View File

@ -79,6 +79,7 @@ class WalkerEdge
public:
static bool weCompare(WalkerEdge i, WalkerEdge j);
bool isEqual(WalkerEdge w);
std::string dump(void);
std::size_t v1;
std::size_t v2;
@ -131,7 +132,8 @@ public:
incidenceItem() {}
incidenceItem(int idx, double a, edge_t ed) {iEdge = idx; angle = a; eDesc = ed;}
~incidenceItem() {}
static bool iiCompare(const incidenceItem& i1, const incidenceItem& i2);
static bool iiEqual(const incidenceItem& i1, const incidenceItem& i2);
int iEdge;
double angle;
edge_t eDesc;
@ -149,7 +151,6 @@ public:
std::vector<incidenceItem> incidenceList;
std::string dump(void);
static std::vector<incidenceItem> sortIncidenceList (std::vector<incidenceItem> &list, bool ascend);
static bool iiCompare(incidenceItem i1, incidenceItem i2);
};