Py binding for EdgeWalker
refactor EdgeWalker code from DVP,DVS
This commit is contained in:
@@ -27,9 +27,24 @@
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <ShapeFix_ShapeTolerance.hxx>
|
||||
#include <ShapeExtend_WireData.hxx>
|
||||
#include <ShapeFix_Wire.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "DrawUtil.h"
|
||||
#include "EdgeWalker.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
@@ -47,22 +62,22 @@ void edgeVisitor::next_edge(Edge e)
|
||||
we.v1 = s;
|
||||
we.v2 = t;
|
||||
we.idx = get(edge_index,m_g,e);
|
||||
faceEdges.push_back(we);
|
||||
wireEdges.push_back(we);
|
||||
}
|
||||
|
||||
void edgeVisitor::begin_face()
|
||||
{
|
||||
faceEdges.clear();
|
||||
wireEdges.clear();
|
||||
}
|
||||
|
||||
void edgeVisitor::end_face()
|
||||
{
|
||||
graphFaces.push_back(faceEdges);
|
||||
graphWires.push_back(wireEdges);
|
||||
}
|
||||
|
||||
TechDraw::facelist edgeVisitor::getResult(void)
|
||||
TechDraw::ewWireList edgeVisitor::getResult(void)
|
||||
{
|
||||
return graphFaces;
|
||||
return graphWires;
|
||||
}
|
||||
|
||||
void edgeVisitor::setGraph(TechDraw::graph& g)
|
||||
@@ -90,6 +105,15 @@ bool EdgeWalker::loadEdges(std::vector<TechDraw::WalkerEdge> edges)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EdgeWalker::loadEdges(std::vector<TopoDS_Edge> edges)
|
||||
{
|
||||
std::vector<TopoDS_Vertex> verts = makeUniqueVList(edges);
|
||||
setSize(verts.size());
|
||||
std::vector<WalkerEdge> we = makeWalkerEdges(edges, verts);
|
||||
saveInEdges = edges;
|
||||
|
||||
return loadEdges(we);
|
||||
}
|
||||
bool EdgeWalker::setSize(int size)
|
||||
{
|
||||
m_g.clear();
|
||||
@@ -122,28 +146,153 @@ bool EdgeWalker::perform()
|
||||
return true;
|
||||
}
|
||||
|
||||
facelist EdgeWalker::getResult()
|
||||
ewWireList EdgeWalker::getResult()
|
||||
{
|
||||
TechDraw::facelist result = m_eV.getResult();
|
||||
return result;
|
||||
ewWireList result = m_eV.getResult();
|
||||
// result is a list of many wires each of which is a list of many WE
|
||||
return result;
|
||||
}
|
||||
|
||||
//static methods
|
||||
bool EdgeWalker::orderEdges(WalkerEdge i, WalkerEdge j)
|
||||
std::vector<TopoDS_Wire> EdgeWalker::getResultWires()
|
||||
{
|
||||
ewWireList result = m_eV.getResult();
|
||||
|
||||
std::vector<ewWire>::iterator iWire = result.wires.begin(); // a WE within [WE]
|
||||
std::vector<TopoDS_Wire> fw;
|
||||
for (;iWire != result.wires.end(); iWire++) {
|
||||
std::vector<WalkerEdge>::iterator iEdge = (*iWire).wedges.begin();
|
||||
std::vector<TopoDS_Edge> topoEdges;
|
||||
for (;iEdge != (*iWire).wedges.end(); iEdge++) {
|
||||
TopoDS_Edge e = saveInEdges.at((*iEdge).idx);
|
||||
topoEdges.push_back(e);
|
||||
}
|
||||
TopoDS_Wire w = makeCleanWire(topoEdges); //make 1 clean wire from its edges
|
||||
fw.push_back(w);
|
||||
}
|
||||
return fw;
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Wire> EdgeWalker::getResultNoDups()
|
||||
{
|
||||
ewWireList result = m_eV.getResult();
|
||||
result = result.removeDuplicates();
|
||||
|
||||
std::vector<ewWire>::iterator iWire = result.wires.begin();
|
||||
std::vector<TopoDS_Wire> fw;
|
||||
for (;iWire != result.wires.end(); iWire++) {
|
||||
std::vector<WalkerEdge>::iterator iEdge = (*iWire).wedges.begin();
|
||||
std::vector<TopoDS_Edge> topoEdges;
|
||||
for (;iEdge != (*iWire).wedges.end(); iEdge++) {
|
||||
TopoDS_Edge e = saveInEdges.at((*iEdge).idx);
|
||||
topoEdges.push_back(e);
|
||||
}
|
||||
TopoDS_Wire w = makeCleanWire(topoEdges); //make 1 clean wire from its edges
|
||||
fw.push_back(w);
|
||||
}
|
||||
return fw;
|
||||
}
|
||||
|
||||
|
||||
//! make a clean wire with sorted, oriented, connected, etc edges
|
||||
TopoDS_Wire EdgeWalker::makeCleanWire(std::vector<TopoDS_Edge> edges, double tol)
|
||||
{
|
||||
TopoDS_Wire result;
|
||||
BRepBuilderAPI_MakeWire mkWire;
|
||||
ShapeFix_ShapeTolerance sTol;
|
||||
Handle(ShapeExtend_WireData) wireData = new ShapeExtend_WireData();
|
||||
|
||||
for (auto e:edges) {
|
||||
wireData->Add(e);
|
||||
}
|
||||
|
||||
Handle(ShapeFix_Wire) fixer = new ShapeFix_Wire;
|
||||
fixer->Load(wireData);
|
||||
fixer->Perform();
|
||||
fixer->FixReorder();
|
||||
fixer->SetMaxTolerance(tol);
|
||||
fixer->ClosedWireMode() = Standard_True;
|
||||
fixer->FixConnected(Precision::Confusion());
|
||||
fixer->FixClosed(Precision::Confusion());
|
||||
|
||||
for (int i = 1; i <= wireData->NbEdges(); i ++) {
|
||||
TopoDS_Edge edge = fixer->WireData()->Edge(i);
|
||||
sTol.SetTolerance(edge, tol, TopAbs_VERTEX);
|
||||
mkWire.Add(edge);
|
||||
}
|
||||
|
||||
result = mkWire.Wire();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Vertex> EdgeWalker:: makeUniqueVList(std::vector<TopoDS_Edge> edges)
|
||||
{
|
||||
std::vector<TopoDS_Vertex> uniqueVert;
|
||||
for(auto& e:edges) {
|
||||
TopoDS_Vertex v1 = TopExp::FirstVertex(e);
|
||||
TopoDS_Vertex v2 = TopExp::LastVertex(e);
|
||||
bool addv1 = true;
|
||||
bool addv2 = true;
|
||||
for (auto v:uniqueVert) {
|
||||
if (DrawUtil::isSamePoint(v,v1))
|
||||
addv1 = false;
|
||||
if (DrawUtil::isSamePoint(v,v2))
|
||||
addv2 = false;
|
||||
}
|
||||
if (addv1)
|
||||
uniqueVert.push_back(v1);
|
||||
if (addv2)
|
||||
uniqueVert.push_back(v2);
|
||||
}
|
||||
return uniqueVert;
|
||||
}
|
||||
|
||||
//!make WalkerEdges (unique Vertex index pairs) from edge list
|
||||
std::vector<WalkerEdge> EdgeWalker::makeWalkerEdges(std::vector<TopoDS_Edge> edges,
|
||||
std::vector<TopoDS_Vertex> verts)
|
||||
{
|
||||
std::vector<WalkerEdge> walkerEdges;
|
||||
for (auto e:edges) {
|
||||
TopoDS_Vertex ev1 = TopExp::FirstVertex(e);
|
||||
TopoDS_Vertex ev2 = TopExp::LastVertex(e);
|
||||
int v1dx = findUniqueVert(ev1, verts);
|
||||
int v2dx = findUniqueVert(ev2, verts);
|
||||
WalkerEdge we;
|
||||
we.v1 = v1dx;
|
||||
we.v2 = v2dx;
|
||||
walkerEdges.push_back(we);
|
||||
}
|
||||
return walkerEdges;
|
||||
}
|
||||
|
||||
int EdgeWalker::findUniqueVert(TopoDS_Vertex vx, std::vector<TopoDS_Vertex> &uniqueVert)
|
||||
{
|
||||
int idx = 0;
|
||||
int result = 0;
|
||||
for(auto& v:uniqueVert) { //we're always going to find vx, right?
|
||||
if (DrawUtil::isSamePoint(v,vx)) {
|
||||
result = idx;
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
} //if idx >= uniqueVert.size() TARFU
|
||||
return result;
|
||||
}
|
||||
|
||||
/*static*/ bool WalkerEdge::weCompare(WalkerEdge i, WalkerEdge j)
|
||||
{
|
||||
return (i.idx < j.idx);
|
||||
}
|
||||
|
||||
bool EdgeWalker::isEqual(edgelist el1, edgelist el2)
|
||||
bool ewWire::isEqual(ewWire w2)
|
||||
{
|
||||
bool result = true;
|
||||
if (el1.size() != el2.size()) {
|
||||
if (wedges.size() != w2.wedges.size()) {
|
||||
result = false;
|
||||
} else {
|
||||
std::sort(el1.begin(),el1.end(),orderEdges);
|
||||
std::sort(el2.begin(),el2.end(),orderEdges);
|
||||
for (unsigned int i = 0; i < el1.size(); i ++) {
|
||||
if (el1.at(i).idx != el2.at(i).idx) {
|
||||
std::sort(wedges.begin(),wedges.end(),WalkerEdge::weCompare);
|
||||
std::sort(w2.wedges.begin(),w2.wedges.end(),WalkerEdge::weCompare);
|
||||
for (unsigned int i = 0; i < w2.wedges.size(); i ++) {
|
||||
if (wedges.at(i).idx != w2.wedges.at(i).idx) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
@@ -152,23 +301,122 @@ bool EdgeWalker::isEqual(edgelist el1, edgelist el2)
|
||||
return result;
|
||||
}
|
||||
|
||||
//check faces that use the same set of edges, but maybe in a different order.
|
||||
facelist EdgeWalker::removeDuplicateFaces(facelist in)
|
||||
void ewWire::push_back(WalkerEdge w)
|
||||
{
|
||||
facelist result;
|
||||
result.push_back(*(in.begin())); //save the first edgelist
|
||||
facelist::iterator iFace = (in.begin()) + 1; //starting with second
|
||||
for (; iFace != in.end(); iFace++) {
|
||||
wedges.push_back(w);
|
||||
}
|
||||
|
||||
//check wirelist for wires that use the same set of edges, but maybe in a different order.
|
||||
ewWireList ewWireList::removeDuplicates()
|
||||
{
|
||||
ewWireList result;
|
||||
result.push_back(*(wires.begin())); //save the first ewWire
|
||||
std::vector<ewWire>::iterator iWire = (wires.begin()) + 1; //starting with second
|
||||
for (; iWire != wires.end(); iWire++) {
|
||||
bool addToResult = true;
|
||||
for (auto& e:result) {
|
||||
if (isEqual((*iFace),e)) { //already in result?
|
||||
for (auto& w:result.wires) {
|
||||
if ((*iWire).isEqual(w)) { //already in result?
|
||||
addToResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addToResult) {
|
||||
result.push_back((*iFace));
|
||||
result.push_back((*iWire));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ewWireList::push_back(ewWire w)
|
||||
{
|
||||
wires.push_back(w);
|
||||
}
|
||||
|
||||
|
||||
std::vector<TopoDS_Wire> EdgeWalker::sortStrip(std::vector<TopoDS_Wire> fw, bool includeBiggest)
|
||||
{
|
||||
std::vector<TopoDS_Wire> sortedWires = sortWiresBySize(fw,false); //biggest 1st
|
||||
if (!sortedWires.size()) {
|
||||
Base::Console().Log("INFO - DVP::extractFaces - no sorted Wires!\n");
|
||||
return sortedWires; // might happen in the middle of changes?
|
||||
}
|
||||
|
||||
if (includeBiggest) {
|
||||
return sortedWires; // all the wires
|
||||
}
|
||||
|
||||
//remove the largest wire (OuterWire of graph) wf: still not convinced we should do this in all cases.
|
||||
Bnd_Box bigBox;
|
||||
if (sortedWires.size() && !sortedWires.front().IsNull()) {
|
||||
BRepBndLib::Add(sortedWires.front(), bigBox);
|
||||
bigBox.SetGap(0.0);
|
||||
}
|
||||
std::vector<std::size_t> toBeChecked;
|
||||
std::vector<TopoDS_Wire>::iterator it = sortedWires.begin() + 1;
|
||||
for (; it != sortedWires.end(); it++) {
|
||||
if (!(*it).IsNull()) {
|
||||
Bnd_Box littleBox;
|
||||
BRepBndLib::Add((*it), littleBox);
|
||||
littleBox.SetGap(0.0);
|
||||
if (bigBox.SquareExtent() > littleBox.SquareExtent()) {
|
||||
break;
|
||||
} else {
|
||||
auto position = std::distance( sortedWires.begin(), it ); //get an index from iterator
|
||||
toBeChecked.push_back(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
//unfortuneately, faces can have same bbox, but not be same size. need to weed out biggest
|
||||
if (toBeChecked.size() == 0) {
|
||||
//nobody had as big a bbox as first element of sortedWires
|
||||
sortedWires.erase(sortedWires.begin());
|
||||
} else if (toBeChecked.size() > 0) {
|
||||
BRepBuilderAPI_MakeFace mkFace(sortedWires.front());
|
||||
const TopoDS_Face& face = mkFace.Face();
|
||||
GProp_GProps props;
|
||||
BRepGProp::SurfaceProperties(face, props);
|
||||
double bigArea = props.Mass();
|
||||
unsigned int bigIndex = 0;
|
||||
for (unsigned int idx = 1; idx < toBeChecked.size(); idx++) {
|
||||
BRepBuilderAPI_MakeFace mkFace2(sortedWires.at(idx));
|
||||
const TopoDS_Face& face2 = mkFace2.Face();
|
||||
BRepGProp::SurfaceProperties(face2, props);
|
||||
double area = props.Mass();
|
||||
if (area > bigArea) {
|
||||
bigArea = area;
|
||||
bigIndex = idx;
|
||||
}
|
||||
}
|
||||
sortedWires.erase(sortedWires.begin() + bigIndex);
|
||||
}
|
||||
return sortedWires;
|
||||
}
|
||||
|
||||
//sort wires in order of bbox diagonal.
|
||||
std::vector<TopoDS_Wire> EdgeWalker::sortWiresBySize(std::vector<TopoDS_Wire>& w, bool ascend)
|
||||
{
|
||||
std::vector<TopoDS_Wire> wires = w;
|
||||
std::sort(wires.begin(), wires.end(), EdgeWalker::wireCompare);
|
||||
if (ascend) {
|
||||
std::reverse(wires.begin(),wires.end());
|
||||
}
|
||||
return wires;
|
||||
}
|
||||
|
||||
//! return true if w1 bbox is bigger than w2 bbox
|
||||
//NOTE: this won't necessarily sort the OuterWire correctly (ex smaller wire, same bbox)
|
||||
/*static*/bool EdgeWalker::wireCompare(const TopoDS_Wire& w1, const TopoDS_Wire& w2)
|
||||
{
|
||||
Bnd_Box box1, box2;
|
||||
if (!w1.IsNull()) {
|
||||
BRepBndLib::Add(w1, box1);
|
||||
box1.SetGap(0.0);
|
||||
}
|
||||
|
||||
if (!w2.IsNull()) {
|
||||
BRepBndLib::Add(w2, box2);
|
||||
box2.SetGap(0.0);
|
||||
}
|
||||
|
||||
return box1.SquareExtent() > box2.SquareExtent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user