I did look into this problem again and found that "Holes" in AecSlabs are defined als Edges. When you look into the Face.Edges collection of the AecSlab, you also find the Edges of the Holes.
I made a function where the user selects the AecSlab and selects a point near a Edge of a Hole in the Slab. The Routine searches the nearest Edge and looks for Edges which connecting with the found Edge.
The routine is for Square Holes only and looks for Lengths which are equal.
The Routine is raw and have to be optimized:
<CommandMethod("SlabHole-Info")> _
Public Sub SlabHoleInfo()
Try
Dim Cmd As New Algemeen
' Connect to Current Drawing
Dim MyDWG As Autodesk.AutoCAD.ApplicationServices.Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim MyDB As Autodesk.AutoCAD.DatabaseServices.Database = MyDWG.Database
Dim MyTransMan As Autodesk.AutoCAD.DatabaseServices.TransactionManager = MyDWG.TransactionManager
Dim Ed As Editor = MyDWG.Editor
Dim SlabID As ObjectId
' Start the Transaction...
Using MyTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = MyTransMan.StartTransaction
' Ask user to select a Wall...
Dim EntSel As PromptEntityResult = Ed.GetEntity(vbLf + "Select Slab to work with.")
If EntSel.Status = PromptStatus.OK Then
' Object selectet, check if it is a slab...
SlabID = EntSel.ObjectId
If SlabID.ObjectClass.DxfName.ToUpper = "AEC_SLAB" Then
' slab selected, ask us to select a point near a edge...
Dim PntSel As PromptPointResult = Ed.GetPoint(vbLf + "Select a point near a Edge of the Hole : ")
If PntSel.Status = PromptStatus.OK Then
'Point selected...
Dim MySlab As ArchDbSrvcs.Slab = MyTrans.GetObject(SlabID, OpenMode.ForRead)
Dim MySlabHoogte As Double = MySlab.Thickness(MySlab.BaseThickness)
Dim ecs2wcs As Matrix3d = MySlab.Ecs
Dim wcs2ecs As Matrix3d = ecs2wcs.Inverse()
' Set the Point the User selected...
Dim Userpt As New Point3d(PntSel.Value.X, PntSel.Value.Y, PntSel.Value.Z)
' Convert point from WCS to ECS of the slab...
Userpt = Userpt.TransformBy(wcs2ecs)
' Search the nearest SlabEdge...
Dim ObjID As Short = MySlab.Face.FindNearestEdge(New Point2d(Userpt.X, Userpt.Y))
Dim MyEdgeFound As Autodesk.Aec.Arch.Geometry.SlabEdge = MySlab.Face.Edge(ObjID)
Userpt = Userpt.TransformBy(ecs2wcs)
' Get the start and endpoint of the edge...
Dim MyEdgeFoundStart As New Point3d(MyEdgeFound.StartPoint.X, MyEdgeFound.StartPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
MyEdgeFoundStart = MyEdgeFoundStart.TransformBy(MySlab.Ecs)
Dim MyEdgeFoundEnd As New Point3d(MyEdgeFound.EndPoint.X, MyEdgeFound.EndPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
MyEdgeFoundEnd = MyEdgeFoundEnd.TransformBy(MySlab.Ecs)
Dim MyEdgeCollection As New Collection
MyEdgeCollection.Add(MyEdgeFound)
' Get the position of the Edge in the Face Collection...
Dim EdgePos As Integer
For i = 0 To MySlab.Face.EdgeCount - 1
Dim MyEdge As Autodesk.Aec.Arch.Geometry.SlabEdge = MySlab.Face.EdgeAt(i)
If MyEdge.Id = MyEdgeFound.Id Then
EdgePos = i
End If
Next
MsgBox("EdgePos is " & EdgePos.ToString & " van " & MySlab.Face.EdgeCount.ToString)
' Search for connecting Edges after the Edge Position...
Dim LastEdgeStart As Point3d = MyEdgeFoundStart
Dim LastEdgeEnd As Point3d = MyEdgeFoundEnd
For i = EdgePos To MySlab.Face.EdgeCount - 1
Dim MyEdge As Autodesk.Aec.Arch.Geometry.SlabEdge = MySlab.Face.EdgeAt(i)
Dim StartPoint As New Point3d(MyEdge.StartPoint.X, MyEdge.StartPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
Dim EndPoint As New Point3d(MyEdge.EndPoint.X, MyEdge.EndPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
StartPoint = StartPoint.TransformBy(MySlab.Ecs)
EndPoint = EndPoint.TransformBy(MySlab.Ecs)
If StartPoint = LastEdgeStart Or StartPoint = LastEdgeEnd Or EndPoint = LastEdgeStart Or EndPoint = LastEdgeEnd Then
Dim EdgeFound As Boolean = False
For Each item As Autodesk.Aec.Arch.Geometry.SlabEdge In MyEdgeCollection
If item.Id = MyEdge.Id Then
EdgeFound = True
End If
Next
If EdgeFound = False Then
MyEdgeCollection.Add(MyEdge)
LastEdgeStart = StartPoint
LastEdgeEnd = EndPoint
End If
End If
Next
' Seach connecting Edges before the Edge Position...
''LastEdgeStart = MyEdgeFoundStart
''LastEdgeEnd = MyEdgeFoundEnd
For i = 0 To EdgePos
Dim MyEdge As Autodesk.Aec.Arch.Geometry.SlabEdge = MySlab.Face.EdgeAt(i)
Dim StartPoint As New Point3d(MyEdge.StartPoint.X, MyEdge.StartPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
Dim EndPoint As New Point3d(MyEdge.EndPoint.X, MyEdge.EndPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
StartPoint = StartPoint.TransformBy(MySlab.Ecs)
EndPoint = EndPoint.TransformBy(MySlab.Ecs)
If StartPoint = LastEdgeStart Or StartPoint = LastEdgeEnd Or EndPoint = LastEdgeStart Or EndPoint = LastEdgeEnd Then
Dim EdgeFound As Boolean = False
For Each item As Autodesk.Aec.Arch.Geometry.SlabEdge In MyEdgeCollection
If item.Id = MyEdge.Id Then
EdgeFound = True
End If
Next
If EdgeFound = False Then
MyEdgeCollection.Add(MyEdge)
LastEdgeStart = StartPoint
LastEdgeEnd = EndPoint
End If
End If
Next
' If the Edgecollection is smaller than the Slab Face.Edgecount then you have a closed Hole...
If MyEdgeCollection.Count < MySlab.Face.EdgeCount Then
'MsgBox("Het is een gesloten sparing met " & MyEdgeCollection.Count & " zijdes")
Dim EdgeLengte, EdgeLengte2 As Integer
Dim HoleSides As New List(Of Integer)
EdgeLengte = CInt(Cmd.DistanceBetween(MyEdgeFoundStart, MyEdgeFoundEnd))
HoleSides.Add(EdgeLengte)
For Each MyEdge As Autodesk.Aec.Arch.Geometry.SlabEdge In MyEdgeCollection
Dim StartPoint As New Point3d(MyEdge.StartPoint.X, MyEdge.StartPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
Dim EndPoint As New Point3d(MyEdge.EndPoint.X, MyEdge.EndPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
Dim count As Integer = 0
EdgeLengte = CInt(Cmd.DistanceBetween(StartPoint, EndPoint))
For Each MyEdge2 As Autodesk.Aec.Arch.Geometry.SlabEdge In MyEdgeCollection
Dim StartPoint2 As New Point3d(MyEdge2.StartPoint.X, MyEdge2.StartPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
Dim EndPoint2 As New Point3d(MyEdge2.EndPoint.X, MyEdge2.EndPoint.Y, (MySlab.Thickness(MySlab.BaseThickness) * -1))
EdgeLengte2 = CInt(Cmd.DistanceBetween(StartPoint2, EndPoint2))
If EdgeLengte = EdgeLengte2 Then
count += 1
End If
Next
If count > 1 Then
' Check of the lengte reeds in de lijst voorkomt...
Dim LgtExist As Boolean = False
For Each Lgt As Integer In HoleSides
If Lgt = EdgeLengte Then
LgtExist = True
End If
Next
' Indien de Lengte niet voorkomt in de lijst, voeg deze toe...
If LgtExist = False Then
HoleSides.Add(EdgeLengte)
End If
End If
Next
MsgBox("Het is een gesloten sparing met " & HoleSides.Count & " zijdes")
Dim MsgStr As String = "Afmetingen : "
For Each item In HoleSides
MsgStr = MsgStr & item.ToString & " x "
Next
MsgStr = Left(MsgStr, Len(MsgStr) - 1)
MsgBox(MsgStr)
Else
MsgBox("Het is geen gesloten sparing")
End If
End If
End If
End If
MyTrans.Commit()
End Using
Catch ex As System.Exception
MsgBox("An Error has occurred." & vbCr & ex.Message)
Finally
End Try
End Sub