# Extracting geometry information (knot vectors, control polygon) from solids

Hi erveryone,

first of all I am using pythonOCC. Still my examples should be easily understandable.

My goal: Extract geometry information ( knot vectors, control points ) from solids

My approach so far:
I am extracting geometry information like knot vectors, control points from imported IGES files for modification purposes. I implemented a solution by converting my imported TopoDS_Shapes to surfaces and using the methods of the Geom_BSplineSurface instances to extract the data. My approach for surfaces works like this:

######### Code - written in python 2.7
from OCC.Utils.Topology import Topo
#
topologyOfShape = Topo(shape) # Topology object of shape returned by Iges import
face = topologyOfShape.faces().next() # get face of shape
#
# convert to a surface object to extract geometry data:
#
brep_surf = BRep_Tool().Surface(face)
bspline_surf_handle = Convert.GeomConvert_SurfaceToBSplineSurface(brep_surf)
_occObj = bspline_surf_handle.GetObject()
#
# extract the data
#
nUKnots = _occObj.NbUKnots() # knot vector number
nVKnots = _occObj.NbVKnots() # knot vector number
#
nU = _occObj.NbUPoles() # control points number
nV = _occObj.NbVPoles() # control points number
#
pU = _occObj.UDegree() # degree
pV = _occObj.VDegree() # degree

# get control polygon
#
#
controlPolygonCoordinates = np.zeros((nU,nV,4)) # matrix of control points, with weights as fourth coordinate
#
for poleU in xrange(nU):
for poleV in xrange(nV):
pnt = _occObj.Pole(poleU+1,poleV+1)
weight = _occObj.Weight(poleU+1,poleV+1)
controlPolygonCoordinates[poleU,poleV,:] = np.array([pnt.X(), pnt.Y(), pnt.Z(), weight])
#
######### /Code

Of course, this returns a controlpolygon which is two dimensional (U,V with control point coords and weights), describing the surface.

My questions:
1. Is there a way to extract the data for a solid? As far as I know a solid is just composed of a closed shell containing a number of faces.
I could extract the data for the faces in the same way as shown above. Then I could manipulate their control polygons but I would be more happy with a solution which would give me a three dimensional control polygon (3D meaning a grid of U,V,W containing control points having coordinates and weights).
2. One way to attain a 3D control polygon would be to extract this data from a cube and rebuilding the control polygon with the face data. After manipulating the controlpolygon, do I have to rebuild the faces or is there a way to use the 3D control polygon data to build a solid?

Thank you for your time and input.
Best regards!

>1. Is there a way to extract the data for a solid?

why not create another Topo class for every consecutive topological level?

tp = Topo(your_geometry)

for solid in tp.solids():
for shell in Topo(solid).shells():
for faces in Topo(shell).faces():

possible the dump_topology function in the Topology.py module offers perspective:

def dump_topology(shape,level=0):
"""
Print the details of an object from the top down
"""
brt = BRep_Tool()
s = shape.ShapeType()
ts = TopoDS.TopoDS()
print
print "." * level,topo_lut[shape.ShapeType()],
if s == TopAbs_VERTEX:
pnt = vertex2pnt(shape_lut[shape])
print "" % (pnt.X(), pnt.Y(), pnt.Z())
it = TopoDS.TopoDS_Iterator(shape)
while it.More():
shp = it.Value()
it.Next()
dump_topology(shp,level + 1 )

> As far as I know a solid is just composed of a closed shell containing a number of faces.

Correct.
Note that indeed shells are below, but compsolids and compounds are above solids in the topological hierarchy.

>I could extract the data for the faces in the same way as shown above. Then I could manipulate their control polygons but I would be more happy with a solution which would give me a three dimensional control polygon (3D meaning a grid of U,V,W containing control points having coordinates and weights).

Isn't that defined by the surface.Pole(index) method?

>2. One way to attain a 3D control polygon would be to extract this data from a cube and rebuilding the control polygon with the face data. After manipulating the controlpolygon, do I have to rebuild the faces or is there a way to use the 3D control polygon data to build a solid?

Take a look here [1], at the Update* methods and at the BRepTools_Modification module.

you've given quite a technical, but not a conceptual explanation of what you want to achieve.
perhaps the latter helps to provide better feedback.

-jelle

My goal is to use the data in isogeoemtric analyses. I.e. using the NURBS as basis functions for structural analyses as in FEM, avoiding the need for mesh generation and using the exact geometry. By having a control polygon spanning in 3 dimensions I could model solid elements for stress computations. For example, I would have a 5x5x5 control polygon (rows, columns, layers) where each point is defined by the 3D coordinates in space and a weight. This is working with handcrafted control polygons. Now I am trying to extract this data from models created by CAD engines which would allow easier model creation by using CAD tools.

> why not create another Topo class for every consecutive topological level?

My first try included the the dumpTopology(shape) function but I received the following error:

>>.......... Compound.:18301873
>>........... Compound.:5294236
>>............ Solid:12865348
>>............. Shell:9887876
>>.............. Face:5740524
>>............... Wire:9873892
>>................ Edge:14498548
>>................. Vertex:13457588
>>Traceback (most recent call last):
>>print dumpTopology(shape,level=10)
File "/usr/local/lib/python2.7/dist-packages/OCC/Utils/Topology.py", line 418, in dumpTopology
dumpTopology(shp,level + 1 )
--> multiple recursions and finally:
>>pnt = brt.Pnt(ts.Vertex(shape))
>>AttributeError: 'TopoDS' object has no attribute 'Vertex'

I did not investigate whether I might have a version problem here (using OCE-0.11 and pythonOCC 0.6-alpha atm). I will try this function on a different machine tomorrow.

>>>I could extract the data for the faces in the same way as shown above. Then I could manipulate their control polygons but I would be more happy with a solution which would give me a three dimensional control polygon (3D meaning a grid of U,V,W containing control points having coordinates and weights).

> Isn't that defined by the surface.Pole(index) method?

Yes I can extract the control polygon points with this function, as shown in my example with
>>pnt = _occObj.Pole(poleU+1,poleV+1)
However, this will give me the control points of the surface (made from a face), which is only part of the solid. I was wondering if it is possible to extrude the data for a solid like this:
>>pnt = _occObj.Pole(poleU+1,poleV+1,poleW+1)

then I would create the 3D control polygon that is not a 2D but a 3D matrix
>>ControlPolygonCoordinates[poleU,poleV,poleW,:] = np.array([pnt.X(), pnt.Y(), pnt.Z(), weight])

>Take a look here [1], at the Update* methods and at the BRepTools_Modification module

I am sorry, I cannot see how these functions would help me. Could you elaborate?

My example to use the face data to construct the control polygon would be rather bothersome. I meant to do it in the following way:

Extracting the Poles of each surface (face) of a box gives a matrix (2D, rows&columns) of control points for each face. Each Control point position in this U,V-matrix is filed with the control point coordinates and its weight.

face1 (faceNb-PoleU-PoleV)
f1u1v1 - f1u2v1 - f1u3v1
| | |
f1u1v2 - f1u2v2 - f1u3v2
| | |
f1u1v3 - f1u2v3 - f1u3v3

I could use the data of all six faces to construct the borders of a 3D control polygon. The center points would be interpolated from the border. This would give me a matrix (like a cube) consisting of rows, columns and layers. Of course the real coordinates of the control points do not have to lie in formation, only the connectivity between them is fixed by this U,V,W-matrix.

Another concern in the future would be the reconstruction of a solid from this data. I would have to reconstruct the 2D control polygons, create surfaces, makeFaces, sew them and then construct a solid. Of course its feasible but if there is a function like
>>Geom_BSplineSurface(polygon, Weights, knotU, knotV, multU, multV, degreeV, degreeU)
for a solid where I can directly input a polygon it would simplify the reconstruction.

Best regards