How to slice a solid into faces

Hello,

I need help as to how to slice a solid into several faces.

As of right now I'm using BRepAlgo_Section and building that to return a TopoDS_Shape. From there, I need to convert it to a face. I've tried converting and that failed. I've also tried to use TopExp_Explorer to find a face, but it doesn't find any. I believe the BRepAlgo_Section is working because when I display the result it looks like a slice.

I have attached a picture of a wire frame from different perspectives to demonstrate what kind of shapes I am trying to slice. I hope it clears up any confusion. As you can see the slices are displayed correctly (the white), but I need to convert them.

Thank you very much in advance,
Dustin

Attachments: 
AP's picture

Hi Dustin,

For each result of your section cut, im imagining your feeding it a Solid and a plane.
it returns a shape, this may have more than one wire since you could have holes so the process to get a face should be.

get the section shape
create a brep makeface object
use topo explorer and loop through the wires
for each wire add it to the makeface object using the add wire function

at the end get the makeface.shape object.
display the face object.

hope this helps.

Best,

AlexP

dustinspecker's picture

Thank you, AlexP.

I have tried that and have come across an issue. TopExp_Explorer reports that there are zero wires in the shape, which I don't understand. I can take the section shape and display it and see what I want, but it doesn't find any wires.

Here's my code. Perhaps I am misunderstanding something.

TopoDS_Shape R = S.Shape(); //shape from BRepAlgo_Section
TopExp_Explorer exp;
cout << "create face";
BRepBuilderAPI_MakeFace theface;
int wn = 0;
for(exp.Init(S.Shape(),TopAbs_WIRE);exp.More();exp.Next()){
theface.Add(TopoDS::Wire(exp.Current()));
wn++;
}
cout << wn;

It prints 0 and when I display the resultant face from theface the program crashes, but I believe that is because it has zero wires.

Thank you again,
Dustin

jelle's picture

here's a fairly complete slicer done by Dave Cowden in pythonocc:
https://github.com/tpaviot/pythonocc/blob/master/src/examples/Tools/Slic...
this is a simpler version of pretty much the same, though it uses all processors:
https://github.com/tpaviot/pythonocc/blob/master/src/examples/Level2/Con...

-jelle

AP's picture

I see, Ill look into it...

meanwhile try this function that makes a fill surface.

TopoDS_Shape HSF::AddNewFillSurface(TopoDS_Shape edge)
{

TopoDS_Shape Result;

if ( edge.ShapeType() == TopAbs_ShapeEnum::TopAbs_EDGE)
{
TopoDS_Edge aEdge = TopoDS::Edge(edge);

BRepFill_Filling* myfill = new BRepFill_Filling();
myfill->Add(aEdge,GeomAbs_Shape::GeomAbs_C0);
myfill->Build();
Result = myfill->Face();

return Result;
} else if ( edge.ShapeType() == TopAbs_ShapeEnum::TopAbs_WIRE)
{
BRepFill_Filling* myfill = new BRepFill_Filling();

TopExp_Explorer Ex;
for (Ex.Init(edge,TopAbs_EDGE); Ex.More(); Ex.Next())
{
TopoDS_Shape myshape = Ex.Current();
TopoDS_Edge aEdge = TopoDS::Edge(myshape);
myfill->Add(aEdge,GeomAbs_Shape::GeomAbs_C0);
}

myfill->Build();
Result = myfill->Face();

return Result;

}
return Result;

}

Best,

AlexP

AP's picture

Hi Dustin ,

This is a better way of doing the slices, but it takes a bit of time, the boolean operations are rather slow.

Best,

Alex

// *************************************************

void update()

{

if(EOS.IsNull())

{
QoccInputOutput* io_man = new QoccInputOutput();
QString filename = QFileDialog::getOpenFileName ( this,
tr("Import File"),"");

if (!(filename.length() > 0)) return;
Handle(TopTools_HSequenceOfShape) famshape1 = io_man->importSTEP(filename);
EOS = famshape1->Value(1);

}

double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
Bnd_Box Bnd;
BRepBndLib::Add(EOS, Bnd);
Bnd.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);

double width = abs(Xmax -Xmin);
double height = abs(Ymax -Ymin);
double depth = abs(Zmax -Zmin);

double slicecount = 100;

double sliceheight =(double) depth / slicecount;
gp_Pnt centerp((Xmin+Xmax)/2,(Ymin+Ymax)/2,(Zmin+Zmax)/2);

TopoDS_Compound slices;
BRep_Builder sliceB;
sliceB.MakeCompound(slices);

for(int i= 0;iAdd(aEdge,GeomAbs_Shape::GeomAbs_C0);
myfill->Build();
Result = myfill->Face();

return Result;
} else if ( edge.ShapeType() == TopAbs_ShapeEnum::TopAbs_WIRE)
{
BRepFill_Filling* myfill = new BRepFill_Filling();

TopExp_Explorer Ex;
for (Ex.Init(edge,TopAbs_EDGE); Ex.More(); Ex.Next())
{
TopoDS_Shape myshape = Ex.Current();
TopoDS_Edge aEdge = TopoDS::Edge(myshape);
myfill->Add(aEdge,GeomAbs_Shape::GeomAbs_C0);
}

myfill->Build();
Result = myfill->Face();

return Result;

}
return Result;

}

TopoDS_Shape HSF::BooleanCommon(TopoDS_Shape Stock,TopoDS_Shape Tool)
{
TopoDS_Shape Result;
try
{
Result = BRepAlgoAPI_Common(Stock,Tool);

}
catch(...)
{

}

return Result;

}

Attachments: 
dustinspecker's picture

Thank you very much, AlexP!

I do have one question, what is the function MovePointByVector? From the parameters it seems like you are doing more than just transforming a point via a vector. I don't understand the use of the third parameter. I apologize if I'm forgetting something obvious.

And your picture is demonstrating exactly what we are trying to accomplish.

Thank you for the help!
Dustin

jelle's picture

hear hear, is there a way of having a peek at your HSF lib?
looks pretty cool to me...

AP's picture

Hi Dustin,

I am just moving a point in the direction of a vector by a specified distance:

gp_Pnt HSF::MovePointByVector(gp_Pnt point, gp_Vec vector, double Offset)
{

gp_Vec aV = vector.Normalized();
aV = aV.Multiplied(Offset);

gp_Pnt newpoint;
newpoint.SetXYZ(point.XYZ() + aV.XYZ());

return newpoint;
}

Best

AlexP

dustinspecker's picture

Thank you again!

For some reason the common shape doesn't display anything, and I can't find any wires. I think it's empty.

I was curious and displayed the slices alongside the shape to slice and noticed that the slices were above the shape. Is this supposed to happen? I would presume it would be level with the shape. I have attached an image of what I mean.

Dustin

Attachments: 
AP's picture

Visualize the bounding box somehow and see that it is actually correct, it might be returning the wrong value, but the planes should begin at the bottom of the bounding box of your shape,

you could add an if statement saying that if the centerpoint is above the Zmax then dont create the plane.

Best,

AlexP

double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
Bnd_Box Bnd;
BRepBndLib::Add(yourshapehere, Bnd);
Bnd.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);