Skip to content

Commit

Permalink
OCC: add shape creation
Browse files Browse the repository at this point in the history
  • Loading branch information
benoit128 committed Sep 3, 2024
1 parent 7ea6e46 commit 1008cfd
Show file tree
Hide file tree
Showing 11 changed files with 394 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ Data*
*.foam/
out_foam/
chm000*
out.step

tools/MigrationSVN
84 changes: 84 additions & 0 deletions Cassiopee/OCC/OCC/Atomic/addSphere.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright 2013-2024 Onera.
This file is part of Cassiopee.
Cassiopee is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Cassiopee 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cassiopee. If not, see <http://www.gnu.org/licenses/>.
*/

#include "occ.h"
#include "TopoDS_Shape.hxx"
#include "TopTools_IndexedMapOfShape.hxx"
#include "TopExp.hxx"
#include "TopExp_Explorer.hxx"
#include "BRepPrimAPI_MakeSphere.hxx"

//=====================================================================
// Add a sphere to hook
//=====================================================================
PyObject* K_OCC::addSphere(PyObject* self, PyObject* args)
{
PyObject* hook; E_Float xc, yc, zc, R;
if (!PYPARSETUPLE_(args, O_ RRRR_, &hook, &xc, &yc, &zc, &R)) return NULL;

void** packet = NULL;
#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 1)
packet = (void**) PyCObject_AsVoidPtr(hook);
#else
packet = (void**) PyCapsule_GetPointer(hook, NULL);
#endif

/* previous shape */
//TopoDS_Shape* psh = (TopoDS_Shape*)packet[0];
//TopAbs_ShapeEnum ptype = curShape.ShapeType();
// == TopAbs_COMPOUND
//for(TopoDS_Iterator anExp(curShape); anExp.More(); anExp.Next()){
//const TopoDS_Shape &curShape1 = anExp.Value();

/* new sphere */
gp_Pnt center(xc, yc, zc);
BRepPrimAPI_MakeSphere makerSphere(center, R);
TopoDS_Shape sh = makerSphere.Shape();

// Building the Resulting Compound
/*
TopoDS_Compound aRes;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aRes);
aBuilder.Add(aRes, myBody);
aBuilder.Add(aRes, myThreading);
*/

/* export */
TopoDS_Shape* newshp = new TopoDS_Shape(sh);
packet[0] = newshp;

// Extract surfaces
TopTools_IndexedMapOfShape* ptr = (TopTools_IndexedMapOfShape*)packet[1];
delete ptr;
TopTools_IndexedMapOfShape* sf = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*newshp, TopAbs_FACE, *sf);
packet[1] = sf;

// Extract edges
TopTools_IndexedMapOfShape* ptr2 = (TopTools_IndexedMapOfShape*)packet[2];
delete ptr2;
TopTools_IndexedMapOfShape* se = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*newshp, TopAbs_EDGE, *se);
packet[2] = se;

Py_INCREF(Py_None);
return Py_None;

}
200 changes: 200 additions & 0 deletions Cassiopee/OCC/OCC/Atomic/bottle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// This code is taken from open cascade tutorial
#include "occ.h"

#include "gp_Pnt.hxx"
#include "TopoDS.hxx"
#include "TopoDS_Compound.hxx"
#include "Geom_TrimmedCurve.hxx"
#include "GC_MakeSegment.hxx"
#include "GC_MakeArcOfCircle.hxx"
#include "BRepBuilderAPI_MakeEdge.hxx"
#include "BRepBuilderAPI_MakeWire.hxx"
#include "TopoDS_Wire.hxx"
#include "TopoDS_Edge.hxx"
#include "gp_Ax1.hxx"
#include "gp_Ax2.hxx"
#include "gp_Trsf.hxx"
#include "gp_Vec.hxx"
#include "BRepBuilderAPI_Transform.hxx"
#include "TopoDS_Face.hxx"
#include "BRepBuilderAPI_MakeFace.hxx"
#include "BRepPrimAPI_MakePrism.hxx"
#include "BRepFilletAPI_MakeFillet.hxx"
#include "TopExp_Explorer.hxx"
#include "BRepPrimAPI_MakeCylinder.hxx"
#include "BRepAlgoAPI_Fuse.hxx"
#include "Geom_Surface.hxx"
#include "Geom_Plane.hxx"
#include "BRepOffsetAPI_MakeThickSolid.hxx"
#include "Geom_CylindricalSurface.hxx"
#include "Geom2d_Ellipse.hxx"
#include "Geom2d_TrimmedCurve.hxx"
#include "GCE2d_MakeSegment.hxx"
#include "BRepOffsetAPI_ThruSections.hxx"
#include "BRepLib.hxx"
#include "TopTools_IndexedMapOfShape.hxx"
#include "TopExp.hxx"
#include "TopExp_Explorer.hxx"

TopoDS_Shape MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight,
const Standard_Real myThickness)
{
// Profile : Define Support Points
gp_Pnt aPnt1(-myWidth / 2., 0, 0);
gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
gp_Pnt aPnt3(0, -myThickness / 2., 0);
gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
gp_Pnt aPnt5(myWidth / 2., 0, 0);
// Profile : Define the Geometry
Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4);
Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);
// Profile : Define the Topology
TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);
// Complete Profile
gp_Ax1 xAxis = gp::OX();
gp_Trsf aTrsf;
aTrsf.SetMirror(xAxis);
BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);
BRepBuilderAPI_MakeWire mkWire;
mkWire.Add(aWire);
mkWire.Add(aMirroredWire);
TopoDS_Wire myWireProfile = mkWire.Wire();
// Body : Prism the Profile
TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
gp_Vec aPrismVec(0, 0, myHeight);
TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);

// Body : Apply Fillets
BRepFilletAPI_MakeFillet mkFillet(myBody);
TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
while (anEdgeExplorer.More())
{
TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
// Add edge to fillet algorithm
mkFillet.Add(myThickness / 12., anEdge);
anEdgeExplorer.Next();
}
myBody = mkFillet.Shape();

// Body : Add the Neck
gp_Pnt neckLocation(0, 0, myHeight);
gp_Dir neckAxis = gp::DZ();
gp_Ax2 neckAx2(neckLocation, neckAxis);
Standard_Real myNeckRadius = myThickness / 4.;
Standard_Real myNeckHeight = myHeight / 10.;
BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
TopoDS_Shape myNeck = MKCylinder.Shape();
myBody = BRepAlgoAPI_Fuse(myBody, myNeck); // boolean union
return myBody;

// Body : Create a Hollowed Solid
TopoDS_Face faceToRemove;
Standard_Real zMax = -1;
for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next())
{
TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
// Check if <aFace> is the top face of the bottle's neck
Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane))
{
Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
gp_Pnt aPnt = aPlane->Location();
Standard_Real aZ = aPnt.Z();
if (aZ > zMax)
{
zMax = aZ;
faceToRemove = aFace;
}
}
}
TopTools_ListOfShape facesToRemove;
facesToRemove.Append(faceToRemove);
BRepOffsetAPI_MakeThickSolid BodyMaker;
//BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
myBody = BodyMaker.Shape();
// Threading : Create Surfaces
Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
// Threading : Define 2D Curves
gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
gp_Ax2d anAx2d(aPnt, aDir);
Standard_Real aMajor = 2. * M_PI;
Standard_Real aMinor = myNeckHeight / 10;

Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);
Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
// Threading : Build Edges and Wires
TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
BRepLib::BuildCurves3d(threadingWire1);
BRepLib::BuildCurves3d(threadingWire2);
// Create Threading
BRepOffsetAPI_ThruSections aTool(Standard_True);
aTool.AddWire(threadingWire1);
aTool.AddWire(threadingWire2);
aTool.CheckCompatibility(Standard_False);
TopoDS_Shape myThreading = aTool.Shape();
// Building the Resulting Compound
TopoDS_Compound aRes;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aRes);
aBuilder.Add(aRes, myBody);
aBuilder.Add(aRes, myThreading);
return aRes;
}

//=====================================================================
// Create the shape of a bottle
//=====================================================================
PyObject* K_OCC::bottle(PyObject* self, PyObject* args)
{
PyObject* hook; E_Float width, height, thickness;
if (!PYPARSETUPLE_(args, O_ RRR_, &hook, &width, &height, &thickness)) return NULL;

void** packet = NULL;
#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 1)
packet = (void**) PyCObject_AsVoidPtr(hook);
#else
packet = (void**) PyCapsule_GetPointer(hook, NULL);
#endif

TopoDS_Shape shp = MakeBottle(width, height, thickness);
TopoDS_Shape* newshp = new TopoDS_Shape(shp);

packet[0] = newshp;

// Extract surfaces
TopTools_IndexedMapOfShape* ptr = (TopTools_IndexedMapOfShape*)packet[1];
delete ptr;
TopTools_IndexedMapOfShape* sf = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*newshp, TopAbs_FACE, *sf);
packet[1] = sf;

// Extract edges
TopTools_IndexedMapOfShape* ptr2 = (TopTools_IndexedMapOfShape*)packet[2];
delete ptr2;
TopTools_IndexedMapOfShape* se = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*newshp, TopAbs_EDGE, *se);
packet[2] = se;

Py_INCREF(Py_None);
return Py_None;

}

70 changes: 70 additions & 0 deletions Cassiopee/OCC/OCC/Atomic/createEmptyCAD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright 2013-2024 Onera.
This file is part of Cassiopee.
Cassiopee is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Cassiopee 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cassiopee. If not, see <http://www.gnu.org/licenses/>.
*/

#include "occ.h"
#include "TopoDS_Shape.hxx"
#include "TopTools_IndexedMapOfShape.hxx"
#include "TopExp.hxx"
#include "TopExp_Explorer.hxx"


// ============================================================================
/* Convert CAD to OpenCascade hook */
// ============================================================================
PyObject* K_OCC::createEmptyCAD(PyObject* self, PyObject* args)
{
char* fileName; char* fileFmt;
if (!PyArg_ParseTuple(args, "ss", &fileName, &fileFmt)) return NULL;

TopoDS_Shape* shp = new TopoDS_Shape(); // empty shape

// Extract surfaces
TopTools_IndexedMapOfShape* surfs = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*shp, TopAbs_FACE, *surfs);
// Extract edges
TopTools_IndexedMapOfShape* edges = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(*shp, TopAbs_EDGE, *edges);

// copy the CAD file name and format
E_Int l = strlen(fileName);
char* fileNameC = new char [l+1];
strcpy(fileNameC, fileName);
l = strlen(fileFmt);
char* fileFmtC = new char [l+1];
strcpy(fileFmtC, fileFmt);

// capsule
PyObject* hook;
E_Int sizePacket = 5;
void** packet = new void* [sizePacket];
packet[0] = shp; // the top shape
packet[1] = surfs; // the face map
packet[2] = edges; // the edge map
packet[3] = fileNameC; // CAD file name
packet[4] = fileFmtC; // CAD file format

#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 1)
hook = PyCObject_FromVoidPtr(packet, NULL);
#else
hook = PyCapsule_New(packet, NULL, NULL);
#endif

return hook;

}
5 changes: 5 additions & 0 deletions Cassiopee/OCC/OCC/occ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ static PyMethodDef Pyocc [] =

{"readCAD", K_OCC::readCAD, METH_VARARGS},
{"writeCAD", K_OCC::writeCAD, METH_VARARGS},
{"createEmptyCAD", K_OCC::createEmptyCAD, METH_VARARGS},

{"bottle", K_OCC::bottle, METH_VARARGS},
{"addSphere", K_OCC::addSphere, METH_VARARGS},

{"getNbFaces", K_OCC::getNbFaces, METH_VARARGS},
{"getNbEdges", K_OCC::getNbEdges, METH_VARARGS},
{"getFileAndFormat", K_OCC::getFileAndFormat, METH_VARARGS},
Expand Down
5 changes: 5 additions & 0 deletions Cassiopee/OCC/OCC/occ.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ namespace K_OCC

PyObject* readCAD(PyObject* self, PyObject* args);
PyObject* writeCAD(PyObject* self, PyObject* args);
PyObject* createEmptyCAD(PyObject* self, PyObject* args);

PyObject* bottle(PyObject* self, PyObject* args);
PyObject* addSphere(PyObject* self, PyObject* args);

PyObject* getNbFaces(PyObject* self, PyObject* args);
PyObject* getNbEdges(PyObject* self, PyObject* args);
PyObject* getFileAndFormat(PyObject* self, PyObject* args);
Expand Down
Loading

0 comments on commit 1008cfd

Please sign in to comment.