Author Topic: Sweeping a Solid  (Read 2281 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 596
Sweeping a Solid
« on: March 03, 2016, 04:18:45 PM »
I have created some simple code to sweep a circle around a polyline.  Unfortunately in wireframe mode the swept solid does not look the same as one created manually using the sweep command as shown in the first picture below.







In this picture, I have the manual sweep on the left and the one created by code on the right.





Here is the code that generated the solid above.  I cannot think straight today.  What do you think needs to be done in order for it to look correct in wireframe?

Code - Visual Basic: [Select]
  1.     Private Sub InputButton1_Click(sender As Object, e As EventArgs) Handles InputButton1.Click
  2.         using Active.Document.LockDocument()
  3.             Using transaction = Active.Database.TransactionManager.StartTransaction()
  4.                 Dim modelSpace = Active.Database.ModelSpace(OpenMode.ForWrite)
  5.                 Dim polylineSegmentCollection = New PolylineSegmentCollection()
  6.                 Using lineSegment1 = New LineSegment2d(New Point2d(- 4, 4), New Point2d(- 4, 0))
  7.                     Dim lineSegment = new PolylineSegment(lineSegment1)
  8.                     polylineSegmentCollection.Add(lineSegment)
  9.                 End Using
  10.                 Dim arcSegment = new PolylineSegment(New Point2d(- 4, 0), New Point2d(4, 0), 1, 0)
  11.                 polylineSegmentCollection.Add(arcSegment)
  12.                 Using lineSegment2 = New LineSegment2d(New Point2d(4, 0), New Point2d(4, 4))
  13.                     Dim lineSegment = new PolylineSegment(lineSegment2)
  14.                     polylineSegmentCollection.Add(lineSegment)
  15.                 End Using
  16.                 Using centerLine = polylineSegmentCollection.ToPolyline()
  17.                     modelSpace.AppendEntity(centerLine)
  18.                     transaction.AddNewlyCreatedDBObject(centerLine, True)
  19.                     Dim solid = New Solid3d()
  20.                     Using circle = New Circle(Point3d.Origin, Vector3d.ZAxis, .5)
  21.                         Dim sweepOptionsBuilder = New SweepOptionsBuilder()
  22.                         sweepOptionsBuilder.Align = SweepOptionsAlignOption.AlignSweepEntityToPath
  23.                         sweepOptionsBuilder.BasePoint = Point3d.Origin
  24.                         sweepOptionsBuilder.Bank = True
  25.                         solid.CreateSweptSolid(circle, centerline, sweepOptionsBuilder.ToSweepOptions())
  26.                     End Using
  27.                     modelSpace.AppendEntity(solid)
  28.                     transaction.AddNewlyCreatedDBObject(solid, True)
  29.                     transaction.Commit()
  30.                 End Using
  31.             End Using
  32.         End Using
  33.     End Sub
  34.  


I am using Gile's Geometry Extensions to create the polyline and have not shown the code for those methods.  If you need them a simple google search will find the correct thread.
« Last Edit: March 03, 2016, 04:30:29 PM by Keith Brown »
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

kdub

  • Mesozoic relic
  • SuperMod
  • Swamp Rat
  • Posts: 1363
  • class keyThumper<T>:ILazy<T>
Re: Sweeping a Solid
« Reply #1 on: March 03, 2016, 10:43:41 PM »

That is weird,
It looks like ISOLINES DISPSILH VSEDGES etc system variables are being changed for one solid .... and I wasn't aware that could be done.
called Kerry in my other life

Sometimes the question is more important than the answer.
#ridesober

Master_Shake

  • Swamp Rat
  • Posts: 1439
Re: Sweeping a Solid
« Reply #2 on: March 08, 2016, 01:09:53 PM »
Were both sweep paths (left and right) created programmatically?

Keith Brown

  • Swamp Rat
  • Posts: 596
Re: Sweeping a Solid
« Reply #3 on: March 08, 2016, 01:15:32 PM »
Yes.  The sweep manually was done by running the program once and then deleting the solid portion of it and sweeping the circle along the polyline path.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Sweeping a Solid
« Reply #4 on: March 09, 2016, 07:40:57 AM »
You are in vanilla, right?  If you're in a vertical, I would look at the display manager and see if that's affecting it.
Revit 2019, AMEP 2019 64bit Win 10

Keith Brown

  • Swamp Rat
  • Posts: 596
Re: Sweeping a Solid
« Reply #5 on: March 09, 2016, 10:45:27 AM »
Yes, running Vanilla AutoCAD.  Well a vertical that starts Vanilla Autocad.  That being said if it was the Display Representation I believe that it would effect both 3d Solids similarly.  They would both look the same.


The problem with the solid created in code that the circle appears to be rotated somewhat when it is swept.  The circle rotation is constant, it is just not aligned with the path correctly.  I have tried all of the sweep builder options and have not come up with anything that appears to work.


My next option will be to try to get this in front of the developers over at the official .NET page and see if they come up with anything.


I am wondering if anyone else running the code has the same issue?  Or is it just me.  I could try building the polyline differently and see if that has an effect but I believe that it will probably not.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Jeff H

  • Needs a day job
  • Posts: 6035
Re: Sweeping a Solid
« Reply #6 on: March 09, 2016, 11:30:52 AM »
I can temporarily mimic it I think in UI


ISOLINES = 4
Sweep
ISOLINES = 2
Sweep

But if I orbit or regen then first sweep updates to look like second one with ISOLINES = 2.


Master_Shake

  • Swamp Rat
  • Posts: 1439
Re: Sweeping a Solid
« Reply #7 on: March 09, 2016, 12:57:43 PM »
I can temporarily mimic it I think in UI


ISOLINES = 4
Sweep
ISOLINES = 2
Sweep

But if I orbit or regen then first sweep updates to look like second one with ISOLINES = 2.

What's odd is that those are system variables, not entity specific properties.

MickD

  • Gator
  • Posts: 3289
  • (x-in)->[process]->(y-out)
Re: Sweeping a Solid
« Reply #8 on: March 09, 2016, 02:51:14 PM »
It's like the circle isn't aligned properly for the sweep.
I was thinking you may need to translate and align the circle normal with the polyline start segment direction like you would with an Extrude but I think this call looks after that:

Code - C#: [Select]
  1. sweepOptionsBuilder.Align = SweepOptionsAlignOption.AlignSweepEntityToPath

try changing

Code - C#: [Select]
  1. sweepOptionsBuilder.BasePoint = Point3d.Origin

to

Code - C#: [Select]
  1. sweepOptionsBuilder.BasePoint = centerLine.StartPoint

Personally, I probably would have used Extrude along path as the 3dSolid section is constant whereas a sweep can have a taper and many other properties that might not be needed.
You would probably have to do the transformation yourself though but that is trivial.
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

Keith Brown

  • Swamp Rat
  • Posts: 596
Re: Sweeping a Solid
« Reply #9 on: March 11, 2016, 07:38:02 AM »
I got some time last night to look at this again and I still have not had any luck.  I tried all of the suggestions listed above and still basically got the same results.  Even the ExtrudeAlongPath is looking incorrect.  I am beginning to think that I have something else wrong with my system settings.   

Code - Visual Basic: [Select]
  1.         using Active.Document.LockDocument()
  2.             Using transaction = Active.Database.TransactionManager.StartTransaction()
  3.                 Dim modelSpace = Active.Database.ModelSpace(OpenMode.ForWrite)
  4.                 Dim polylineSegmentCollection = New PolylineSegmentCollection()
  5.                 Using lineSegment1 = New LineSegment2d(New Point2d(-4, 4), New Point2d(-4, 0))
  6.                     Dim lineSegment = new PolylineSegment(lineSegment1)
  7.                     polylineSegmentCollection.Add(lineSegment)
  8.                 End Using
  9.                 Dim arcSegment = new PolylineSegment(New Point2d(-4, 0), New Point2d(4, 0), 1, 0)
  10.                 polylineSegmentCollection.Add(arcSegment)
  11.                 Using lineSegment2 = New LineSegment2d(New Point2d(4, 0), New Point2d(4, 4))
  12.                     Dim lineSegment = new PolylineSegment(lineSegment2)
  13.                     polylineSegmentCollection.Add(lineSegment)
  14.                 End Using
  15.                 Using centerLine = polylineSegmentCollection.ToPolyline()
  16.                     Dim solid1 = New Solid3d()
  17.                     Using circle = New Circle(centerLine.StartPoint, Vector3d.YAxis, .5)
  18.                         Dim sweepOptionsBuilder = New SweepOptionsBuilder()
  19.                         sweepOptionsBuilder.Align = SweepOptionsAlignOption.AlignSweepEntityToPath
  20.                         sweepOptionsBuilder.BasePoint = centerLine.StartPoint
  21.                         sweepOptionsBuilder.Bank = True
  22.                         solid1.CreateSweptSolid(circle, centerline, sweepOptionsBuilder.ToSweepOptions())
  23.                     End Using
  24.                     modelSpace.AppendEntity(solid1)
  25.                     transaction.AddNewlyCreatedDBObject(solid1, True)
  26.  
  27.                     Dim solid2 = New Solid3d()
  28.                     Using circle2 = New Circle(centerLine.StartPoint, Vector3d.YAxis, 0.5)
  29.                         Dim circleCollection = New DBObjectCollection()
  30.                         circleCollection.Add(circle2)
  31.                         Dim regionCollection = Autodesk.AutoCAD.DatabaseServices.Region.CreateFromCurves(circleCollection)
  32.                         Dim region As Region = regionCollection(0)
  33.                         solid2.ExtrudeAlongPath(region, centerLine, 0.0)
  34.                     End Using
  35.                     solid2.TransformBy(Matrix3d.Displacement(New Vector3d(-12, 0, 0)))
  36.                     modelSpace.AppendEntity(solid2)
  37.                     transaction.AddNewlyCreatedDBObject(solid2, True)
  38.                     transaction.Commit()
  39.                 End Using
  40.             End Using
  41.         End Using

ISOLINES does remedy the situation but only if you make it a high value and as Jeff mentioned changing it back and regening just resets it to its originally sucky condition.


What I am trying to accomplish is the beginnings of making a U-Bolt.  I thought this was going to be an easy exercise but apparently I over estimated my own ability.  :(
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

MickD

  • Gator
  • Posts: 3289
  • (x-in)->[process]->(y-out)
Re: Sweeping a Solid
« Reply #10 on: March 11, 2016, 06:04:33 PM »
I think I've come across this before too Keith and as long it doesn't affect the integrity of your system/data, don't let it worry you too much unless your 2d output is suffering. :)
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

Keith Brown

  • Swamp Rat
  • Posts: 596
Re: Sweeping a Solid
« Reply #11 on: March 12, 2016, 01:01:28 PM »
Well I kept at it and came up with a solution that works for me.  I noticed that when used the ExtrudeAlongPath api that only the first segment of the polyline was incorrect.  So i just made the first segment the minimum length that Autocad would accept for an extrusion which in this case was 0.001.


I made a couple modifications to the code and this is what I came up with.  Hopefully it will help someone in the future.

Code - Visual Basic: [Select]
  1. Private Sub InputButton1_Click(sender As Object, e As EventArgs) Handles InputButton1.Click
  2.    Me.CancelCommands()
  3.    using Active.Document.LockDocument()
  4.       Using transaction = Active.Database.TransactionManager.StartTransaction()
  5.          Dim modelSpace = Active.Database.ModelSpace(OpenMode.ForWrite)
  6.          Dim uBolt = CreateUBolt(0.375, 3.5, 3.0)
  7.          If uBolt IsNot Nothing Then
  8.             modelSpace.AppendEntity(uBolt)
  9.             transaction.AddNewlyCreatedDBObject(uBolt, True)
  10.          Else
  11.             Active.WriteMessage("Unable to create a UBolt with the current dimensions.")
  12.          End If
  13.          transaction.Commit()
  14.       End Using
  15.    End Using
  16. End Sub
  17.  
  18. ''' <summary>
  19. ''' Cancels any current command by sending escape to the command line twice.
  20. ''' </summary>
  21. Private Sub CancelCommands()
  22.    If CShort(CoreApplication.GetSystemVariable("CMDACTIVE")) <> 0 Then
  23.       Active.Document.SendStringToExecute(ChrW(27) & ChrW(27), False, True, False)
  24.       Utils.PostCommandPrompt()
  25.    End If
  26. End Sub
  27.  
  28. Private Const MinimumExtrusionLength = .001
  29.  
  30.  
  31. ''' <summary>
  32. ''' Createsa 3D UBolt with a center point at the world origin.  To change the centerpoint, tranform the solid after creation.
  33. ''' </summary>
  34. ''' <param name="uBoltDiameter">The u bolt diameter.</param>
  35. ''' <param name="pipeDiameter">The pipe diameter.</param>
  36. ''' <param name="extendedLength">The extended length of the ubolt beyond the diameter..</param>
  37. ''' <returns>A Solid3D representation of the UBolt</returns>
  38. ''' <exception cref="System.ArgumentOutOfRangeException">
  39. ''' UBolt Diameter is too small.
  40. ''' or
  41. ''' Pipe Diameter is to small.
  42. ''' </exception>
  43. Private Function CreateUBolt(uBoltDiameter As Double, pipeDiameter As Double, extendedLength As Double) As Solid3d
  44.  
  45.    If uBoltDiameter <= MinimumExtrusionLength Then
  46.       Throw New ArgumentOutOfRangeException(NameOf(uBoltDiameter), "UBolt Diameter is too small.")
  47.    End If
  48.    If pipeDiameter <= MinimumExtrusionLength Then
  49.       Throw New ArgumentOutOfRangeException(NameOf(pipeDiameter), "Pipe Diameter is to small.")
  50.    End If
  51.    Dim centerToCenter = (pipeDiameter / 2) + uBoltDiameter
  52.  
  53.    ' While not probable, it is possible that the sum value is greater then the largest double value.  Input values for
  54.   ' extended length should take this into account.
  55.   Dim straightLength = (pipeDiameter / 2) + extendedLength
  56.    Dim uBolt = New Solid3d()
  57.    Dim polylineSegmentCollection = New PolylineSegmentCollection()
  58.    using lineSegment1 = New LineSegment2d(New Point2d(-1 * centerToCenter, straightLength), New Point2d(-1 * centerToCenter, straightLength - minimumExtrusionLength))
  59.       Dim lineSegment = New PolylineSegment(lineSegment1)
  60.       polylineSegmentCollection.Add(lineSegment)
  61.    End Using
  62.    Using lineSegment2 = New LineSegment2d(New Point2d(-1 * centerToCenter, straightLength - minimumExtrusionLength), New Point2d(-1 * centerToCenter, 0))
  63.       Dim lineSegment = new PolylineSegment(lineSegment2)
  64.       polylineSegmentCollection.Add(lineSegment)
  65.    End Using
  66.    Dim arcSegment = new PolylineSegment(New Point2d(-1 * centerToCenter, 0), New Point2d(centerToCenter, 0), 1, 0)
  67.    polylineSegmentCollection.Add(arcSegment)
  68.    Using lineSegment3 = New LineSegment2d(New Point2d(centerToCenter, 0), New Point2d(centerToCenter, straightLength))
  69.       Dim lineSegment = new PolylineSegment(lineSegment3)
  70.       polylineSegmentCollection.Add(lineSegment)
  71.    End Using
  72.    Using centerLine = polylineSegmentCollection.ToPolyline()
  73.       Using profile = New Circle(centerLine.StartPoint, Vector3d.YAxis, uBoltDiameter)
  74.          Try
  75.             Dim profileCollection = New DBObjectCollection()
  76.             profileCollection.Add(profile)
  77.             Dim profileRegionCollection = Autodesk.AutoCAD.DatabaseServices.Region.CreateFromCurves(profileCollection)
  78.             Dim profileRegion As Region = profileRegionCollection(0)
  79.             uBolt.ExtrudeAlongPath(profileRegion, centerLine, 0.0)
  80.             uBolt.CleanBody()
  81.          Catch exception As Exception
  82.             Log.Logger.Error(exception, "Unable to extrude the 3D Solid")
  83.             Return Nothing
  84.          End Try
  85.  
  86.       End Using
  87.    End Using
  88.    Return uBolt
  89. End Function
« Last Edit: March 14, 2016, 09:26:31 AM by Keith Brown »
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Master_Shake

  • Swamp Rat
  • Posts: 1439
Re: Sweeping a Solid
« Reply #12 on: March 14, 2016, 07:57:28 AM »
Curious, kind of makes sense but I wonder what the absolute minimum is as there is a soft-coded maximum limit on extrusions.

Also, is it a concern that you added an additional vertex into the solid? Might be beneficial (if possible in .net) to clean the 3D solid after extrusion.

 

Master_Shake

  • Swamp Rat
  • Posts: 1439
Re: Sweeping a Solid
« Reply #13 on: March 14, 2016, 07:57:51 AM »
Pre-Clean attached

Keith Brown

  • Swamp Rat
  • Posts: 596
Re: Sweeping a Solid
« Reply #14 on: March 14, 2016, 09:12:19 AM »
I was unaware that you could 'Clean' solids.


I updated the previous post with the CleanBody() method.  Thanks for the info.


I do believe that .001 is the minimum length for solid functions. 
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

huiz

  • Swamp Rat
  • Posts: 832
  • Certified Prof C3D
Re: Sweeping a Solid
« Reply #15 on: April 12, 2019, 09:00:51 AM »
Quite old this topic but useful information now I am working on this.


I found out that a Solid created by the AutoCAD Command creates a more intelligent 3D Solid than I create with code. Do a list on both and you will see this:


Code: [Select]

                  3DSOLID   Layer: "0"
                            Space: Model space
                   Color: BYLAYER    Linetype: "Continuous"
                   LineWeight: Default
                   Handle = 145
         History = None
    Show History = No
   Bounding Box: Lower Bound X = 159.809  , Y = 159.747  , Z = 0.341
                 Upper Bound X = 198.179  , Y = 186.957  , Z = 4.638




Code: [Select]



                  3DSOLID   Layer: "0"
                            Space: Model space
                   Handle = 157
         History = None
    Show History = No
      Solid type = Sweep
     Sweep length: 38.867
 Profile rotation: 0.00
 Scale along path: 1.000
 Twist along path: 0.00
Press ENTER to continue:
             Bank: Off
   Bounding Box: Lower Bound X = 173.891  , Y = 144.954  , Z = -0.692
                 Upper Bound X = 205.943  , Y = 169.206  , Z = 0.692


So, the API probably just create a 3D Solid and AutoCAD can create a more intelligent object.


Also, and that makes it really weird, the coded solid get XData added! Why?


Code: [Select]

* Registered Application Name: ACAD_STEPID
* Code 1071, 32-bit signed long integer: 2



The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.