Basic Face detection using BGL
This commit is contained in:
@@ -76,7 +76,8 @@ SET(Draw_SRCS
|
||||
DrawHatch.cpp
|
||||
DrawHatch.h
|
||||
DrawViewDraft.cpp
|
||||
DrawViewDraft.h)
|
||||
DrawViewDraft.h
|
||||
)
|
||||
|
||||
SET(TechDraw_SRCS
|
||||
AppTechDraw.cpp
|
||||
@@ -85,6 +86,8 @@ SET(TechDraw_SRCS
|
||||
DrawUtil.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
EdgeWalker.cpp
|
||||
EdgeWalker.h
|
||||
)
|
||||
|
||||
SET(Geometry_SRCS
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
//#include <limits>
|
||||
|
||||
#include <HLRBRep_Algo.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
@@ -45,8 +46,6 @@
|
||||
#include <Poly_PolygonOnTriangulation.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
@@ -61,6 +60,19 @@
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <Handle_Geom_Curve.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepLProp_CurveTool.hxx>
|
||||
#include <BRepLProp_CLProps.hxx>
|
||||
#include <GeomLib_Tool.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
//# include <Standard_ConstructionError.hxx>
|
||||
//# include <Standard_DomainError.hxx>
|
||||
#include <BRepExtrema_DistShapeShape.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
|
||||
#include <Base/BoundBox.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
@@ -69,12 +81,14 @@
|
||||
|
||||
#include "Geometry.h"
|
||||
#include "DrawViewPart.h"
|
||||
//#include "ProjectionAlgos.h"
|
||||
#include "DrawHatch.h"
|
||||
//#include "DrawViewDimension.h"
|
||||
#include "EdgeWalker.h"
|
||||
|
||||
|
||||
#include "DrawViewPartPy.h" // generated from DrawViewPartPy.xml
|
||||
|
||||
void _dumpEdge1(char* label, int i, TopoDS_Edge e);
|
||||
|
||||
using namespace TechDraw;
|
||||
using namespace std;
|
||||
|
||||
@@ -242,14 +256,162 @@ void DrawViewPart::extractFaces()
|
||||
geometryObject->clearFaceGeom();
|
||||
const std::vector<TechDrawGeometry::BaseGeom*>& goEdges = geometryObject->getEdgeGeometry();
|
||||
std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin();
|
||||
std::vector<TopoDS_Edge> occEdges;
|
||||
std::vector<TopoDS_Edge> origEdges;
|
||||
for (;itEdge != goEdges.end(); itEdge++) {
|
||||
occEdges.push_back((*itEdge)->occEdge);
|
||||
origEdges.push_back((*itEdge)->occEdge);
|
||||
}
|
||||
|
||||
//almost works. :(
|
||||
std::vector<TopoDS_Wire> wires = connectEdges(occEdges);
|
||||
std::vector<TopoDS_Wire> sortedWires = sortWiresBySize(wires,true); //smallest first
|
||||
std::vector<TopoDS_Edge> faceEdges = origEdges;
|
||||
std::vector<TopoDS_Edge>::iterator itOrig = origEdges.begin();
|
||||
|
||||
//HLR algo does not provide all edge intersections for edge endpoints.
|
||||
//need to split long edges touched by Vertex of another edge
|
||||
int idb = 0;
|
||||
for (; itOrig != origEdges.end(); itOrig++, idb++) {
|
||||
TopoDS_Vertex v1 = TopExp::FirstVertex((*itOrig));
|
||||
TopoDS_Vertex v2 = TopExp::LastVertex((*itOrig));
|
||||
std::vector<TopoDS_Edge>::iterator itNew = faceEdges.begin();
|
||||
std::vector<size_t> deleteList;
|
||||
std::vector<TopoDS_Edge> edgesToAdd;
|
||||
int idx = 0;
|
||||
for (; itNew != faceEdges.end(); itNew++,idx++) {
|
||||
if ( itOrig->IsSame(*itNew) ){
|
||||
continue;
|
||||
}
|
||||
bool removeThis = false;
|
||||
std::vector<TopoDS_Vertex> splitPoints;
|
||||
if (isOnEdge((*itNew),v1,false)) {
|
||||
splitPoints.push_back(v1);
|
||||
removeThis = true;
|
||||
}
|
||||
if (isOnEdge((*itNew),v2,false)) {
|
||||
splitPoints.push_back(v2);
|
||||
removeThis = true;
|
||||
}
|
||||
if (removeThis) {
|
||||
deleteList.push_back(idx);
|
||||
}
|
||||
|
||||
if (!splitPoints.empty()) {
|
||||
std::vector<TopoDS_Edge> subEdges = splitEdge(splitPoints,(*itNew));
|
||||
edgesToAdd.insert(std::end(edgesToAdd), std::begin(subEdges), std::end(subEdges));
|
||||
}
|
||||
}
|
||||
//delete the split edge(s) and add the subedges
|
||||
//TODO: look into sets or maps or???? for all this
|
||||
std::sort(deleteList.begin(),deleteList.end()); //ascending
|
||||
auto last = std::unique(deleteList.begin(), deleteList.end()); //duplicates at back
|
||||
deleteList.erase(last, deleteList.end()); //remove dupls
|
||||
std::vector<size_t>::reverse_iterator ritDel = deleteList.rbegin();
|
||||
for ( ; ritDel != deleteList.rend(); ritDel++) {
|
||||
faceEdges.erase(faceEdges.begin() + (*ritDel));
|
||||
}
|
||||
faceEdges.insert(std::end(faceEdges), std::begin(edgesToAdd),std::end(edgesToAdd));
|
||||
}
|
||||
|
||||
//find list of unique Vertex
|
||||
std::vector<TopoDS_Vertex> uniqueVert;
|
||||
for(auto& fe:faceEdges) {
|
||||
TopoDS_Vertex v1 = TopExp::FirstVertex(fe);
|
||||
TopoDS_Vertex v2 = TopExp::LastVertex(fe);
|
||||
bool addv1 = true;
|
||||
bool addv2 = true;
|
||||
for (auto v:uniqueVert) {
|
||||
if (isSamePoint(v,v1))
|
||||
addv1 = false;
|
||||
if (isSamePoint(v,v2))
|
||||
addv2 = false;
|
||||
}
|
||||
if (addv1)
|
||||
uniqueVert.push_back(v1);
|
||||
if (addv2)
|
||||
uniqueVert.push_back(v2);
|
||||
}
|
||||
|
||||
//rebuild every edge using only unique verts
|
||||
//this should help with connecting them later
|
||||
std::vector<TopoDS_Edge> cleanEdges;
|
||||
std::vector<WalkerEdge> walkerEdges;
|
||||
for (auto fe:faceEdges) {
|
||||
TopoDS_Vertex fev1 = TopExp::FirstVertex(fe);
|
||||
TopoDS_Vertex fev2 = TopExp::LastVertex(fe);
|
||||
int v1dx = findUniqueVert(fev1, uniqueVert);
|
||||
int v2dx = findUniqueVert(fev2, uniqueVert);
|
||||
BRepAdaptor_Curve adapt(fe);
|
||||
Handle_Geom_Curve c = adapt.Curve().Curve();
|
||||
BRepBuilderAPI_MakeEdge mkBuilder1(c, uniqueVert.at(v1dx), uniqueVert.at(v2dx));
|
||||
TopoDS_Edge eClean = mkBuilder1.Edge();
|
||||
cleanEdges.push_back(eClean);
|
||||
WalkerEdge we;
|
||||
we.v1 = v1dx;
|
||||
we.v2 = v2dx;
|
||||
walkerEdges.push_back(we);
|
||||
}
|
||||
|
||||
EdgeWalker ew;
|
||||
ew.setSize(uniqueVert.size());
|
||||
ew.loadEdges(walkerEdges);
|
||||
ew.perform();
|
||||
facelist result = ew.getResult();
|
||||
|
||||
facelist::iterator iFace = result.begin();
|
||||
std::vector<TopoDS_Wire> fw;
|
||||
for (;iFace != result.end(); iFace++) {
|
||||
edgelist::iterator iEdge = (*iFace).begin();
|
||||
std::vector<TopoDS_Edge> fe;
|
||||
for (;iEdge != (*iFace).end(); iEdge++) {
|
||||
fe.push_back(cleanEdges.at((*iEdge).idx));
|
||||
}
|
||||
std::vector<TopoDS_Wire> w = connectEdges(fe);
|
||||
fw.push_back(w.at(0)); //looks weird, but we only passing 1 wire's edges so we only want 1 wire back
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Wire> sortedWires = sortWiresBySize(fw,false);
|
||||
|
||||
//remove the largest wire (OuterWire of graph)
|
||||
Bnd_Box bigBox;
|
||||
if (!(sortedWires.back().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);
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Wire>::iterator itWire = sortedWires.begin();
|
||||
for (; itWire != sortedWires.end(); itWire++) {
|
||||
@@ -262,6 +424,113 @@ void DrawViewPart::extractFaces()
|
||||
}
|
||||
}
|
||||
|
||||
//obs?
|
||||
int DrawViewPart::findEdgeByWalkerEdge(WalkerEdge we, std::vector<TopoDS_Vertex> uniqueVert, std::vector<TopoDS_Edge>& edges)
|
||||
{
|
||||
int result = -1;
|
||||
TopoDS_Vertex v1 = uniqueVert.at(we.v1);
|
||||
TopoDS_Vertex v2 = uniqueVert.at(we.v2);
|
||||
int idx = 0;
|
||||
for (auto& e:edges) {
|
||||
TopoDS_Vertex ev1 = TopExp::FirstVertex(e);
|
||||
TopoDS_Vertex ev2 = TopExp::LastVertex(e);
|
||||
if ( (isSamePoint(v1,ev1) && isSamePoint(v2,ev2)) ||
|
||||
(isSamePoint(v2,ev1) && isSamePoint(v1,ev2)) ) {
|
||||
result = idx;
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int DrawViewPart::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 (isSamePoint(v,vx)) {
|
||||
result = idx;
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
} //if idx >= uniqueVert.size() TARFU
|
||||
return result;
|
||||
}
|
||||
|
||||
double DrawViewPart::simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2)
|
||||
{
|
||||
Standard_Real minDist = -1;
|
||||
|
||||
BRepExtrema_DistShapeShape extss(s1, s2);
|
||||
if (!extss.IsDone()) {
|
||||
Base::Console().Message("DVP - BRepExtrema_DistShapeShape failed");
|
||||
return -1;
|
||||
}
|
||||
int count = extss.NbSolution();
|
||||
if (count != 0) {
|
||||
minDist = extss.Value();
|
||||
} else {
|
||||
minDist = -1;
|
||||
}
|
||||
return minDist;
|
||||
}
|
||||
|
||||
bool DrawViewPart::isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, bool allowEnds)
|
||||
{
|
||||
bool result = false;
|
||||
double dist = simpleMinDist(v,e);
|
||||
if (dist < 0.0) {
|
||||
Base::Console().Error("DVP::isOnEdge - simpleMinDist failed: %.3f\n",dist);
|
||||
result = false;
|
||||
} else if (dist < Precision::Confusion()) {
|
||||
result = true;
|
||||
}
|
||||
if (result) {
|
||||
TopoDS_Vertex v1 = TopExp::FirstVertex(e);
|
||||
TopoDS_Vertex v2 = TopExp::LastVertex(e);
|
||||
if (isSamePoint(v,v1) || isSamePoint(v,v2)) {
|
||||
if (!allowEnds) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DrawViewPart::isSamePoint(TopoDS_Vertex v1, TopoDS_Vertex v2)
|
||||
{
|
||||
bool result = false;
|
||||
gp_Pnt p1 = BRep_Tool::Pnt(v1);
|
||||
gp_Pnt p2 = BRep_Tool::Pnt(v2);
|
||||
if (p1.IsEqual(p2,Precision::Confusion())) {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<TopoDS_Edge> DrawViewPart::splitEdge(std::vector<TopoDS_Vertex> splitPoints, TopoDS_Edge e)
|
||||
{
|
||||
std::vector<TopoDS_Edge> result;
|
||||
if (splitPoints.empty()) {
|
||||
return result;
|
||||
}
|
||||
TopoDS_Vertex vStart = TopExp::FirstVertex(e);
|
||||
TopoDS_Vertex vEnd = TopExp::LastVertex(e);
|
||||
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
Handle_Geom_Curve c = adapt.Curve().Curve();
|
||||
//simple version for 1 splitPoint
|
||||
//TODO: handle case where e is split in multiple points (ie circular edge cuts line twice)
|
||||
BRepBuilderAPI_MakeEdge mkBuilder1(c, vStart, splitPoints[0]);
|
||||
TopoDS_Edge e1 = mkBuilder1.Edge();
|
||||
BRepBuilderAPI_MakeEdge mkBuilder2(c, splitPoints[0], vEnd);
|
||||
TopoDS_Edge e2 = mkBuilder2.Edge();
|
||||
result.push_back(e1);
|
||||
result.push_back(e2);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
|
||||
{
|
||||
std::vector<TechDraw::DrawHatch*> result;
|
||||
@@ -272,7 +541,6 @@ std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
|
||||
result.push_back(hatch);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -331,20 +599,21 @@ std::vector<TopoDS_Wire> DrawViewPart::connectEdges (std::vector<TopoDS_Edge>& e
|
||||
|
||||
//tolerance sb tolerance of DrawViewPart instead of Precision::Confusion()?
|
||||
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges, Precision::Confusion(), Standard_False, hWires);
|
||||
|
||||
int len = hWires->Length();
|
||||
for(int i=1;i<=len;i++) {
|
||||
TopoDS_Wire w = TopoDS::Wire(hWires->Value(i));
|
||||
//if (BRep_Tool::IsClosed(w)) {
|
||||
if (BRep_Tool::IsClosed(w)) {
|
||||
result.push_back(w);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
//delete hEdges; //does Handle<> take care of this?
|
||||
//delete hWires;
|
||||
return result;
|
||||
}
|
||||
|
||||
//! return true if w1 bbox is bigger than w2 bbox
|
||||
//NOTE: this won't necessarily sort the OuterWire correctly (ex smaller wire, same bbox)
|
||||
class DrawViewPart::wireCompare: public std::binary_function<const TopoDS_Wire&,
|
||||
const TopoDS_Wire&, bool>
|
||||
{
|
||||
@@ -366,12 +635,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//sort wires in descending order of bbox diagonal. if reversed, then ascending bbox diagonal
|
||||
std::vector<TopoDS_Wire> DrawViewPart::sortWiresBySize(std::vector<TopoDS_Wire>& w, bool reverse)
|
||||
//sort wires in order of bbox diagonal.
|
||||
std::vector<TopoDS_Wire> DrawViewPart::sortWiresBySize(std::vector<TopoDS_Wire>& w, bool ascend)
|
||||
{
|
||||
std::vector<TopoDS_Wire> wires = w;
|
||||
std::sort(wires.begin(), wires.end(), wireCompare());
|
||||
if (reverse) {
|
||||
if (ascend) {
|
||||
std::reverse(wires.begin(),wires.end());
|
||||
}
|
||||
return wires;
|
||||
@@ -422,6 +691,22 @@ PyObject *DrawViewPart::getPyObject(void)
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
||||
|
||||
void _dumpEdge1(char* label, int i, TopoDS_Edge e)
|
||||
{
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
double start = BRepLProp_CurveTool::FirstParameter(adapt);
|
||||
double end = BRepLProp_CurveTool::LastParameter(adapt);
|
||||
BRepLProp_CLProps propStart(adapt,start,0,Precision::Confusion());
|
||||
const gp_Pnt& vStart = propStart.Value();
|
||||
BRepLProp_CLProps propEnd(adapt,end,0,Precision::Confusion());
|
||||
const gp_Pnt& vEnd = propEnd.Value();
|
||||
//Base::Console().Message("%s edge:%d start:(%.3f,%.3f,%.3f)/%0.3f end:(%.2f,%.3f,%.3f)/%.3f\n",label,i,
|
||||
// vStart.X(),vStart.Y(),vStart.Z(),start,vEnd.X(),vEnd.Y(),vEnd.Z(),end);
|
||||
Base::Console().Message("%s edge:%d start:(%.3f,%.3f,%.3f) end:(%.2f,%.3f,%.3f)\n",label,i,
|
||||
vStart.X(),vStart.Y(),vStart.Z(),vEnd.X(),vEnd.Y(),vEnd.Z());
|
||||
}
|
||||
|
||||
|
||||
// Python Drawing feature ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#ifndef _DrawViewPart_h_
|
||||
#define _DrawViewPart_h_
|
||||
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include "DrawView.h"
|
||||
@@ -34,13 +37,12 @@
|
||||
|
||||
namespace TechDraw {
|
||||
class DrawHatch;
|
||||
class WalkerEdge;
|
||||
}
|
||||
|
||||
namespace TechDraw
|
||||
{
|
||||
|
||||
/** Base class of all View Features in the drawing module
|
||||
*/
|
||||
class TechDrawExport DrawViewPart : public DrawView
|
||||
{
|
||||
PROPERTY_HEADER(TechDraw::DrawViewPart);
|
||||
@@ -106,6 +108,13 @@ protected:
|
||||
std::vector<TopoDS_Wire> sortWiresBySize(std::vector<TopoDS_Wire>& w, bool reverse = false);
|
||||
class wireCompare;
|
||||
|
||||
bool isOnEdge(TopoDS_Edge e, TopoDS_Vertex v, bool allowEnds = false);
|
||||
std::vector<TopoDS_Edge> splitEdge(std::vector<TopoDS_Vertex> splitPoints, TopoDS_Edge e);
|
||||
double simpleMinDist(TopoDS_Shape s1, TopoDS_Shape s2);
|
||||
bool isSamePoint(TopoDS_Vertex v1, TopoDS_Vertex v2);
|
||||
int findUniqueVert(TopoDS_Vertex vx, std::vector<TopoDS_Vertex> &uniqueVert);
|
||||
int findEdgeByWalkerEdge(WalkerEdge we, std::vector<TopoDS_Vertex> uniqueVert, std::vector<TopoDS_Edge>& edges);
|
||||
|
||||
private:
|
||||
static App::PropertyFloatConstraint::Constraints floatRange;
|
||||
|
||||
|
||||
148
src/Mod/TechDraw/App/EdgeWalker.cpp
Normal file
148
src/Mod/TechDraw/App/EdgeWalker.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2016 Wandererfan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//#include "PreCompiled.h"
|
||||
|
||||
#include "EdgeWalker.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
using namespace boost;
|
||||
|
||||
//*******************************************************
|
||||
//* edgeVisior methods
|
||||
//*******************************************************
|
||||
template <typename Edge>
|
||||
void edgeVisitor::next_edge(Edge e)
|
||||
{
|
||||
std::cout << e << " ";
|
||||
graph_traits<graph>::vertex_descriptor s = source(e,m_g);
|
||||
graph_traits<graph>::vertex_descriptor t = target(e,m_g);
|
||||
WalkerEdge we;
|
||||
we.v1 = s;
|
||||
we.v2 = t;
|
||||
we.idx = get(edge_index,m_g,e);
|
||||
faceEdges.push_back(we);
|
||||
}
|
||||
|
||||
void edgeVisitor::begin_face()
|
||||
{
|
||||
std::cout << "begin_face()" << std::endl;
|
||||
faceEdges.clear();
|
||||
}
|
||||
|
||||
void edgeVisitor::end_face()
|
||||
{
|
||||
std::cout << "end_face()" << std::endl;
|
||||
graphFaces.push_back(faceEdges);
|
||||
}
|
||||
|
||||
facelist edgeVisitor::getResult(void)
|
||||
{
|
||||
return graphFaces;
|
||||
}
|
||||
|
||||
void edgeVisitor::setGraph(graph& g)
|
||||
{
|
||||
std::cout << "setGraph()" << std::endl;
|
||||
m_g = g;
|
||||
}
|
||||
|
||||
//*******************************************************
|
||||
//* EdgeWalker
|
||||
//*******************************************************
|
||||
|
||||
EdgeWalker::EdgeWalker()
|
||||
{
|
||||
}
|
||||
|
||||
EdgeWalker::~EdgeWalker()
|
||||
{
|
||||
}
|
||||
|
||||
bool EdgeWalker::loadEdges(std::vector<WalkerEdge> edges)
|
||||
{
|
||||
std::cout << "loadEdges()" << std::endl;
|
||||
for (auto e: edges) {
|
||||
add_edge(e.v1,e.v2,m_g);
|
||||
}
|
||||
// add_edge(0, 1, m_g);
|
||||
// add_edge(2, 3, m_g);
|
||||
// add_edge(4, 0, m_g);
|
||||
// add_edge(5, 3, m_g);
|
||||
// add_edge(6, 7, m_g);
|
||||
// add_edge(6, 4, m_g);
|
||||
// add_edge(7, 5, m_g);
|
||||
// add_edge(8, 9, m_g);
|
||||
// add_edge(4, 1, m_g);
|
||||
// add_edge(1, 8, m_g);
|
||||
// add_edge(5, 2, m_g);
|
||||
// add_edge(2, 9, m_g);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EdgeWalker::setSize(int size)
|
||||
{
|
||||
std::cout << "setsize()" << std::endl;
|
||||
m_g.clear();
|
||||
for (int i = 0; i < size; i++) {
|
||||
boost::adjacency_list<>::vertex_descriptor vd = boost::add_vertex(m_g);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EdgeWalker::perform()
|
||||
{
|
||||
// Initialize the interior edge index
|
||||
//property<edge_index_t, int>
|
||||
property_map<TechDraw::graph, edge_index_t>::type e_index = get(edge_index, m_g);
|
||||
graph_traits<TechDraw::graph>::edges_size_type edge_count = 0;
|
||||
graph_traits<TechDraw::graph>::edge_iterator ei, ei_end;
|
||||
for(boost::tie(ei, ei_end) = edges(m_g); ei != ei_end; ++ei)
|
||||
put(e_index, *ei, edge_count++);
|
||||
|
||||
// Test for planarity - we know it is planar, we just want to
|
||||
// compute the planar embedding as a side-effect
|
||||
typedef std::vector< graph_traits<TechDraw::graph>::edge_descriptor > vec_t;
|
||||
std::vector<vec_t> embedding(num_vertices(m_g));
|
||||
boyer_myrvold_planarity_test(boyer_myrvold_params::graph = m_g,
|
||||
boyer_myrvold_params::embedding = &embedding[0]);
|
||||
|
||||
m_eV.setGraph(m_g);
|
||||
planar_face_traversal(m_g, &embedding[0], m_eV);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
facelist EdgeWalker::getResult()
|
||||
{
|
||||
TechDraw::facelist result = m_eV.getResult();
|
||||
TechDraw::facelist::iterator iFace = result.begin();
|
||||
for (;iFace != result.end(); iFace++) {
|
||||
std::cout << "face begins:" << std::endl;
|
||||
TechDraw::edgelist::iterator iEdge = (*iFace).begin();
|
||||
for (;iEdge != (*iFace).end(); iEdge++) {
|
||||
std::cout << (*iEdge).idx << ":(" << (*iEdge).v1 << ", " << (*iEdge).v2 << ") ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
93
src/Mod/TechDraw/App/EdgeWalker.h
Normal file
93
src/Mod/TechDraw/App/EdgeWalker.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2016 Wandererfan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TECHDRAW_EDGEWALKER_H
|
||||
#define TECHDRAW_EDGEWALKER_H
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/graph/boyer_myrvold_planar_test.hpp>
|
||||
#include <boost/graph/planar_face_traversal.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace TechDraw {
|
||||
using namespace boost;
|
||||
|
||||
typedef adjacency_list
|
||||
< vecS,
|
||||
vecS,
|
||||
undirectedS,
|
||||
property<vertex_index_t, int>,
|
||||
property<edge_index_t, int>
|
||||
>
|
||||
graph;
|
||||
|
||||
struct WalkerEdge {
|
||||
int v1;
|
||||
int v2;
|
||||
int idx;
|
||||
};
|
||||
|
||||
typedef std::vector<WalkerEdge> edgelist;
|
||||
typedef std::vector<edgelist> facelist ;
|
||||
|
||||
|
||||
class edgeVisitor : public planar_face_traversal_visitor
|
||||
{
|
||||
public:
|
||||
template <typename Edge>
|
||||
void next_edge(Edge e);
|
||||
void begin_face();
|
||||
void end_face();
|
||||
facelist getResult(void);
|
||||
void setGraph(graph& g);
|
||||
|
||||
private:
|
||||
edgelist faceEdges;
|
||||
facelist graphFaces;
|
||||
graph m_g;
|
||||
};
|
||||
|
||||
class EdgeWalker
|
||||
{
|
||||
public:
|
||||
EdgeWalker(void);
|
||||
virtual ~EdgeWalker();
|
||||
|
||||
bool loadEdges(std::vector<WalkerEdge> edges);
|
||||
bool setSize(int size);
|
||||
bool perform();
|
||||
facelist getResult();
|
||||
|
||||
private:
|
||||
edgeVisitor m_eV;
|
||||
graph m_g;
|
||||
};
|
||||
|
||||
} //end namespace
|
||||
|
||||
#endif //TECHDRAW_EDGEWALKER_H
|
||||
@@ -730,8 +730,8 @@ void _dumpEdge(char* label, int i, TopoDS_Edge e)
|
||||
const gp_Pnt& vStart = propStart.Value();
|
||||
BRepLProp_CLProps propEnd(adapt,end,0,Precision::Confusion());
|
||||
const gp_Pnt& vEnd = propEnd.Value();
|
||||
Base::Console().Message("%s edge:%d start:(%.3f,%.3f,%.3f) end:(%.2f,%.3f,%.3f)\n",label,i,
|
||||
vStart.X(),vStart.Y(),vStart.Z(),vEnd.X(),vEnd.Y(),vEnd.Z());
|
||||
Base::Console().Message("%s edge:%d start:(%.3f,%.3f,%.3f)/%0.3f end:(%.2f,%.3f,%.3f)/%.3f\n",label,i,
|
||||
vStart.X(),vStart.Y(),vStart.Z(),start,vEnd.X(),vEnd.Y(),vEnd.Z(),end);
|
||||
}
|
||||
|
||||
const char* _printBool(bool b)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
add_definitions(-DMOD_TECHDRAW_HANDLE_FACES=0)
|
||||
add_definitions(-DMOD_TECHDRAW_HANDLE_FACES=1)
|
||||
|
||||
add_subdirectory(App)
|
||||
if(BUILD_GUI)
|
||||
|
||||
@@ -44,7 +44,10 @@
|
||||
using namespace TechDrawGui;
|
||||
|
||||
QGIFace::QGIFace(int ref) :
|
||||
reference(ref)
|
||||
reference(ref),
|
||||
m_fill(Qt::NoBrush)
|
||||
//m_fill(Qt::CrossPattern)
|
||||
//m_fill(Qt::Dense3Pattern)
|
||||
{
|
||||
setCacheMode(QGraphicsItem::NoCache);
|
||||
setAcceptHoverEvents(true);
|
||||
@@ -59,7 +62,7 @@ QGIFace::QGIFace(int ref) :
|
||||
m_colPre = fcColor.asValue<QColor>();
|
||||
|
||||
//m_pen.setStyle(Qt::NoPen);
|
||||
//m_brush.setStyle(m_fill);
|
||||
m_brush.setStyle(m_fill);
|
||||
setPrettyNormal();
|
||||
}
|
||||
|
||||
@@ -112,10 +115,11 @@ void QGIFace::setPrettySel() {
|
||||
|
||||
void QGIFace::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
|
||||
QStyleOptionGraphicsItem myOption(*option);
|
||||
//myOption.state &= ~QStyle::State_Selected; //temp for debugging
|
||||
//myOption.state &= ~QStyle::State_Selected; //commented for debugging
|
||||
|
||||
//m_pen.setColor(m_colCurrent);
|
||||
//setPen(m_pen);
|
||||
//setBrush(m_brush);
|
||||
//m_brush.setStyle(m_fill);
|
||||
setBrush(m_brush);
|
||||
QGraphicsPathItem::paint (painter, &myOption, widget);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ private:
|
||||
QColor m_colNormal;
|
||||
QColor m_colPre;
|
||||
QColor m_colSel;
|
||||
Qt::BrushStyle m_fill;
|
||||
};
|
||||
|
||||
} // namespace MDIViewPageGui
|
||||
|
||||
@@ -296,15 +296,12 @@ void QGIViewPart::drawViewPart()
|
||||
facePen.setCosmetic(true);
|
||||
//QBrush faceBrush;
|
||||
for(int i = 0 ; fit != faceGeoms.end(); fit++, i++) {
|
||||
QGIFace* newFace = drawFace(*fit);
|
||||
QGIFace* newFace = drawFace(*fit,i);
|
||||
newFace->setPen(facePen);
|
||||
newFace->setZValue(ZVALUE::FACE);
|
||||
newFace->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
||||
//newFace->setBrush(faceBrush);
|
||||
}
|
||||
//debug a path
|
||||
//std::stringstream faceId;
|
||||
//faceId << "facePath" << i;
|
||||
//_dumpPath(faceId.str().c_str(),facePath);
|
||||
#endif //#if MOD_TECHDRAW_HANDLE_FACES
|
||||
|
||||
// Draw Hatches
|
||||
@@ -411,7 +408,7 @@ void QGIViewPart::drawViewPart()
|
||||
}
|
||||
}
|
||||
|
||||
QGIFace* QGIViewPart::drawFace(TechDrawGeometry::Face* f)
|
||||
QGIFace* QGIViewPart::drawFace(TechDrawGeometry::Face* f, int idx)
|
||||
{
|
||||
std::vector<TechDrawGeometry::Wire *> fWires = f->wires;
|
||||
QPainterPath facePath;
|
||||
@@ -430,11 +427,14 @@ QGIFace* QGIViewPart::drawFace(TechDrawGeometry::Face* f)
|
||||
}
|
||||
facePath.addPath(wirePath);
|
||||
}
|
||||
QGIFace* gFace = new QGIFace(-1);
|
||||
QGIFace* gFace = new QGIFace(idx);
|
||||
addToGroup(gFace);
|
||||
gFace->setPos(0.0,0.0);
|
||||
gFace->setPath(facePath);
|
||||
//_dumpPath("QGIVP.facePath",facePath);
|
||||
//debug a path
|
||||
//std::stringstream faceId;
|
||||
//faceId << "facePath " << idx;
|
||||
//_dumpPath(faceId.str().c_str(),facePath);
|
||||
|
||||
//gFace->setFlag(QGraphicsItem::ItemIsSelectable, true); ???
|
||||
return gFace;
|
||||
|
||||
@@ -83,7 +83,7 @@ protected:
|
||||
QPainterPath drawPainterPath(TechDrawGeometry::BaseGeom *baseGeom) const;
|
||||
std::vector <TechDraw::DrawHatch *> getHatchesForView(TechDraw::DrawViewPart* viewPart);
|
||||
void drawViewPart();
|
||||
QGIFace* drawFace(TechDrawGeometry::Face* f);
|
||||
QGIFace* drawFace(TechDrawGeometry::Face* f, int idx);
|
||||
|
||||
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ void QGIViewSection::drawSectionFace()
|
||||
facePen.setCosmetic(true);
|
||||
QBrush faceBrush(QBrush(QColor(0,0,255,40))); //temp. sb preference or property.
|
||||
for(; fit != sectionFaces.end(); fit++) {
|
||||
QGIFace* newFace = drawFace(*fit);
|
||||
QGIFace* newFace = drawFace(*fit,-1);
|
||||
newFace->setZValue(ZVALUE::SECTIONFACE);
|
||||
newFace->setBrush(faceBrush);
|
||||
newFace->setPen(facePen);
|
||||
|
||||
Reference in New Issue
Block a user