Code Red => VB(A) => Topic started by: GILESP on January 11, 2017, 07:36:45 am
I'm working on a project which among other things has to determine the visibility properties of an entity within a block definition.
The task is to determine the maximum drawing extents of a block reference within modelspace, however blocks with multiple visibility states are currently showing up with greater extents due to my code not taking into account the currently selected visibility state.
what I'd like to do is pass a visibility state name to the function, and have it compare each entity it encounters with the state name, and if the entity is not visible in that state, ignore it.
This way I can pass a block name, and visibility state to the function, and it will return the maximum extents of the block in that visibility mode only.
Code fragment below of the function that calculates maximum extents,
the block argument is the block definition in the blockstable used to define the reference being processed.
SubjectDwg is a cheat that allows this script/routine to be processed as part of a batch.
the optional 'view' argument is the visibility state name of the current block reference being processed:
Has anyone got any idea how I can get the conditional statement in the code to recognize the visibility parameter of an entity?
Function GetExtents(Block As AcadBlock, SubjectDwg As AcadDocument, Optional View As String) As Double()
Dim Obj As AcadEntity
Dim MinExt(0 To 1) As Variant 'minimum bounding extents of block
Dim MaxExt(0 To 1) As Variant 'maximum bounding extents of block
Dim ObjMinExt As Variant
Dim ObjMaxExt As Variant
Dim TempArray() As Double
ReDim TempArray(0 To 3)
For Each Obj In Block
Select Case Obj.EntityName
TempArray = GetExtents(SubjectDwg.Blocks.Item(Obj.Name), SubjectDwg)
Case "AcDbPolyline", "AcDbLine", "AcDbArc", "AcDbCircle"
If UCase(Obj.Layer) Like "CENTRELINES" Or UCase(Obj.Layer) Like "*-C" Or UCase(Obj.Layer) Like "*-CLEAR" Then
ElseIf obj.visilitystate <> View then ######################### <= this conditional statement needs to work!
Obj.GetBoundingBox ObjMinExt, ObjMaxExt
If ObjMaxExt(0) > MaxExt(0) Then
MaxExt(0) = ObjMaxExt(0)
If ObjMaxExt(1) > MaxExt(1) Then
MaxExt(1) = ObjMaxExt(1)
If MinExt(0) > ObjMinExt(0) Then
MinExt(0) = ObjMinExt(0)
If MinExt(1) > ObjMinExt(1) Then
MinExt(1) = ObjMinExt(1)
TempArray(0) = MinExt(0)
TempArray(1) = MinExt(1)
TempArray(2) = MaxExt(0)
TempArray(3) = MaxExt(1)
GetExtents = TempArray()
I am not sure I fully understand your question, but it seems to me that your code is logically wrong (if the AcadBlock argument in the function is not ModelSpace or PaperSpace):
1. The extents of a block definition is not necessarily the same as Block reference. For example, the block definition could have a few attribute definition with very short tag string, while the corresponding attribute reference could have very long value string, or even the block reference could have attribute reference that does not have matching attribute definition, or no attribute reference at all. This would be very likely make the extents of block reference different from the block definition. Also, you need to take it into account that the block reference could be scaled/rotated, which also result in different extents from the block definition's.
2. There is no API available to access dynamic design in block definition, so your code comment "<= this conditional statement needs to work!" is not doable.
If your goal is to know all possible extents of a dynamic BLOCK REFERENCE, it is rather simple:
1. Get a dynamic property name list available in the block reference (keep in mind, other dynamic properties rather than Visibility could also result in different extents);
2. loop through the property one by one and set it and get the extents of the block reference.
Of course, if combination of more than one dynamic properties could lead to different extents, then things are quite complicated and it would up to you to find out.
In the simple case (assume you only have one property/Visibility with a list of values), you can then do this (pseudo code):
Dim originalVal as Object
Dim propVals() As Object
Dim i as Integer
Dim j As Integer
Dim prop As AcadDynamicBlockReferenceProperty
Dim props As Variant
//Get the list of values of the property/Visibility
For i=0 To Ubound(props)
If prop.PropertyName=[The target property] Then
For j=0 To Ubound(prop.AllowedValues)
Redim Preserve propVals(j)
//Loop through the priperty/visibility states
Dim state as object
For i=0 to Ubound(propVals)
'' Get the block reference's property/visibility to the value
'' Get block reference's extents in this state
The intention is to find the extents of the block for the currently visible state - in this case the visibility states refer to front, top, bottom and side elevations of a panel mounted control or connector, but I only need to know the extents of the front elevation for panel layout purposes.
I understand your argument with regard to the attributes - however in this instance attributes are irrelevant, though I didn't state that in the original question. Scaling shouldn't be applied in the intended usage, and rotation is allowed for in another part of the code.
The code as it's currently written (i.e. without my commented line) will already return all possible extents as it ignores visibility parameters, but due to the dynamic nature of the blocks, it is throwing up false values as it's getting the extents of a view/orientation that isn't needed.
Your point no2 is a disappointment, as it means a pretty major rethink of this project, perhaps to find a way of interrogating the block reference rather than the definition -or by using the anonymous blocks that Autocad creates to represent dynamic block references..?
back to the drawing board I think.. :(