Author Topic: Can a hatch be created in .net by clicking a point?  (Read 7581 times)

0 Members and 1 Guest are viewing this topic.

Patch61

  • Guest
Can a hatch be created in .net by clicking a point?
« on: May 03, 2011, 10:50:58 PM »
Can a hatch be created in .net by clicking a point and having AutoCAD find the boundaries (just like selecting 'Pick Point' manually)? All the examples I've seen show a hatch created by passing it a boundary.

Thanks!

kaefer

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #1 on: May 04, 2011, 09:59:45 AM »
Can a hatch be created in .net by clicking a point and having AutoCAD find the boundaries (just like selecting 'Pick Point' manually)?

Yes. Needs at least 18.1, see Autodesk.AutoCAD.EditorInput.Editor.TraceBoundary(Autodesk.AutoCAD.Geometry.Point3d, bool)

Quote
All the examples I've seen show a hatch created by passing it a boundary.

That step is still necessary.

Cheers

Patch61

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #2 on: May 04, 2011, 09:05:28 PM »
Yes. Needs at least 18.1, see Autodesk.AutoCAD.EditorInput.Editor.TraceBoundary(Autodesk.AutoCAD.Geometry.Point3d, bool)


That step is still necessary.

Cheers


Thanks for responding.

Are you saying that the TraceBoundary you mention will return a boundary that I must then pass to the hatch command?

Edit> Just looked at it in Object Browser. It says it returns a DBObjectCollection. I assume that is a collection of the boundary items?
« Last Edit: May 04, 2011, 09:55:40 PM by Patch61 »

kaefer

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #3 on: May 05, 2011, 06:53:58 AM »
Edit> Just looked at it in Object Browser. It says it returns a DBObjectCollection. I assume that is a collection of the boundary items?

Yep. You'd have to cast them to Entity for being able to add them to a BlockTableRecord and subsequently append them as hatch loops. Indeed, I think they wll be invariably of type Polyline.

Now here's a complete C# sample showing the basic functionality of the BHATCH command with option Keep Boundaries activated. Just to be on the safe side, I'm trying to cast the objects to Curve.

Code: [Select]
        [CommandMethod("CHFP")]
        static public void CreateHatchFromPointCommand(){

            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
 
            PromptPointResult ppr = ed.GetPoint("\nSelect internal point: ");
            if(ppr.Status != PromptStatus.OK) return;

            DBObjectCollection objs = ed.TraceBoundary(ppr.Value, true);
            if(objs.Count == 0) return;

            using(Transaction tr = doc.TransactionManager.StartTransaction()){
                BlockTableRecord cspace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                Hatch hat = new Hatch();
                hat.SetDatabaseDefaults();
                hat.SetHatchPattern(HatchPatternType.PreDefined, "SOLID");
                cspace.AppendEntity(hat);
                tr.AddNewlyCreatedDBObject(hat, true);

                hat.Associative = true;
                foreach(DBObject obj in objs){
                    Curve c = obj as Curve;
                    if(c != null){
                        ObjectId curveId = cspace.AppendEntity(c);
                        tr.AddNewlyCreatedDBObject(c, true);
                        hat.AppendLoop(HatchLoopTypes.Default, new ObjectIdCollection() { curveId });
                    }
                }
                hat.EvaluateHatch(true);

                tr.Commit();
            }
        }

Patch61

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #4 on: May 07, 2011, 02:30:38 AM »
Thanks, kaefer!

This works well. I really appreciate your help. (if only AutoDesk's documentation were as helpful!)

 :-)

Patch61

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #5 on: May 17, 2011, 02:58:47 PM »
Ok, I've run into a small problem. If I have the TraceBoundary function set to detect islands, I get an error that says eInvalidInput. The crash only happens if it does detect an island. I'm wondering if maybe it is because there would be two polylines returned by the TraceBoundary function instead of one? I add all entities returned into the objectID collection and pass that on to the AppendLoop method. I'm not sure why that would crash the hatch creation, tho. I looked everywhere and couldn't find a code example that specifically handled islands. I can't step through the code to debug because I'm using VB2010 Express and none of the debugging workarounds work for me.

Thanks

Code: [Select]
   Public Shared Sub Pick()
        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim ed As Editor = doc.Editor
        Dim _index As Integer = 3
        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database
        Dim acEditor As Editor = acDoc.Editor
        Dim acBlkTbl As BlockTable

        Dim tr As Transaction = doc.TransactionManager.StartTransaction()
        Using tr
            ' add the objects to the model space
            Dim bt As BlockTable = DirectCast(tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
            Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
            Dim acSSPrompt As PromptSelectionResult
            Dim acSSet As SelectionSet
            Dim acPoly As Polyline = Nothing
            Dim acMText As MText = Nothing
            Dim acDBText As DBText = Nothing
            Dim TxtLoc As Autodesk.AutoCAD.Geometry.Point3d
            Dim strRoomNum As String = String.Empty
            Dim acHatch As Hatch = New Hatch()
            Dim frmHatch As frmHatchDetails
            Dim acLyrTbl As LayerTable
            Dim acLyrTblRec As LayerTableRecord
            Dim acBlkTblRec As BlockTableRecord
            Dim acColorNum As Integer
            Dim result As DialogResult
            Try
                Do
                    acSSPrompt = acDoc.Editor.GetSelection()
                    If acSSPrompt.Status = PromptStatus.OK Then
                        acSSet = acSSPrompt.Value
                    Else
                        Return
                    End If

                    If acSSet.Count <> 1 Then
                        acEditor.WriteMessage("You must select only the Room Number text object to add a hatch.")
                    End If
                Loop While acSSet.Count <> 1

                For Each acSSObj As SelectedObject In acSSet
                    If Not IsDBNull(acSSObj) Then
                        Dim acObj As DBObject = tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead)
                        If TypeOf (acObj) Is Polyline Then
                            acPoly = CType(acObj, Polyline)
                        ElseIf TypeOf (acObj) Is MText Then
                            acMText = CType(acObj, MText)
                            TxtLoc = acMText.Location
                            strRoomNum = acMText.Text
                        ElseIf TypeOf (acObj) Is DBText Then
                            acDBText = CType(acObj, DBText)
                            TxtLoc = acDBText.Position
                            strRoomNum = acDBText.TextString
                        End If
                    End If
                Next

                'create/retrieve layer
                acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)
                If acLyrTbl.Has("A-ROOM") = False Then
                    acLyrTblRec = New LayerTableRecord()
                    '' Assign the layer a name
                    acLyrTblRec.Name = "A-ROOM"
                    '' Upgrade the Layer table for write
                    acLyrTbl.UpgradeOpen()
                    '' Append the new layer to the Layer table and the transaction
                    acLyrTbl.Add(acLyrTblRec)
                    tr.AddNewlyCreatedDBObject(acLyrTblRec, True)
                    acLyrTblRec.IsOff = True
                End If

                ' Get the objects making up the boundary
                Dim objs As DBObjectCollection = ed.TraceBoundary(TxtLoc, True)

                ' Add boundary objects to the drawing and
                ' collect their ObjectObjIDCol for later use
                Dim ObjIDCol As New ObjectIdCollection()
                For Each acobj As DBObject In objs
                    Dim ent As Entity = TryCast(acobj, Entity)
                    If ent IsNot Nothing Then
                        If Not acLyrTbl.Has("RM") Then
                            If TypeOf (acobj) Is Polyline Then
                                acLyrTblRec = New LayerTableRecord()
                                '' Assign the layer a name
                                acLyrTblRec.Name = "RM"
                                '' Upgrade the Layer table for write
                                acLyrTbl.UpgradeOpen()
                                '' Append the new layer to the Layer table and the transaction
                                acLyrTbl.Add(acLyrTblRec)
                                tr.AddNewlyCreatedDBObject(acLyrTblRec, True)
                                acPoly = CType(acobj, Polyline)
                                acPoly.Layer = "RM"
                            End If
                        Else
                            acLyrTblRec = tr.GetObject(acLyrTbl("RM"), OpenMode.ForWrite)
                            acLyrTblRec.IsOff = False
                        End If

                        ' Add each boundary object to the modelspace
                        ' and add its ID to a collection
                        ObjIDCol.Add(btr.AppendEntity(ent))
                        tr.AddNewlyCreatedDBObject(ent, True)
                    End If
                Next

                acHatch.SetHatchPattern(HatchPatternType.PreDefined, "SOLID")
                acHatch.ColorIndex = System.Math.Max(System.Threading.Interlocked.Increment(_index), _index - 1)

                Dim acHatchId As ObjectId = btr.AppendEntity(acHatch)
                tr.AddNewlyCreatedDBObject(acHatch, True)

                If Not acLyrTbl.Has("DC-" & strRoomNum) Then
                    acLyrTblRec = New LayerTableRecord()
                    '' Assign the layer a name
                    acLyrTblRec.Name = "DC-" & strRoomNum
                    '' Upgrade the Layer table for write
                    acLyrTbl.UpgradeOpen()
                    '' Append the new layer to the Layer table and the transaction
                    acLyrTbl.Add(acLyrTblRec)
                    tr.AddNewlyCreatedDBObject(acLyrTblRec, True)
                Else
                    acLyrTblRec = tr.GetObject(acLyrTbl("DC-" & strRoomNum), OpenMode.ForRead)
                End If

                'set associative properties of new hatch object
                acHatch.SetDatabaseDefaults()
                'acHatch.HatchObjectType =
                acHatch.SetHatchPattern(HatchPatternType.PreDefined, "SOLID")
                acHatch.Layer = "DC-" & strRoomNum
                acHatch.Associative = True
                acHatch.AppendLoop(HatchLoopTypes.[Default], ObjIDCol)

                acHatch.EvaluateHatch(True)

                btr.DowngradeOpen()
                ObjIDCol.Add(acHatchId)

                'this is used to send the hatch to the back so it isn't overtop of the text
                Dim dot As Autodesk.AutoCAD.DatabaseServices.DrawOrderTable = tr.GetObject(btr.DrawOrderTableId, OpenMode.ForWrite)
                dot.MoveToBottom(ObjIDCol)

                ' Commit the transaction
                tr.Commit()

            Catch ex As Exception
                Autodesk.AutoCAD.ApplicationServices.Application.
                    ShowAlertDialog("An error was encountered trying to add a hatch object.  Error: " & ex.Message)
            End Try
        End Using
    End Sub
« Last Edit: May 17, 2011, 11:46:31 PM by Patch61 »

kaefer

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #6 on: May 18, 2011, 03:51:14 AM »
... If I have the TraceBoundary function set to detect islands, I get an error that says eInvalidInput. The crash only happens if it does detect an island.

I think that's because you're putting multiple loops into the same ObjectIdCollection, whereas you should call Hatch.AppendLoop for each loop separately.

Cheers

Patch61

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #7 on: May 18, 2011, 08:39:39 AM »
Great! I will try this out when I get home tonight. I guess I assumed that since the function accepted a collection, that it would handle multiple objects. But, this makes sense.

Thanks again!

Patch61

  • Guest
Re: Can a hatch be created in .net by clicking a point?
« Reply #8 on: May 19, 2011, 08:43:36 AM »
That was exactly the problem. I had to jury-rig some changes to try this out, but it worked. I'll post the code once I get a chance to clean it up a little.

Thanks again, kaefer!