3D Geometry API - A Gentle Introduction


Among tangible or visible geometric elements, the prominently accessed collections in a Part or Sheetmetal document are the Features, Sketches, Profiles, PMI and the Reference Planes. The most sought after automation requirements include parametric updating of models or creation of simple parts involving sketches that are extruded or revolved.


It is rare for a designer who is also typically a Mechanical guy having specialized as an automation programmer caring to think about diving into low level geometry like the faces, edges and vertices to manipulate model geometry in a more powerful and direct manner.


But once you know how to extract and use it, the possibilities are endless. Some common examples would be custom composite holes or Sheetmetal punch shapes. A scenario of a custom composite hole would be a .150 diameter counterbore with a depth of .200.  At the bottom of the counterbore is a thru hole of .050 diameter with a nearside countersink of .070 diameter.



Although this article does not aim to show you all the geometric calculations and APIs involved in achieving such composite holes, it is a beginning in the right direction.


Note the additional Solid Edge Geometry reference that must be added which provides for the meaty part of the API involved in 3D geometry access and manipulation:




Faces and Edges can be accessed for the entire model using the workflow below:


Dim seApp As SolidEdgeFramework.Application = GetActiveObject("SolidEdge.Application")
Dim seDoc As SolidEdgePart.PartDocument = seApp.ActiveDocument
Dim seModel As Model = seDoc.Models(0)
Dim seBody As Body = seModel.Body
Dim seFaces As Faces = seBody.Faces(FeatureTopologyQueryTypeConstants.igQueryAll)
Dim seEdges As Edges = seBody.Edges(FeatureTopologyQueryTypeConstants.igQueryAll)


The FeatureTopologyQueryTypeConstants come from the SolidEdgeGeometry reference.

The other possible filters are:




You can either query all faces or edges using igQueryAll and then check each one using its Geometry property in a loop as below:


Dim seFace As Face
For i As Integer = 0 To seFaces.Count - 1
seFace = seFaces.Item(i)
  If TypeOf (seFace.Geometry) Is SolidEdgeGeometry.Plane Then
  End If


Similarly, to check edges you use the Geometry property as shown next.

02_TipIcon.png Note how the geometry is compared with Line and not with Line2D from the SolidEdgeFrameworkSupport library. These two are entirely different species.


For Each seEdge As Edge In seEdges
  If TypeOf seEdge.Geometry Is Line Then
  End If


Where the GetEdgeLength function looks like:


Public Function GetEdgeLength(ByVal seEdge As Edge) As Double
  Dim StartVertex As Vertex = seEdge.StartVertex()
  Dim EndVertex As Vertex = seEdge.EndVertex
  Dim StartVertexCoordinates(2) As Double
  Dim EndVertexCoordinates(2) As Double
  Dim StartX As Double = StartVertexCoordinates(0)
  Dim StartY As Double = StartVertexCoordinates(1)
  Dim StartZ As Double = StartVertexCoordinates(2)
  Dim EndX As Double = EndVertexCoordinates(0)
  Dim EndY As Double = EndVertexCoordinates(1)
  Dim EndZ As Double = EndVertexCoordinates(2)
  Dim EdgeLength As Double
  EdgeLength = Math.Sqrt((StartX - EndX) ^ 2 + (StartX - EndY) ^ 2 + (StartXZ - EndZ) ^ 2)
  Return EdgeLength
End Function

Another shorter method of getting the length of an edge is using the GetLengthAtParam function:


Dim seEdges As Edges = seBody.Edges(FeatureTopologyQueryTypeConstants.igQueryAll)
Dim EdgeLength As Double, MinParam As Double, MaxParam As Double

For Each seEdge As Edge In seEdges If TypeOf seEdge.Geometry Is Line Then
seEdge.GetParamExtents(MinParam, MaxParam)
seEdge.GetLengthAtParam(MinParam, MaxParam, EdgeLength) Debug.WriteLine(EdgeLength) End If Next


In the function for getting the edge length you also get a quick introduction to the Vertex object. The function also shows there are direct functions to get the start and end vertex of an edge.

All vertices of the body can be accessed simply using with no additional parameters:


Dim seVertices As Vertices = seBody.Vertices()


Similarly, vertices for one specific face can be extracted using:


seFace = seFaces.Item(0)
seVertices = seFace.Vertices


Further, there are faces attached to an edge which can be obtained as below:


Dim seFaceArray() As Object = { }
Dim FaceCount As Integer
Dim seEdge As Edge = seEdges.Item(0)

seEdge.GetFaces(FaceCount, seFaceArray)


When you debug the above lines of code, note that the number of faces associated with an edge are always 2 so FaceCount will be 2



Finally there are edges and faces attached to a vertex which can be obtained as below:


Dim seVertex As Vertex = seVertices.Item(0)

seEdges = seVertex.Edges()
seFaces = seVertex.Faces


This shows that the Geometry objects like Faces, Edges and Vertices do not have a hierarchical structure like the other objects in the Solid Edge object model.


In the next part of this article learn about:


  1. What are Edge and Face IDs.
  2. How to reliably extract a face from its ID when the face is modified.
  3. Extracting Edges and faces of features.
  4. Special faces and edges of features.
  5. Highlighting edges, faces and vertices.
  6. How to use the TopoTools free tool to identify and highlight faces, edges and vertices.


Solution Partner Phenom

Tushar wrote:


My general understanding of the FromParam and To Param is they range between 0 to 1 over the length of the edge, but I could stand corrected in case the implied meaning in Solid Edge is different. This because the API sample for the GetLengthAtParam method uses a range of 0 to PI/2


You cannot assume that the parameter range of an edge is between 0 and 1. I would say, it rarely is!!

To get the length of an edge, you should always retrieve the parameter range first and then get the length between both.



For enhancing the understanding as usual, thanks a lot !!

The article is now updated with the new information.


So I continue to traverse the learning path while sharing whatever I know Robot Happy



Tushar, I have worked with a faces and other low level elements, also we dod a log of work with the Extruded Protrusion and ExtrudedCutOut interfaces. We have recently been attempting add support for the Hole interface. If one looks at the type library, we would expect the techniques we use for accessing the Hole interface would be similar to how we access Extruded Protrusion and ExtrudedCutOut interfaces, but even though our code complies, we geterors on execution. We use Delphi, but could yyou refer me to VB or C# examples that access the Hole interface (we are currently still useing Ordered Geometry)


Hello @DesktopEda

Both extruded features and holes provide direct access to their faces and edges.

Additionally they also provide special face/edge sets like end caps, side faces for direct usage.

I will be covering these in the next part of the same topic.


What is your specific query about hole interfaces ?



Our Solid Edge add-in allows users to model printed circuit boards in Solid Edge.

Currently we model drilled holes in a circuit board using ExtrudedCutouts.

Many of our users would like to be able to use the Solid Edge Hole feature instead of ExtrudedCutouts when the model holes in a circuit board.

We are attempting to update our add-in to support the option to allow the user to model holes with either ExtrudedCutouts or the Hole feature.

Our problem is we cannot access the Solid Edge Hole interface. We have applied the same approach we use for ExtrudedCutouts - we can access both the Hole features and ExtrudedCutouts via Model.Features, but when we try to access the Hole feature by typecasting it to a Hole interface, it fails. ( See the Delphi example code below).

When we encounter issues like this, we can usually resolve them if we have an example VB or C# - could you pint me to an example.

The Solid Edge API has an example but it only returns the name of the Hole feature (which we aslo can do) , but we cannot return any other method of the Hole interface.

here is a procedure I have been using to test this problem (this is Delphi - but we use the same methods os VB or C# )

{ .............................................................................. }

procedure GetHoleFeatures(aPartDoc: PartDocument; var List: TInterfaceList);
i, Count: integer;
oModel: Model;
oHole: Hole;
oExtrudedProtrusion: ExtrudedProtrusion;
oExtrudedCutOut: ExtrudedCutOut;
HoleDisp, FeatureDisp: olevariant;
tmpHole: IUnknown;
if aPartDoc.Models.Count = 0 then

oModel := aPartDoc.Models.Item(1);
if oModel <> nil then
Count := oModel.Features.Count; // use Count variable so we can see count value with debug

for i := 1 to Count do
if supports(IDispatch(oModel.Features.Item(i)), IUnknown, tmpHole) then
if supports(tmpHole, ExtrudedProtrusion, oExtrudedProtrusion) then
List.Add(oExtrudedProtrusion) // ExtrudedProtrusion gets added
else if supports(tmpHole, Hole, oHole) then
List.Add(oHole); //never get here

for i := 1 to Count do
FeatureDisp := oModel.Features.Item(i);
Showmessage(FeatureDisp.Name); // this displays hole name correctly as well as all other features

oModel := aPartDoc.Models.Item(1);
if oModel <> nil then
Count := oModel.Features.Count;

for i := 1 to Count do
if supports(IDispatch(oModel.Features.Item(i)), ExtrudedProtrusion, oExtrudedProtrusion) then
List.Add(oExtrudedProtrusion) // this gets populated when there is an Extruded Protrusion
else if supports(IDispatch(oModel.Features.Item(i)), ExtrudedCutOut, oExtrudedCutOut) then
List.Add(oExtrudedCutOut) // this gets populated when there is an Extruded Cutout
else if supports(IDispatch(oModel.Features.Item(i)), Hole, oHole) then
List.Add(oHole) // this never gets populated
on e: exception do


for i := 0 to List.Count - 1 do
if supports(List.Items[i], ExtrudedProtrusion, oExtrudedProtrusion) then
Showmessage(oExtrudedProtrusion.Name) // displays name
else if supports(List.Items[i], ExtrudedCutOut, oExtrudedCutOut) then
Showmessage(oExtrudedCutOut.Name) // displays name
else if supports(List.Items[i], Hole, oHole) then
Showmessage(oHole.Name) // nver get here

Showmessage('# Holes : ' + inttostr(oModel.Holes.Count)); // diplays # Holes : 0


{ .............................................................................. }



Brian Watson
Desktop EDA
ph +61 3 9008 6124
Skype DesktopEDA
Message protected by MailGuard: e-mail anti-virus, anti-spam and content filtering.



I don't think it is possible to cast a ExtrudedCutout to a Hole type.


Solid Edge provides a Holes feature collection which can be accessed directly from the model:


Dim seApp As SolidEdgeFramework.Application = System.Runtime.InteropServices.Marshal.GetActiveObject("SolidEdge.Application")
Dim seDoc As SolidEdgePart.PartDocument = seApp.ActiveDocument

Dim seModel As Model = seDoc.Models.Item(1)
Dim seHoles As SolidEdgePart.Holes = seModel.Holes

Dim ListOfHoles As List(Of Hole) = New List(Of Hole)
For Each seHole As Hole In seHoles


The above VB code loops through the Holes feature collection and displays the name of each hole and adds them to a List.

It then displays the number of holes found in the model.


Alternatively, if you still want to check with each feature in the model.


Dim seFeatures As SolidEdgePart.Features = seModel.Features

For Each seFeature As Object In seFeatures
	If TypeOf (seFeature) Is SolidEdgePart.Hole Then
		MessageBox.Show("Hole, " + "Name = " + seFeature.Name)
	ElseIf TypeOf (seFeature) Is SolidEdgePart.ExtrudedCutout Then
		MessageBox.Show("Cutout, " + "Name = " + seFeature.Name)
	End If

I'd suggest posting queries in the Solid Edge Developer Forum.





Top Kudoed Posts