Well, I can assure you that the code is not called through a 'reactor' or 'event' call back. There is no 'automatic' response process happening here. The user has to type in a command to activate this code.
The calling code:
<CommandMethod("FillOutClearanceDimsTable")> _
Public Shared Sub FillOutClearanceDimsTable()
Try
Dim doc As Document = AApplication.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Using lock As DocumentLock = doc.LockDocument
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
Dim btrSpace As BlockTableRecord = trans.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite)
Dim dimensions As New List(Of Autodesk.AutoCAD.DatabaseServices.RotatedDimension)
Dim psr As Autodesk.AutoCAD.EditorInput.PromptSelectionResult
Dim pso As New Autodesk.AutoCAD.EditorInput.PromptSelectionOptions
pso.MessageForAdding = "Select all vertical and horizontal clearance dimensions"
pso.MessageForRemoval = "Remove dimensions"
pso.AllowDuplicates = False
pso.SingleOnly = False
psr = doc.Editor.GetSelection(pso)
If psr.Status = Autodesk.AutoCAD.EditorInput.PromptStatus.OK Then
For Each so As Autodesk.AutoCAD.EditorInput.SelectedObject In psr.Value
Dim ent As Entity = trans.GetObject(so.ObjectId, OpenMode.ForRead)
If TypeOf ent Is Autodesk.AutoCAD.DatabaseServices.RotatedDimension Then
dimensions.Add(ent)
End If
Next
ClearanceDrawings.ProcessDimensions(dimensions, trans, btrSpace, doc)
End If
trans.Commit()
End Using
End Using
Catch ex As System.Exception
MsgBox(ex.ToString)
End Try
End Sub The Process Dimensions Code:
Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.Windows Imports Microsoft.Win32 Imports System.Reflection Imports System.Drawing Imports AApplication = Autodesk.AutoCAD.ApplicationServices.Application Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.DatabaseServices.Filters Module ClearanceDrawings Dim dTable As Autodesk.AutoCAD.DatabaseServices.Table Public Sub ProcessDimensions(ByRef dims As List(Of Autodesk.AutoCAD.DatabaseServices.RotatedDimension), ByRef mTrans As Transaction, ByRef btrSpace As BlockTableRecord, ByRef mDoc As Document) 'separate dimensions by horizontal and vertical, and sort by measurement Dim doc As Document = mDoc Using trans As Transaction = mTrans.TransactionManager.StartTransaction Dim vertDims As New SortedDictionary(Of Double, Autodesk.AutoCAD.DatabaseServices.RotatedDimension) Dim horizontalDims As New SortedDictionary(Of Double, Autodesk.AutoCAD.DatabaseServices.RotatedDimension) For Each rDim As RotatedDimension In dims Select Case Math.Round(rDim.Rotation, 6) Case 0 If Not horizontalDims.ContainsKey(rDim.Measurement) Then horizontalDims.Add(rDim.Measurement, rDim) End If Case CommonTools.DegreesToRadians(90) If Not vertDims.ContainsKey(rDim.Measurement) Then vertDims.Add(rDim.Measurement, rDim) End If Case CommonTools.DegreesToRadians(180) If Not horizontalDims.ContainsKey(rDim.Measurement) Then horizontalDims.Add(rDim.Measurement, rDim) End If Case CommonTools.DegreesToRadians(270) If Not vertDims.ContainsKey(rDim.Measurement) Then vertDims.Add(rDim.Measurement, rDim) End If End Select Next 'now we have sorted lists of vertical dims and horizontal dims 'Start a new table dTable = Nothing Dim psr As Autodesk.AutoCAD.EditorInput.PromptSelectionResult Dim pso As New Autodesk.AutoCAD.EditorInput.PromptSelectionOptions pso.MessageForAdding = "Select the clearance dimensions table" pso.MessageForRemoval = "Remove dimensions" pso.AllowDuplicates = False pso.SingleOnly = True psr = doc.Editor.GetSelection(pso) If psr.Status = Autodesk.AutoCAD.EditorInput.PromptStatus.OK Then For Each so As Autodesk.AutoCAD.EditorInput.SelectedObject In psr.Value Dim ent As Entity = trans.GetObject(so.ObjectId, OpenMode.ForRead) If TypeOf ent Is Autodesk.AutoCAD.DatabaseServices.Table Then dTable = ent Exit For End If Next End If If dTable IsNot Nothing Then dTable = trans.GetObject(dTable.Id, OpenMode.ForWrite) If dTable.Rows.Count < (vertDims.Count + 2) Then Dim lastRow As Integer = dTable.Rows.Count - 1 Dim rowHeight As Double = dTable.Rows(lastRow).Height Dim rowCount As Integer = (vertDims.Count + 2) - dTable.Rows.Count dTable.InsertRows(lastRow, rowHeight, rowCount) 'dTable.RecomputeTableBlock(True) End If Dim rowNum As Integer = 1 Dim hMax As Double = 0 Dim roundUp As Boolean = False Dim strZero As String = "%<\AcExpr (0) \f " & Chr(34) & "%lu4%pr0" & Chr(34) & ">%" '"0'-0" & Chr(34) 'Dim strDBDims As String = String.Empty 'in here we will store a replica of the dimensions to be pushed into the TTS Main database. 'strDBDims was disabled because we always modify the dimensions after creating this table. For Each vDim As RotatedDimension In vertDims.Values Dim dbHDim As Double = 0 rowNum += 1 Dim vCell As Cell = dTable.Cells.Item(rowNum, 0) Dim strVField As String = "%<\AcObjProp Object(%<\_ObjId " strVField += Replace(Replace(vDim.ObjectId.ToString, ")", ""), "(", "") strVField += ">%).Measurement \f " & Chr(34) & "%lu4%pr4" & Chr(34) & ">%" SetCellValue(vCell, strVField) 'now find the horizontal dimension that exactly corresponds to the vertical dimension Dim vDimPoint As Autodesk.AutoCAD.Geometry.Point3d = Nothing If vDim.XLine1Point.Y - vDim.XLine2Point.Y > 0 Then vDimPoint = vDim.XLine1Point Else vDimPoint = vDim.XLine2Point End If Dim booFound As Boolean = False Dim hCell As Cell = dTable.Cells.Item(rowNum, 1) Dim horDim As RotatedDimension = Nothing For Each hDim As RotatedDimension In horizontalDims.Values 'first look for coincident points If vDimPoint.DistanceTo(hDim.XLine1Point) < 0.0000001 Then booFound = True End If If vDimPoint.DistanceTo(hDim.XLine2Point) < 0.0000001 Then booFound = True End If 'if boofound = false then look for point that share the same x value If Math.Abs(vDimPoint.X - hDim.XLine1Point.X) < 0.0000001 Then booFound = True End If If Math.Abs(vDimPoint.X - hDim.XLine2Point.X) < 0.0000001 Then booFound = True End If If booFound Then horDim = hDim If hDim.Measurement >= hMax Then hMax = hDim.Measurement Else roundUp = True End If Dim strHField As String = "%<\AcObjProp Object(%<\_ObjId " strHField += Replace(Replace(hDim.ObjectId.ToString, ")", ""), "(", "") strHField += ">%).Measurement \f " & Chr(34) & "%lu4%pr4" & Chr(34) & ">%" SetCellValue(hCell, strHField) dbHDim = Math.Round(hDim.Measurement, 8) Exit For End If Next If booFound = False Then SetCellValue(hCell, strZero) End If 'now set the rounded values vCell = dTable.Cells.Item(rowNum, 2) Dim strRDown As String = "%<\AcExpr (A" & (rowNum + 1).ToString & "-.49" & Chr(34) & ") \f " & Chr(34) & "%lu4%pr0" & Chr(34) & ">%" Dim strRUp As String = "%<\AcExpr (A" & (rowNum + 1).ToString & "+.49" & Chr(34) & ") \f " & Chr(34) & "%lu4%pr0" & Chr(34) & ">%" If roundUp Then SetCellValue(vCell, strRUp) 'strDBDims += "V" & (rowNum - 1) & ":" & CStr(CInt(Math.Round((vDim.Measurement + 0.49999999), 0))) & ";" Else SetCellValue(vCell, strRDown) 'strDBDims += "V" & (rowNum - 1) & ":" & CStr(CInt(Math.Round((vDim.Measurement - 0.49999999), 0))) & ";" End If hCell = dTable.Cells.Item(rowNum, 3) strRUp = "%<\AcExpr (B" & (rowNum + 1).ToString & "+.49" & Chr(34) & ") \f " & Chr(34) & "%lu4%pr0" & Chr(34) & ">%" SetCellValue(hCell, strRUp) 'strDBDims += "H" & (rowNum - 1) & ":" & CStr(CInt(Math.Round((dbHDim + 0.49999999), 0))) & ";" Next 'strDBDims = strDBDims.TrimEnd(";") 'UploadDimensionsToDatabase(strDBDims) trans.Commit() End If End Using End Sub End Module
The cell value code:
Public Sub SetCellValue(ByRef cell As Autodesk.AutoCAD.DatabaseServices.Cell, ByRef value As String)
If cell IsNot Nothing Then
If cell.FieldId <> ObjectId.Null Then
Dim field As Field = cell.FieldId.GetObject(OpenMode.ForWrite)
Dim code As String = field.GetFieldCode()
field.SetFieldCode(value)
Else
cell.TextString = value
End If
End If
End Sub
Public Function GetCellValue(ByRef cell As Autodesk.AutoCAD.DatabaseServices.Cell) As String
Dim strValue As String = Nothing
If cell IsNot Nothing Then
If cell.FieldId <> ObjectId.Null Then
Dim field As Field = cell.FieldId.GetObject(OpenMode.ForWrite)
strValue = field.GetStringValue
Else
strValue = cell.TextString
End If
End If
Return strValue
End Function That is the entire basic process.
- Create a drawing in modelspace to world scale
- create viewport in paperspace to some scale (anyscale will do)
- draw associative dimensions (7 vertical 7 horizontal -any number will do, but 7 is average for us) in paperspace to the linework in modelspace over the viewport
- stack your vertical dimensions in baseline style from bottom up
- make sure that each vertical dimension has one node (the highest node of the dimension) in common with a node of a horizontal dimension vertically (with no tolerance). (xVertDim - xHorizDim = 0)
- (Dimassoc = 2, dimscale=1)
- create a 4 column table with 1 title row, 1 header row, and 20 data rows
- Fill the table with 0's
- Run the routine and follow the prompts.
- Notice the table took down 3 more cells than called for.
- To reproduce the error (happens many times but not all) remove or add a row from the table and rerun routine.
jvj