.NET

.NET

Reply
Valued Contributor
swaywood
Posts: 91
Registered: ‎08-22-2013
Message 1 of 11 (283 Views)
Accepted Solution

how to find the blockrefercen in a rectangle area which bound by to point?

283 Views, 10 Replies
03-14-2014 08:35 AM

is there any method without looking throgh all the blockrenferences?

Mentor
mzakiralam
Posts: 231
Registered: ‎11-09-2012
Message 2 of 11 (279 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-14-2014 08:43 AM in reply to: swaywood
Can you clear Little bit more regarding your Problem? you can also your Screen shot.
*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 3 of 11 (265 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-14-2014 10:19 AM in reply to: swaywood

Try this code

    <CommandMethod("CSW")> _
        Public Sub TestSelectWindow()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

            Dim db As Database = doc.Database

            Dim ed As Editor = doc.Editor
            '' dummy object types for test:
            Dim objects() As String = New String() {"INSERT", "LINE", "LWPOLYLINE", "CIRCLE"}
            '' dummy layers for test:
            Dim layers() As String = New String() {"DIM", "DWGRU", "ANNO-TLB", "Defpoints"}

            Dim layerfilt As String = String.Join(",", layers)

            Dim objfilt As String = String.Join(",", objects)

            '' Create a TypedValue array to define the filter by object types (dxf code 0) and layers (dxf code 8)
            Dim tvs() As TypedValue = New TypedValue() {New TypedValue(0, objfilt), New TypedValue(8, layerfilt)}

            '' Assign the filter criteria to a SelectionFilter object
            Dim filter As SelectionFilter = New SelectionFilter(tvs)

            Dim ppo As PromptPointOptions = New PromptPointOptions(vbLf & "Specify lower legt corner of window: ")

            Dim pres As PromptPointResult = ed.GetPoint(ppo)

            If pres.Status <> PromptStatus.OK Then Return

            Dim p1 As Point3d = pres.Value

            Dim pco As PromptCornerOptions = New PromptCornerOptions(vbLf & "Opposite corner point: ", p1)

            pres = ed.GetCorner(pco)

            If pres.Status <> PromptStatus.OK Then Return

            Dim p2 As Point3d = pres.Value

            '' Request for objects to be selected in the drawing area
            Dim res As PromptSelectionResult
            res = ed.SelectCrossingWindow(p1, p2, filter)

            '' If the prompt status is OK, objects were selected
            'If res.Status = PromptStatus.OK Then
            Dim sset As SelectionSet = res.Value
            If sset.Count > 0 Then
                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Number of objects selected: " & sset.Count.ToString)
            Else
                Return
            End If
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Try
                    
                    For Each sobj As SelectedObject In sset
                        Dim ent As Entity = DirectCast(tr.GetObject(sobj.ObjectId, OpenMode.ForRead, False), Entity)
                        Dim blk As BlockReference = TryCast(ent, BlockReference)
                        If blk IsNot Nothing Then
                            ed.WriteMessage(vbLf & "Block Name: {0}", blk.Name)
                        End If
                        Dim circ As Circle = TryCast(ent, Circle)
                        If circ IsNot Nothing Then
                            ed.WriteMessage(vbLf & "Radius: {0}", circ.Radius.ToString())
                        End If
                        Dim pline As Polyline = TryCast(ent, Polyline)
                        If pline IsNot Nothing Then
                            ed.WriteMessage(vbLf & "Number Of Vertices: {0}", pline.NumberOfVertices.ToString())
                        End If
                        Dim ln As Line = TryCast(ent, Line)
                        If ln IsNot Nothing Then
                            ed.WriteMessage(vbLf & "Start Point: {0}", ln.StartPoint.ToString())
                        End If

                    Next

                    tr.Commit()
                Catch ex As System.Exception
                    ed.WriteMessage(ex.StackTrace & vbLf & ex.StackTrace)
                End Try
            End Using

        End Sub

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Valued Contributor
swaywood
Posts: 91
Registered: ‎08-22-2013
Message 4 of 11 (238 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-14-2014 11:48 PM in reply to: mzakiralam
hi,mzakiralam,
i lost two letters, 'by to point' shall be 'by two points', sorry for that.
best regards
swaywood
Valued Contributor
swaywood
Posts: 91
Registered: ‎08-22-2013
Message 5 of 11 (238 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-14-2014 11:50 PM in reply to: Hallex
hi, Hallex,
thank you for your reply, your method is correct, but i want to find another method which will use LINQ.
*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 6 of 11 (229 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-15-2014 01:37 AM in reply to: swaywood
Better yet show us you code you're started with,
or upload the image to make a sense
_____________________________________
C6309D9E0751D165D0934D0621DFF27919
*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 7 of 11 (211 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-16-2014 03:47 AM in reply to: swaywood

Hi,

 

I'm not sure to understand what you mean with "using Linq".

 

If you meant using Linq to avoid using a selection set (e.g. using from a side database), her's an example:

 

Query syntax:

        private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db)
        {
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            using (Line line = new Line(pt1, pt2))
            {
                Extents3d bound = line.GeometricExtents;

                BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
                  SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);

                Func<ObjectId, bool> isBlockReference = (id =>
                    id.ObjectClass == RXClass.GetClass(typeof(BlockReference)));

                Func<ObjectId, bool> isInside = (id =>
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                    Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint);
                    exts.AddExtents(br.GeometricExtents);
                    return bound.IsEqualTo(exts);
                }); ;

                var blocks =
                    from ObjectId id in modelSpace
                    where isBlockReference(id) && isInside(id)
                    select id;

                return blocks.ToArray();
            }
        }

 

Extension methods syntax:

        private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db)
        {
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            using (Line line = new Line(pt1, pt2))
            {
                Extents3d bound = line.GeometricExtents;

                BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);

                Func<ObjectId, bool> isBlockReference = (id =>
                    id.ObjectClass == RXClass.GetClass(typeof(BlockReference)));

                Func<ObjectId, bool> isInside = (id =>
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                    Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint);
                    exts.AddExtents(br.GeometricExtents);
                    return bound.IsEqualTo(exts);
                });

                return modelSpace
                    .Cast<ObjectId>()
                    .Where(isBlockReference)
                    .Where(isInside)
                    .ToArray();
            }
        }

 

Gilles Chanteau
Valued Contributor
swaywood
Posts: 91
Registered: ‎08-22-2013
Message 8 of 11 (202 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-16-2014 07:39 AM in reply to: _gile
hi,giles,
that's exactly what i expect, thank you so much.
regards
swaywood
*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 9 of 11 (173 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-17-2014 02:47 AM in reply to: swaywood

Hi swaywood,

 

I'm glad it helps.

 

I also like the functional style available with Linq for the .NET "historic" languages (VB and C#), it is the "natural" way of coding with F#:

 

let findBlocksInRectangle pt1 pt2 (db : Database) =
    use tr = db.TransactionManager.StartOpenCloseTransaction()
    use line = new Line(pt1, pt2)
    let bound = line.GeometricExtents
    let rxc = RXClass.GetClass(typeof<BlockReference>)

    let isBlock (id : ObjectId) =  id.ObjectClass = rxc

    let isInside (id : ObjectId) =
        let br = tr.GetObject(id, OpenMode.ForRead) :?> BlockReference
        let exts = new Extents3d(bound.MinPoint, bound.MaxPoint)
        exts.AddExtents(br.GeometricExtents)
        exts.IsEqualTo(bound) 

    (tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead) 
    :?> BlockTableRecord)
    |> Seq.cast<ObjectId>
    |> Seq.filter isBlock
    |> Seq.filter isInside
    |> Seq.toArray

 

Anyway all these functions do scan the whole model space entities to get all the block references and filter those which are inside the rectangle.

They are all absolutely equivalent to the following one written in a classic imperative style:

 

        private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db)
        {
            return QueryForBlocksInRectangle(pt1, pt2, db).ToArray();
        }

        private IEnumerable<ObjectId> QueryForBlocksInRectangle(Point3d pt1, Point3d pt2, Database db)
        {
            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            using (Line line = new Line(pt1, pt2))
            {
                Extents3d bound = line.GeometricExtents;

                RXClass brClass = RXClass.GetClass(typeof(BlockReference));

                BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);

                foreach (ObjectId id in modelSpace)
                {
                    if (id.ObjectClass == brClass)
                    {
                        BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                        Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint);
                        exts.AddExtents(br.GeometricExtents);
                        if (bound.IsEqualTo(exts))
                        {
                            yield return id;
                        }
                    }
                }
            }
        }

 

 

 

Gilles Chanteau
Valued Contributor
swaywood
Posts: 91
Registered: ‎08-22-2013
Message 10 of 11 (134 Views)

Re: how to find the blockrefercen in a rectangle area which bound by to point?

03-18-2014 01:04 AM in reply to: _gile
Hi,Gilles:
I am not familiar with F#.
I think linq is more efficient to find the result. I will have a try.
Thanks again
swaywood
Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.