For all issues regarding the Forums use, please, refer to the Forum Rules.

Our Solutions

Need professional assistance?
Consider our:

Support Offerings

 

Need to speed up your development?
Have a look at our:

Samples & Tools

 

Need some functionality extending standard OCCT capabilities?
Check out our:

Adv. Components

Related pages

How to slice a solid into faces

Dustin Specker's picture
Forums: 

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

Dustin Specker'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 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

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/Slicer/OccSliceLib.py
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/Concurrency/parallel_slicer.py

-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;i gp_Pnt slicecenter = centerp;
slicecenter.SetZ((double) i * sliceheight);

TopoDS_Shape rect = hsf::AddNewRectangle(slicecenter,gp::DZ(),width*2,height*2);
TopoDS_Shape rectfill = hsf::AddNewFillSurface(rect);
sliceB.Add(slices,rectfill);

}

TopoDS_Shape common = hsf::BooleanCommon(EOS,slices); // here are the slice planes

//display the common object.
//you can also use the topo explorer and search for wires, should be the boundaries of each face.

}

// *********************************** utility functions

TopoDS_Shape HSF::AddNewRectangle(gp_Pnt center, gp_Vec orient, double width, double height)
{

Geom_Plane myplane(center,orient);
gp_Pnt cp;
gp_Vec v1;
gp_Vec v2;
myplane.D1(0,0,cp,v1,v2);

gp_Pnt p1 = center;
p1 = HSF::MovePointByVector(p1,v1,-(width/2));
p1 = HSF::MovePointByVector(p1,v2,(height/2));

gp_Pnt p2 = center;
p2 = HSF::MovePointByVector(p2,v1,(width/2));
p2 = HSF::MovePointByVector(p2,v2,(height/2));

gp_Pnt p3 = center;
p3 = HSF::MovePointByVector(p3,v1,(width/2));
p3 = HSF::MovePointByVector(p3,v2,-(height/2));

gp_Pnt p4 = center;
p4 = HSF::MovePointByVector(p4,v1,-(width/2));
p4 = HSF::MovePointByVector(p4,v2,-(height/2));

//gp_Pnt p1(center.X()-(width/2),center.Y()+(height/2),0);
//gp_Pnt p2(center.X()+(width/2),center.Y()+(height/2),0);
//gp_Pnt p3(center.X()+(width/2),center.Y()-(height/2),0);
//gp_Pnt p4(center.X()-(width/2),center.Y()-(height/2),0);

BRepBuilderAPI_MakePolygon W;

W.Add(p1);
W.Add(p2);
W.Add(p3);
W.Add(p4);
W.Add(p1);

double angle = orient.Angle(gp::DY());
angle = (Pi*180) / angle;

//gp_Pnt uppoint = MovePointByVector(center,gp::DZ(),10);
//gp_Vec rotvec(center,uppoint);

TopoDS_Shape orientedshape;
//orientedshape = rotate(W,center,rotvec,angle);
orientedshape = W;

return orientedshape;

}

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;

}

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

}
catch(...)
{

}

return Result;

}

Attachments: 
Dustin Specker'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

Dustin Specker'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);

Contact us

Attention: DO NOT use this form for all kind of request for the removal of your personal data. Please follow this link for such cases.