What is a easiest way to find object placed inside wall?
My current idea is iterate over all object and check boundaries intersection
does it any other ways?
I get door, window and openings in a wall by looping through a selection set of each, checking to see if the curveID of the door/window/opening anchor equals the wallobject ID. Below is some sample code I use to get windows anchored to the wall object objWall.
Chris
''Windows CreateSS("Aec_Window", objSS) If Not objSS Is Nothing Then For i As Integer = 0 To objSS.Count - 1 objWindow = tr.GetObject(objSS(i).ObjectId, OpenMode.ForRead) If objWindow.IsAnchored = True Then Dim myAnchor As AnchorOpeningBaseToWall = tr.GetObject(objWindow.AnchorId, OpenMode.ForRead) If myAnchor.CurveId = objWall.ObjectId Then MsgBox("window is anchored to wall") End If End If Next i End If Public Sub CreateSS(ByVal strObjType As String, ByRef objSS As SelectionSet) Dim ed As Editor = AcApp.Application.DocumentManager.MdiActiveDocument.Editor Dim myTypedValue(0) As TypedValue myTypedValue(0) = New TypedValue(DxfCode.Start, strObjType) '' Assign the filter criteria to a SelectionFilter object Dim myFilter As SelectionFilter = New SelectionFilter(myTypedValue) Dim myPromptSelectionResult As PromptSelectionResult = ed.SelectAll(myFilter) If myPromptSelectionResult.Status = Autodesk.AutoCAD.EditorInput.PromptStatus.OK Then objSS = myPromptSelectionResult.Value End If End Sub
I have a lot of objects with different types, so I cannot use filter by type name method.
Does it possible to filter by region or bounds?
There is a lot of embedding elements, connectors, lifters, electricity, pipes etc.
trying to filter by bounds
private static SelectionSet CreateSelection(Editor ed, Extents3d wallBounds) { TypedValue[] tvs = new TypedValue[] { new TypedValue((int) DxfCode.Operator, ">,>,*"), new TypedValue((int) DxfCode.XCoordinate, wallBounds.MinPoint), new TypedValue((int) DxfCode.Operator, "<,<,*"), new TypedValue((int) DxfCode.XCoordinate, wallBounds.MaxPoint) }; SelectionFilter myFilter = new SelectionFilter(tvs); PromptSelectionResult myPromptSelectionResult = ed.SelectAll(myFilter); if (myPromptSelectionResult.Status == Autodesk.AutoCAD.EditorInput.PromptStatus.OK) return myPromptSelectionResult.Value; return null; }
But myPromptSelectionResult.Status is Error without any details.
does it possible to understand what is exactly wrong?
You're thinking about how to solve the most trivial case. That's not how you approach solving a problem.
The most trivial case in this case, is a wall that is parallel to the x or y axis. All walls are not necessarily parallel to the x or y axis.
You have to obtain the points that define the polygon containing the objects you want to find, then you have to find out if each candidate object lies inside or outside of that polygon regardless of how many points there are, or what shape or orientation the polygon has.
Selection set filtering will not work to solve the problem.
this simplification is ok for me. I can set restrictions/requirements for drawing
To back things up a bit... better definitions will help you start solving the problem.
What is an "object"? A line? Block? Text? Something from one of the vertical products?
What is a "wall"? A set of parallel lines? A multi-line? Something from one of the vertical products?
What constitutes being "inside a wall"?
"Wall" is Aec_Wall
"Objects" - blocks in most cases, dynamic blocks or MultiViewBlocks
Solution is for sandwich panels manufacturer. they draw walls, and literally put objects inside. On production it will be putted inside concrete
@ngogol wrote:"Wall" is Aec_Wall
"Objects" - blocks in most cases, dynamic blocks or MultiViewBlocks
Solution is for sandwich panels manufacturer. they draw walls, and literally put objects inside. On production it will be putted inside concrete
No need to backpedal. Regardless of what constitutes a wall, you have to get its 2D geometric bounds, which is almost always a rectangle.
Once you have that, you have to check for intersection with or containment within the rectangle. If you're checking blocks, then it depends on whether you want to detect if any of the block's geometry intersects the rectangle, or if you only care about the insertion point. The IntersectWith() method, the Explode() method, and a few methods of the Curve class will do the job, but it isn't as trivial as your attempt to use a filtered selection. If everything is visible in the current view, you might try using within polygon (WP at the SelectObjects: prompt), which you can do from .NET using the Editor's SelectCrossingPolygon() or SelectWindowPolygon() methods, but these methods are view-dependent, and not precise, but I don't think you need to be that precise in this case.
If you choose the purely analytical route (going through model space and checking each object against a rectangle that represents the wall's bounds), you can use the bounding boxes of objects to quickly reject those that could not be inside the wall, and then use IntersectWith() on objects that might be inside the wall, and the process should be not much slower than trying to cajole AutoCAD into doing it for you via selection filtering or graphical selection.
You can find an example that is remotely similar to what you're trying to do in this post.
Thanks, I will try.
Another question - After I found objects inside wall, I need normalize coordinates relatively to wall, which can be problematic for non parallel walls/objects.
Does AutoCad API have anything for it? or better use some foreign 3d library ?
@ngogol wrote:Thanks, I will try.
Another question - After I found objects inside wall, I need normalize coordinates relatively to wall, which can be problematic for non parallel walls/objects.
Does AutoCad API have anything for it? or better use some foreign 3d library ?
You can set up a transformation matrix (Matrix3d) to the point on the wall that is to be the origin of the coordinate system, and the x-axis to a point on the same side of the wall, where the other side is in the direction of the positive Y axis. Then you can pass it to the Point3d.TransformBy() method to transform world coordinates to the local coordinate system of the wall. You use the AlignCoordinateSystem() method of Matrix3d to set up the matrix. You can search here for examples of how it's used.
...About IntersectWith()
if suggest that wall is parallelepiped, I need do intersect with all 6 wall faces?
Does Autocad Architecture/MEP not have an interference API? You can run interference checks inside the program so it is probable that there is an API for it.
Actually i still not find yet AEC API reference ...
does it existing at all?
I'm assuming you're using AutoCAD Architectural? Or are you inheriting ACA drawings from another source?
... or, look at the AEC documentation to see if there's an easy button. FYI, custom objects don't always play nice for getting things like geometric extents, wall edges, and so on so it's best to start with native functions.
@ngogol wrote:...About IntersectWith()
if suggest that wall is parallelepiped, I need do intersect with all 6 wall faces?
It depends on if you're doing 3D interference checking or 2D intersection/containment checking.
If it is the former, what is in the blocks that you are checking? Are there 3D objects (solids/surfaces), or are there 2D objects (lines, arcs, polylines, etc.)?
If you want to do 3D intereference checking, you can do that by creating polysolids (which are essentially extrusions of 2D wall plan geometry), and then use the Solid3d'S CheckInterference() method to detect intersections between other 3D objects (but not with 2D objects).
IntersectWith() is a 2D-only operation. It only detects intersections between 2D objects (mainly Curves). The rough equivalent for 3D objects is the Solid3d's CheckInterference() method, which will vastly simplify the problem if all the objects involved are 3D objects, or can be easily converted into 3D objects.
So, it depends on whether you're dealing with 3D or 2D information.