Skip to content

Commit

Permalink
Part: support element mapping in all c++ features
Browse files Browse the repository at this point in the history
  • Loading branch information
realthunder committed Mar 21, 2018
1 parent d3a1241 commit 83a58cd
Show file tree
Hide file tree
Showing 24 changed files with 597 additions and 94 deletions.
95 changes: 95 additions & 0 deletions src/Mod/Part/App/CrossSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#endif

#include "CrossSection.h"
#include "TopoShapeOpCode.h"

using namespace Part;

Expand Down Expand Up @@ -199,3 +200,97 @@ void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std:
wires.push_back(aFix.Wire());
}
}

///////////////////////////////////////////////////////////////////////////
TopoCrossSection::TopoCrossSection(double a, double b, double c, const TopoShape& s, const char *op)
: a(a), b(b), c(c), shape(s), op(op?op:TOPOP_SLICE)
{
}

void TopoCrossSection::slice(int idx, double d, std::vector<TopoShape> &wires) const {
// Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results
// Fixes: 0001137: Incomplete slices when using Part.slice on a torus
bool found = false;
for(auto &s : shape.getSubTopoShapes(TopAbs_SOLID)) {
sliceSolid(idx, d, s, wires);
found = true;
}
if(!found) {
for(auto &s : shape.getSubTopoShapes(TopAbs_SHELL)) {
sliceSolid(idx, d, s, wires);
found = true;
}
if(!found) {
for(auto &s : shape.getSubTopoShapes(TopAbs_FACE))
sliceSolid(idx, d, s, wires);
}
}
}

TopoShape TopoCrossSection::slice(int idx, double d) const {
std::vector<TopoShape> wires;
slice(idx,d,wires);
return TopoShape().makECompound(wires,false,0,false);
}

void TopoCrossSection::sliceNonSolid(int idx, double d,
const TopoShape& shape, std::vector<TopoShape>& wires) const
{
BRepAlgoAPI_Section cs(shape.getShape(), gp_Pln(a,b,c,-d));
if (cs.IsDone()) {
std::string prefix(op);
if(idx>1) {
prefix += '_';
prefix += std::to_string(idx);
}
auto res = TopoShape().makEShape(cs,shape,prefix.c_str()).makEWires().getSubTopoShapes(TopAbs_WIRE);
wires.insert(wires.end(),res.begin(),res.end());
}
}

void TopoCrossSection::sliceSolid(int idx, double d,
const TopoShape& shape, std::vector<TopoShape>& wires) const
{
gp_Pln slicePlane(a,b,c,-d);
BRepBuilderAPI_MakeFace mkFace(slicePlane);
TopoShape face(idx);
face.setShape(mkFace.Face());

// Make sure to choose a point that does not lie on the plane (fixes #0001228)
gp_Vec tempVector(a,b,c);
tempVector.Normalize();//just in case.
tempVector *= (d+1.0);
gp_Pnt refPoint(0.0, 0.0, 0.0);
refPoint.Translate(tempVector);

BRepPrimAPI_MakeHalfSpace mkSolid(TopoDS::Face(face.getShape()), refPoint);
TopoShape solid(idx);
std::string prefix(op);
if(idx>1) {
prefix += '_';
prefix += std::to_string(idx);
}
solid.makEShape(mkSolid,face,prefix.c_str());
BRepAlgoAPI_Cut mkCut(shape.getShape(), solid.getShape());

if (mkCut.IsDone()) {
TopoShape res(shape.Tag,shape.Hasher);
std::vector<TopoShape> shapes;
shapes.push_back(shape);
shapes.push_back(solid);
res.makEShape(mkCut,shapes,prefix.c_str());
for(auto &face : res.getSubTopoShapes(TopAbs_FACE)) {
BRepAdaptor_Surface adapt(TopoDS::Face(face.getShape()));
if (adapt.GetType() == GeomAbs_Plane) {
gp_Pln plane = adapt.Plane();
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
auto repaired_wires = TopoShape(face.Tag).makEWires(
face.getSubTopoShapes(TopAbs_EDGE),prefix.c_str(),true).getSubTopoShapes(TopAbs_WIRE);
wires.insert(wires.end(),repaired_wires.begin(),repaired_wires.end());
}
}
}
}
}

19 changes: 19 additions & 0 deletions src/Mod/Part/App/CrossSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#define PART_CROSSSECTION_H

#include <list>
#include <vector>
#include <TopTools_IndexedMapOfShape.hxx>
#include "TopoShape.h"

class TopoDS_Shape;
class TopoDS_Wire;
Expand All @@ -49,6 +51,23 @@ class PartExport CrossSection
const TopoDS_Shape& s;
};

class PartExport TopoCrossSection
{
public:
TopoCrossSection(double a, double b, double c, const TopoShape& s, const char *op=0);
void slice(int idx, double d, std::vector<TopoShape> &wires) const;
TopoShape slice(int idx, double d) const;

private:
void sliceNonSolid(int idx, double d, const TopoShape&, std::vector<TopoShape>& wires) const;
void sliceSolid(int idx, double d, const TopoShape&, std::vector<TopoShape>& wires) const;

private:
double a,b,c;
const TopoShape& shape;
const char *op;
};

}

#endif // PART_CROSSSECTION_H
42 changes: 39 additions & 3 deletions src/Mod/Part/App/FeatureChamfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#endif


#include <App/Document.h>
#include "TopoShapeOpCode.h"
#include "FeatureChamfer.h"


Expand All @@ -53,11 +55,15 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
return new App::DocumentObjectExecReturn("No object linked");

try {
TopoDS_Shape baseShape = Feature::getShape(link);
TopoShape baseTopoShape = Feature::getTopoShape(link);
auto baseShape = baseTopoShape.getShape();
BRepFilletAPI_MakeChamfer mkChamfer(baseShape);
TopTools_IndexedMapOfShape mapOfEdges;
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
TopExp::MapShapesAndAncestors(baseShape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);


#ifdef FC_NO_ELEMENT_MAP
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfEdges);

std::vector<FilletElement> values = Edges.getValues();
Expand All @@ -73,7 +79,7 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
TopoDS_Shape shape = mkChamfer.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");
ShapeHistory history(mkChamfer, TopAbs_FACE, shape, baseShape);
ShapeHistory history(mkFillet, TopAbs_FACE, shape, baseTopoShape);
this->Shape.setValue(shape);

// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
Expand All @@ -82,6 +88,36 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
prop.setContainer(this);
prop.touch();

#else
const auto &vals = EdgeLinks.getSubValues();
const auto &subs = EdgeLinks.getShadowSubs();
if(subs.size()!=(size_t)Edges.getSize())
return new App::DocumentObjectExecReturn("Edge link size mismatch");
size_t i=0;
for(const auto &info : Edges.getValues()) {
auto &sub = subs[i];
auto &ref = sub.first.size()?sub.first:vals[i];
++i;
TopoDS_Shape edge;
try {
edge = baseTopoShape.getSubShape(ref.c_str());
}catch(...){}
if(edge.IsNull())
return new App::DocumentObjectExecReturn("Invalid edge link");
double radius1 = info.radius1;
double radius2 = info.radius2;
const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
mkChamfer.Add(radius1, radius2, TopoDS::Edge(edge), face);
}

TopoDS_Shape shape = mkChamfer.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");

TopoShape res(getID(),getDocument()->getStringHasher());
this->Shape.setValue(res.makEShape(mkChamfer,baseTopoShape,TOPOP_CHAMFER));
#endif

return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
Expand Down
Loading

0 comments on commit 83a58cd

Please sign in to comment.