Hi!
I have a DGN file with many elements (lines, linestrings, shapes, sharedcells, etc.).
I make a fence from an shape element. I have these elements in the array in the program and they are drawn in the model.
If I use a tool for fence, then everything works fine.
Then I wrote a small macro to do this automatically. But the result of his work is different.
For i = LBound(Segments) To UBound(Segments) Dim oFence As Fence Dim oFenceContents As ElementEnumerator ActiveSettings.FenceVoid = False ActiveSettings.FenceOverlap = False ActiveSettings.FenceClip = True Set oFence = ActiveModelReference.Attachments(Index).DesignFile.Fence ' This attached file has elements for clip oFence.DefineFromModelPoints TopView, Segments(i).Points ' This shape's vertices Set oFenceContents = oFence.GetContents While oFenceContents.MoveNext Dim curEle As Element Set curEle = oFenceContents.Current.Clone ' if without clone - error "Invalid cell" curEle.Color = 3 curEle.LineWeight = 1 ActiveModelReference.AddElement curEle Set curEle.Level = ActiveModelReference.Levels.FindByNumber(0) Wend Next i
What could be the problem?
Unknown said:What could be the problem?
It's hard to say without some evidence: screenshots are good, DGN files are better. Post the DGN file with the model where the clipping is not what you expect.
What is variable Segments?
Segments
Regards, Jon Summers LA Solutions
Segments - it's array of my structure for programm.
Segments(i).Points - These are the vertices of the shape.
DGN File: https://yadi.sk/d/bw2QMLZ03LcDEi
In the Fences layer (50) there are shapes for work.
But once again I will say: the manual tool works well.
For a simple test, I wrote a small procedure.
It creates a fence from the selected shape-element. The View is set to View number 1 (Top).
Sub TestFence() Dim fenceEnum As ElementEnumerator Set fenceEnum = ActiveModelReference.GetSelectedElements While fenceEnum.MoveNext Dim oFence As Fence Dim oFenceContents As ElementEnumerator ActiveSettings.FenceVoid = False ActiveSettings.FenceOverlap = False ActiveSettings.FenceClip = True Set oFence = ActiveDesignFile.Fence oFence.DefineFromElement ActiveDesignFile.Views(1), fenceEnum.Current Set oFenceContents = oFence.GetContents While oFenceContents.MoveNext Dim curEle As Element Set curEle = oFenceContents.Current.Clone curEle.Color = 3 curEle.LineWeight = 1 ActiveModelReference.AddElement curEle Wend Wend End Sub
Unknown said:For a simple test, I wrote a small procedure
That code is different to the first example you posted. Does that second example fail in the same way?
The only difference is that the new code does not need data that the entire program calculates. In the attached file, the fences are exactly those that the program creates. The connected file is also not used, because I gave the source file myself.The result using this procedure is similar - there are errors in the form of missing parts of the elements.
The example DGN has a reference For fence.dgn. You haven't supplied that so I can't tell what's in it.
For fence.dgn
You can't clip anything in a reference attachment.
I can make MicroStation's manual fence tools misbehave (in V8i SS3). See the screenshot below. I created a fence from your red shape on level Fence, then did element move using the fence. The move correctly worked on elements within the fence, but look at your neighbouring green shape also on level Fence: it's been cut by the fence move operation even though it lies outside the fence.
So something is wrong, before you even start using VBA!
Hi Maxim,
I see two problems there:
This code seems to work, but I had not enough time for any more extensive testing:
Option Explicit Public Sub ProcessFence() Dim fenceElement As ClosedElement Set fenceElement = ActiveModelReference.GetElementByID(DLongFromLong(879920)) CadInputQueue.SendKeyin "view top;selview 1" Dim viewWithFence As View Set viewWithFence = ActiveDesignFile.Views(1) Dim fnc As Fence ActiveDesignFile.Fence.DefineFromElement viewWithFence, fenceElement ActiveSettings.FenceVoid = False ActiveSettings.FenceClip = True Dim ee As ElementEnumerator Set ee = ActiveDesignFile.Fence.GetContents(True, True) Dim targetLevel As Level Set targetLevel = ActiveDesignFile.Levels("elems from fence") Do While ee.MoveNext ee.Current.Level = targetLevel ActiveModelReference.AddElement ee.Current Loop ActiveDesignFile.Fence.Undefine End Sub
For a simplicity I created a new level "elems from fence" and to move all processed elements from fence to this level, so the rest of file is not changed. A content of this level looks correctly and as expected. But as I wrote, no detail evaluation was done.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Hi Jan,
Thanks for your code! I was looking for it.
But I would like to "redecorate" it in 6th line - so I don't want to indicate fenceElement by ID but by Level <name> AND msdElementType ellipse.
And stops at error
Option Explicit Public Sub ProcessFence() Dim fenceElement As ClosedElement Dim oScanCriteria As ElementScanCriteria Set oScanCriteria = New ElementScanCriteria Dim oLevel As Level Set oLevel = ActiveDesignFile.Levels("elem") oScanCriteria.ExcludeAllLevels oScanCriteria.IncludeLevel oLevel Dim oScanEnumerator As ElementEnumerator Set oScanEnumerator = ActiveModelReference.Scan(oScanCriteria) Set fenceElement = ActiveModelReference.Scan(oScanCriteria) CadInputQueue.SendKeyin "view top;selview 1" Dim viewWithFence As View Set viewWithFence = ActiveDesignFile.Views(1) Dim fnc As Fence ActiveDesignFile.Fence.DefineFromElement viewWithFence, fenceElement ActiveSettings.FenceVoid = False ActiveSettings.FenceClip = True Dim ee As ElementEnumerator Set ee = ActiveDesignFile.Fence.GetContents(True, True) Dim targetLevel As Level Set targetLevel = ActiveDesignFile.Levels("elems from fence") Do While ee.MoveNext ee.Current.Level = targetLevel ActiveModelReference.AddElement ee.Current Loop ActiveDesignFile.Fence.Undefine End Sub
Could I ask you for some advice?
Regards
Paweł
Paweł Szabłowski said:I would like to "redecorate" it in 6th line
It's not clear what you mean. Line 6 is empty.
Paweł Szabłowski said:I want to indicate fenceElement by Level <name> AND msdElementType ellipse
Something like this?
Dim oScanCriteria As ElementScanCriteria Set oScanCriteria = New ElementScanCriteria SetScanCriteriaForLevelAndElemType oScanCriteria, "my level", msdElementTypeEllipse Set oScanEnumerator = ActiveModelReference.Scan(oScanCriteria)
Subroutine SetScanCriteriaForLevelAndElemType is a small procedure having a single purpose — to set up your scan criteria
SetScanCriteriaForLevelAndElemType
Sub SetScanCriteriaForLevelAndElemType ( _ ByVal oCriteria As ElementScanCriteria, _ ByVal levelName As String, _ ByVal elemType As MsdElementType) With oCriteria ' Set level Dim oLevel As Level Set oLevel = ActiveDesignFile.Levels(levelName) .ExcludeAllLevels .IncludeLevel oLevel ' Set element type .ExcludeAllTypes .IncludeType elemType End With End Sub
Hi Jon,
6th line of Jan's code not mine
Thank you for your reply.
So I implemented your remarks and code looks like this:
Option Explicit Public Sub ProcessFence() Dim fenceElement As ClosedElement Dim oScanCriteria As ElementScanCriteria Dim oScanEnumerator As ElementEnumerator Set oScanCriteria = New ElementScanCriteria SetScanCriteriaForLevelAndElemType oScanCriteria, "elem", msdElementTypeEllipse Set oScanEnumerator = ActiveModelReference.Scan(oScanCriteria) Set fenceElement = ActiveModelReference.Scan(oScanCriteria) CadInputQueue.SendKeyin "view top;selview 1" Dim viewWithFence As View Set viewWithFence = ActiveDesignFile.Views(1) Dim fnc As Fence ActiveDesignFile.Fence.DefineFromElement viewWithFence, fenceElement ActiveSettings.FenceVoid = False ActiveSettings.FenceClip = True Dim ee As ElementEnumerator Set ee = ActiveDesignFile.Fence.GetContents(True, True) Dim targetLevel As Level Set targetLevel = ActiveDesignFile.Levels("elems from fence") Do While ee.MoveNext ee.Current.Level = targetLevel ActiveModelReference.AddElement ee.Current Loop ActiveDesignFile.Fence.Undefine End Sub Sub SetScanCriteriaForLevelAndElemType( _ ByVal oCriteria As ElementScanCriteria, _ ByVal levelName As String, _ ByVal elemType As MsdElementType) With oCriteria ' Set level Dim oLevel As Level Set oLevel = ActiveDesignFile.Levels(levelName) .ExcludeAllLevels .IncludeLevel oLevel ' Set element type .ExcludeAllTypes .IncludeType elemType End With End Sub
Now I got problem with line: "Set fenceElement = ActiveModelReference.Scan(oScanCriteria)"
fenceElement is a closedElement not ElementEnumerator
Error 13 mismatch.
Unfortunately, I cannot load help content.
May I ask politely for help ith it?
Regards,
Paweł Szabłowski said:I got problem with line: "Set fenceElement = ActiveModelReference.Scan(oScanCriteria)"
That should be
Set oScanEnumerator = ActiveModelReference.Scan (oScanCriteria)
Paweł Szabłowski said:I cannot load help content
VBA help