Looking for suggestions or improvements on sketch creating function

Looking for suggestions or improvements on sketch creating function

pball
Mentor Mentor
1,824 Views
16 Replies
Message 1 of 17

Looking for suggestions or improvements on sketch creating function

pball
Mentor
Mentor

I use a 2 point center rectangle with points on the corners all the time for creating symmetrical holes centered on a part and have dreamt of making a script to do it for far too long. Finally found some time to make this script and as sketches are one of the more unknown areas of the API for me, I wanted to see if anyone has suggestions or better ways to accomplish this. This code is VBA and was done as a proof of concept, I'm going to clean it up better and move it over to my VB.net addin when I have more spare time.

Public Sub SketchCreation()
    'Prompt to select face to create new sketch
    Dim sketch As PlanarSketch
    Set sketch = ThisApplication.ActiveEditDocument.ComponentDefinition.Sketches.Add(ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick face to add sketch"))
    
    Dim tg As TransientGeometry
    Set tg = ThisApplication.TransientGeometry

    Dim oPoint As WorkPoint
    Set oPoint = ThisApplication.ActiveDocument.ComponentDefinition.WorkPoints.Item(1)

    'Try to get origin point
    Dim oOriginSketchPoint As SketchPoint
    Dim oSketchPoint As SketchPoint
    For Each oSketchPoint In sketch.SketchPoints
        If oSketchPoint.ReferencedEntity Is oPoint Then
            Set oOriginSketchPoint = oSketchPoint
            Exit For
        End If
    Next
    
    ' Create the sketch point for the origin, if it doesn't already exist.
    If oOriginSketchPoint Is Nothing Then
        ' Project the origin point onto the sketch.
        Set oOriginSketchPoint = sketch.AddByProjectingEntity(oPoint)
    End If
    
    'Get size of rectangle
    X = CDbl(InputBox(Prompt:="X dimension.", Title:="X", Default:="1")) * 2.54
    Y = CDbl(InputBox(Prompt:="Y dimension.", Title:="Y", Default:="1")) * 2.54

    ' Draw rectangles by center point.
    Call sketch.SketchLines.AddAsTwoPointCenteredRectangle(oOriginSketchPoint, tg.CreatePoint2d(X / 2, Y / 2))
    
    'Add dimensions to two sides of rectangle
    Dim TextPoint As Point2d
    Set TextPoint = ThisApplication.TransientGeometry.CreatePoint2d(0, Y / 2 + 1)
    Call sketch.DimensionConstraints.AddTwoPointDistance(sketch.SketchLines.Item(3).StartSketchPoint, sketch.SketchLines.Item(3).EndSketchPoint, kHorizontalDim, TextPoint)
    Set TextPoint = ThisApplication.TransientGeometry.CreatePoint2d(X / 2 + 1, 0)
    Call sketch.DimensionConstraints.AddTwoPointDistance(sketch.SketchLines.Item(2).StartSketchPoint, sketch.SketchLines.Item(2).EndSketchPoint, kVerticalDim, TextPoint)
    
    'Add center points four corners of rectangle
    Dim point As SketchPoint
    For num = 1 To 4 Step 2
        Set point = sketch.SketchPoints.Add(tg.CreatePoint2d(0, 0))
        Call sketch.GeometricConstraints.AddCoincident(point, sketch.SketchLines.Item(num).StartSketchPoint)
        Set point = sketch.SketchPoints.Add(tg.CreatePoint2d(0, 0))
        Call sketch.GeometricConstraints.AddCoincident(point, sketch.SketchLines.Item(num).EndSketchPoint)
    Next
End Sub

 

pball_0-1710177546695.png

Check out my style edits for the Autodesk forums
pball's Autodesk Forum Style

Userscript to edit forum links to jump to first unread post
Jump To First Post Userscript
0 Likes
1,825 Views
16 Replies
Replies (16)
Message 2 of 17

davidt162003
Advocate
Advocate

the only two things which are different to the way my add-in is set up are some separation and generalization. Ie create sketch just creates a sketch then calls a sub to add in the origin and my create sketch sub can take a plane, plane enum, plane name or a face. but i presume you were going to do steps like that when transferring to vb.net

 

the only other thing i have which might not be important in your work flow is checking if said sketch already exists and naming it 

 For Each pSK As PlanarSketch In PartDef.Sketches
     If pSK.Name = SketchName Then
         CheckOrginSkPnt(PartDef, pSK)
         Return pSK
     End If
 Next

  

HII
0 Likes
Message 3 of 17

WCrihfield
Mentor
Mentor

Hi @pball.  This copy of your code is basically just cleaned-up for vb.net (or an iLogic rule) and includes a few tweaks to help improve performance a little.  It is pretty much always best to get a collection to a variable before iterating the items in that collection, and if the same item is retrieved from the collection more than once, it is better to create a variable for it, then use that variable in later lines.  Just tiny stuff like that.  Looks pretty good overall though.  Depending on how / when it gets called to run, it might be a good idea to make sure it is getting a 'model' document though, and not a drawing or presentation, just to avoid that potential error.  Or, it could just attempt to step up the object model ladder from the 'Picked' Face to get a reference to the needed ComponentDefinition or Document.

 

Public Sub SketchCreation()
	Dim oDoc As Inventor.Document = ThisApplication.ActiveEditDocument
	Dim oDef As ComponentDefinition = oDoc.ComponentDefinition
	'Prompt to select face to create new sketch
	Dim oFace As Inventor.Face = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick face to add sketch")
	If oFace Is Nothing Then Return
	Dim sketch As PlanarSketch = oDef.Sketches.Add(oFace)

	Dim tg As TransientGeometry = ThisApplication.TransientGeometry

	Dim oOriginPoint As WorkPoint = oDef.WorkPoints.Item(1)
	sketch.OriginPoint = oOriginPoint
	Dim oOriginSketchPoint As SketchPoint

	'Try to get origin point
	Dim oSketchPoints As SketchPoints = sketch.SketchPoints
	Dim oSketchPoint As SketchPoint
	For Each oSketchPoint In oSketchPoints
		If oSketchPoint.ReferencedEntity Is oOriginPoint Then
			oOriginSketchPoint = oSketchPoint
			Exit For
		End If
	Next
	' Create the sketch point for the origin, if it doesn't already exist.
	If oOriginSketchPoint Is Nothing Then
		' Project the origin point onto the sketch.
		oOriginSketchPoint = sketch.AddByProjectingEntity(oOriginPoint)
	End If

	'Get size of rectangle
	X = CDbl(InputBox(Prompt :="X dimension.", Title :="X", DefaultResponse :="1")) * 2.54
	Y = CDbl(InputBox(Prompt :="Y dimension.", Title :="Y", DefaultResponse :="1")) * 2.54

	' Draw rectangles by center point.
	Dim oSketchLines As SketchLines = sketch.SketchLines
	oSketchLines.AddAsTwoPointCenteredRectangle(oOriginSketchPoint, tg.CreatePoint2d(X / 2, Y / 2))

	'Add dimensions to two sides of rectangle
	Dim oDConstraints As DimensionConstraints = sketch.DimensionConstraints
	Dim TextPoint As Point2d = tg.CreatePoint2d(0, Y / 2 + 1)
	Dim oSketchLine2 As SketchLine = oSketchLines.Item(2)
	Dim oSketchLine3 As SketchLine = oSketchLines.Item(3)
	oDConstraints.AddTwoPointDistance(oSketchLine3.StartSketchPoint, oSketchLine3.EndSketchPoint, DimensionOrientationEnum.kHorizontalDim, TextPoint)
	TextPoint = tg.CreatePoint2d(X / 2 + 1, 0)
	oDConstraints.AddTwoPointDistance(oSketchLine2.StartSketchPoint, oSketchLine2.EndSketchPoint, DimensionOrientationEnum.kVerticalDim, TextPoint)

	'Add center points four corners of rectangle
	Dim oGConstraints As GeometricConstraints = sketch.GeometricConstraints
	Dim oPointZero As Inventor.Point2d = tg.CreatePoint2d(0, 0)
	For num = 1 To 4 Step 2
		Dim oThisSketchLine As SketchLine = oSketchLines.Item(num)
		oSketchPoint = oSketchPoints.Add(oPointZero)
		oSketchPoint.HoleCenter = True
		oGConstraints.AddCoincident(oSketchPoint, oThisSketchLine.StartSketchPoint)
		oSketchPoint = oSketchPoints.Add(oPointZero)
		oSketchPoint.HoleCenter = True
		oGConstraints.AddCoincident(oSketchPoint, oThisSketchLine.EndSketchPoint)
	Next
End Sub

 

If this solved your problem, or answered your question, please click ACCEPT SOLUTION .
Or, if this helped you, please click (LIKE or KUDOS) 👍.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 17

J-Camper
Advisor
Advisor

@pball,

I did a little rework here:

Public Sub SketchCreation()
	Dim aeDoc As Document = ThisApplication.ActiveEditDocument
    'Prompt to select face to create new sketch
    Dim sketch As PlanarSketch = aeDoc.ComponentDefinition.Sketches.Add(ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick face to add sketch"), True)
    If sketch Is Nothing Then MessageBox.Show("No face selected to create a sketch on.", "Early Exit") :Exit Sub

    'get origin point in 2D space
    Dim oOriginSketchPoint As SketchPoint = sketch.AddByProjectingEntity(aeDoc.ComponentDefinition.WorkPoints.Item(1))
    
    'Get size of rectangle
	Dim Xinput As String = InputBox(Prompt :="X dimension [input as inches].", Title :="X", DefaultResponse :="1")
	If Xinput Is String.Empty Then sketch.Delete() : Exit Sub
	Dim Yinput As String = InputBox(Prompt:="Y dimension [input as inches].", Title:="Y", DefaultResponse:="1")
	If Yinput Is String.Empty Then sketch.Delete() : Exit Sub
	
	'get doubles from strings
	Dim X, Y As Double 
	Try
		X = Abs(CDbl(Xinput)) * 2.54 'convert expected inches to cm for database
	Catch
		MessageBox.Show(String.Format("User input: {0} could not be converted to Double.", Xinput), "Early Exit") : sketch.Delete() : Exit Sub
	End Try
	Try
		Y = Abs(CDbl(Yinput)) * 2.54 'convert expected inches to cm for database
	Catch
		MessageBox.Show(String.Format("User input: {0} could not be converted to Double.", Yinput), "Early Exit") : sketch.Delete() : Exit Sub
	End Try
	'Exit if 0 is entered for either X or Y
	If X*Y = 0 Then MessageBox.Show(String.Format("Both values X({0}) and Y({1}) need to be non-zero.", X, Y), "Early Exit") : sketch.Delete() : Exit Sub
		
	'Create second point to make rectangle
	Dim RectangleCorner As Point2d = oOriginSketchPoint.Geometry.Copy
	RectangleCorner.X += X / 2
	RectangleCorner.Y += Y / 2
	
    ' Draw rectangles by center point.
    Dim RectangleLines As SketchEntitiesEnumerator = sketch.SketchLines.AddAsTwoPointCenteredRectangle(oOriginSketchPoint, RectangleCorner)
    
    'Add dimensions to two sides of rectangle
    Dim TextPointHorizontal As Point2d = oOriginSketchPoint.Geometry.Copy 
	TextPointHorizontal.Y += Y*.55 '5% beyond geometry
	Dim TextPointVertical As Point2d = oOriginSketchPoint.Geometry.Copy 
	TextPointVertical.X += X*.55 '5% beyond geometry
	
	sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(3).StartSketchPoint, RectangleLines.Item(3).EndSketchPoint, kHorizontalDim , TextPointHorizontal, False)
	sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(2).StartSketchPoint, RectangleLines.Item(2).EndSketchPoint, kVerticalDim   , TextPointVertical  , False)
	
	'Set all rectangle corners to be a centerpoint
	For Each skLine As SketchLine In RectangleLines.OfType(Of SketchLine)
		skLine.StartSketchPoint.HoleCenter = True
		skLine.EndSketchPoint.HoleCenter = True
	Next
	
	sketch.Solve()
End Sub

Changes:

  • Removed loop to look for origin point.  Since we are creating a new sketch each time it should be empty.  I even tested with the "AutoProjectPartOrigin" Option set to True and it was never present when creating the sketch with API
  • Removed the TransientGeometry object as i didn't need to use it
  • I separated the user input from casting to doubles since the user input is a string and a user can input a value that cannot be converted from string to double
    • I also added some checks to make sure all doubles are greater than zero.
  • I created the rectangle corner point by copying the origin and adding half the X & Y inputs to the X & Y values of the copied point
  • I did a similar thing as above with the text points for dimension constraints
  • I changed the "centerpoint corners" loop to use the lines created from the rectangle command
  • Finally I added a Call for the Sketch to solve at the end

 

Let me know if you have any questions

0 Likes
Message 5 of 17

pball
Mentor
Mentor

Thank you all for the suggestions. My original code had a weird issue where the rectangle didn't end up the proper size when choosing surfaces that weren't parallel to the XY plane. Using what @J-Camper did for the rectangle creation fixed that, so I never bothered to figure out what was happening.

 

The other big thing I noticed as I used it some more is the face selection process had to be improved in order to work while doing an in place edit in an assembly. Luckily it wasn't that hard with a bit of forum searching. I'll share any other improvements if I find anything else lacking.

 

Still VBA since I've been lazy lol

    If (ThisApplication.ActiveEditDocument.DocumentType <> kPartDocumentObject) Then
        MsgBox ("Active item is not a part")
        Exit Sub
    End If
    Dim oPart As PartDocument
    Set oPart = ThisApplication.ActiveEditDocument
    
    Dim oFace As Object
    
    'Prompt to select face to create new sketch
    If (ThisApplication.ActiveDocument.DisplayName = oPart.DisplayName) Then
        'Selection in part document
        Set oFace = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick Planar Face")
    Else
        'Selection when editing part inside assembly
        Dim oFaceProxy As FaceProxy
        Set oFaceProxy = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick Planar Face")
        Set oFace = oFaceProxy.NativeObject
    End If

 

Check out my style edits for the Autodesk forums
pball's Autodesk Forum Style

Userscript to edit forum links to jump to first unread post
Jump To First Post Userscript
0 Likes
Message 6 of 17

J-Camper
Advisor
Advisor

@pball,

 

The reason your original code was not making the rectangle the correct size is your corner point had no relationship to the 2D point representing origin work point.  The origin projected into a sketch is not guaranteed to be aligned with the sketch's coordinate system origin.  That is why I copied the center point and adjusted the copied point values with the inputs. 

0 Likes
Message 7 of 17

harvey3ELEA
Collaborator
Collaborator

J-Camper, that's a dandy little ilogic code to make the 4 corner points to create some holes.

 

Is there a way to add more than the 4 points at the corners?  Perhaps a prompt could ask how many hole centers are needed at the 4 corners plus evenly spaced down each line of the rectangle?  Just thinking out loud....

0 Likes
Message 8 of 17

WCrihfield
Mentor
Mentor

One thought would be to draw a polygon, instead of a rectangle.  Then put hole center points at all of its line end points.

SketchLines.AddAsPolygon 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 9 of 17

J-Camper
Advisor
Advisor

@harvey3ELEA,

Are you asking for a linear array along each line or a 2D matrix array, with points inside the rectangle?

If Linear, would both the left/right lines get the same count? Same question for top/bottom array.

Finally, would you want individual points constrained and dimensioned on their own or a sketch array of points?

We could develop the code to go down anyone of the routes branching from my questions, maybe even some I'm not thinking of, so if you have a specific workflow in mind you could present it.  With that being said, this may be deviating from the original post enough to create your own post for the discussion. 

0 Likes
Message 10 of 17

harvey3ELEA
Collaborator
Collaborator

Thanks for replying J-Camper.  Agreed on deviating from the original post's purpose, but there are still strong similarities using the same center-rectangle sketch idea...

 

Something along the lines of what's been done above, but would enable me to build a multi-hole flanged piece like shown in the attached snapshot (ignore that it has slotted holes).

 

We burn these as one-piece square rings at various sizes, hole spacing, and hole counts.

0 Likes
Message 11 of 17

J-Camper
Advisor
Advisor

@harvey3ELEA,

 

Try This:

 

 

Public Sub SketchCreation()
	Dim aeDoc As Document = ThisApplication.ActiveEditDocument
    'Prompt to select face to create new sketch
    Dim Sketch As PlanarSketch = aeDoc.ComponentDefinition.Sketches.Add(ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick face to add sketch"), True)
    If sketch Is Nothing Then MessageBox.Show("No face selected to create a sketch on.", "Early Exit") :Exit Sub

    'get origin point in 2D space
    Dim oOriginSketchPoint As SketchPoint = sketch.AddByProjectingEntity(aeDoc.ComponentDefinition.WorkPoints.Item(1))
    
    '[Get size of rectangle
	Dim X As Double = 1
	Dim Y As Double = 1
	
	Dim Xinput As String = InputBox(Prompt :="X dimension [input as inches].", Title :="X size", DefaultResponse := X)
	If Xinput Is String.Empty Then sketch.Delete() : Exit Sub
	Dim Yinput As String = InputBox(Prompt:="Y dimension [input as inches].", Title:="Y size", DefaultResponse:= Y)
	If Yinput Is String.Empty Then sketch.Delete() : Exit Sub
	
	'get doubles from strings
	Try
		X = Abs(CDbl(Xinput)) * 2.54 'convert expected inches to cm for database
	Catch
		MessageBox.Show(String.Format("User input: {0} could not be converted to Double.", Xinput), "Early Exit") : sketch.Delete() : Exit Sub
	End Try
	Try
		Y = Abs(CDbl(Yinput)) * 2.54 'convert expected inches to cm for database
	Catch
		MessageBox.Show(String.Format("User input: {0} could not be converted to Double.", Yinput), "Early Exit") : sketch.Delete() : Exit Sub
	End Try
	'Exit if 0 is entered for either X or Y
	If X*Y = 0 Then MessageBox.Show(String.Format("Both values X({0}) and Y({1}) need to be non-zero.", X, Y), "Early Exit") : sketch.Delete() : Exit Sub
	']	
	
	'[Get array count of rectangle
	Dim XQTY As Integer = 2
	Dim YQTY As Integer = 2
	
	Dim XQTYinput As String = InputBox(Prompt :="Quantity on holes in X direction.", Title :="X count", DefaultResponse := XQTY)
	Dim YQTYinput As String = InputBox(Prompt:="Quantity on holes in Y direction.",  Title :="Y count", DefaultResponse := YQTY)
		
	'get integers from strings
	Try
		XQTY = Round(Abs(CDbl(XQTYinput)))
	Catch : End Try
	Try
		YQTY = Round(Abs(CDbl(YQTYinput)))
	Catch : End Try

	If XQTY < 2 Then XQTY = 2 'Enforce min value
	If YQTY < 2 Then YQTY = 2 'Enforce min value
	']
	
	'[Create Initial Rectangle
	
	'Create second point to make rectangle
	Dim RectangleCorner As Point2d = oOriginSketchPoint.Geometry.Copy
	RectangleCorner.X += X / 2
	RectangleCorner.Y += Y / 2
	
    ' Draw rectangles by center point.
    Dim RectangleLines As SketchEntitiesEnumerator = sketch.SketchLines.AddAsTwoPointCenteredRectangle(oOriginSketchPoint, RectangleCorner)
    
    'Add dimensions to two sides of rectangle
    Dim TextPointHorizontal As Point2d = oOriginSketchPoint.Geometry.Copy 
	TextPointHorizontal.Y += Y*.55 '5% beyond geometry
	Dim TextPointVertical As Point2d = oOriginSketchPoint.Geometry.Copy 
	TextPointVertical.X += X*.55 '5% beyond geometry
	
	Dim HorizontalParam As Inventor.Parameter = sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(3).StartSketchPoint, RectangleLines.Item(3).EndSketchPoint, kHorizontalDim , TextPointHorizontal, False).Parameter
	Dim VerticalParam As Inventor.Parameter = sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(2).StartSketchPoint, RectangleLines.Item(2).EndSketchPoint, kVerticalDim   , TextPointVertical  , False).Parameter
	
	'prep for arrays
	Dim BottomLine, RightLine, TopLine, LeftLine As SketchLine
	'Set all rectangle corners to be a centerpoint
	For Each skLine As SketchLine In RectangleLines.OfType(Of SketchLine)
		'This appears to be a fixed draw order
		If BottomLine Is Nothing
			BottomLine = skLine
		Else If RightLine Is Nothing
			RightLine = skLine
		Else If TopLine Is Nothing
			TopLine = skLine
		Else If LeftLine Is Nothing
			LeftLine = skLine
		End If
		skLine.StartSketchPoint.HoleCenter = True
		skLine.EndSketchPoint.HoleCenter = True
		i+=1
	Next
	']
	
	'Create arrays if needed
	If XQTY <= 2 And YQTY <= 2 Then sketch.Solve() : Exit Sub 'No arrays	
	
	If XQTY > 2 Then Call AddArrayAlongLine(sketch, XQTY, TopLine, BottomLine, LeftLine, HorizontalParam, DimensionOrientationEnum.kHorizontalDim)
	If YQTY > 2 Then Call AddArrayAlongLine(sketch, YQTY, LeftLine, RightLine, BottomLine, VerticalParam, DimensionOrientationEnum.kVerticalDim)

	sketch.Solve()
End Sub

Sub AddArrayAlongLine(aSketch As PlanarSketch, HoleQuantity As Integer, StartLine As SketchLine, EndLine As SketchLine,  PerpendicularLine As SketchLine, SpanningParameter As Inventor.Parameter, Orientation As DimensionOrientationEnum)
	
	Dim Length As Double = SpanningParameter.Value
	Dim Spacing As Double = Length / (HoleQuantity - 1)
	
	Dim StartPoint As SketchPoint = Nothing
	Dim EndPoint As SketchPoint = Nothing
	Dim Counting As Integer = 2
	
	While Counting < HoleQuantity
		'StartFresh if no memory
		If StartPoint Is Nothing Then 
			StartPoint = PerpendicularLine.StartSketchPoint
			EndPoint = PerpendicularLine.EndSketchPoint
		End If
		
		'Locate new Points
		Dim newStartPoint As Point2d = StartPoint.Geometry.Copy
		Dim newEndPoint As Point2d = EndPoint.Geometry.Copy
				
		Dim TranslationVector As Vector2d = EndLine.Geometry.Direction.AsVector
		TranslationVector.ScaleBy(Spacing) 
		
		newStartPoint.TranslateBy(TranslationVector)
		newEndPoint.TranslateBy(TranslationVector)
		
		'Create new Points
		Dim newStartSketchPoint As SketchPoint = aSketch.SketchPoints.Add(newStartPoint, True)
		Dim newEndSketchPoint As SketchPoint = aSketch.SketchPoints.Add(newEndPoint, True)
		
		aSketch.GeometricConstraints.AddCoincident(newStartSketchPoint, StartLine)
		aSketch.GeometricConstraints.AddCoincident(newEndSketchPoint, EndLine)
		
		'TextPoints
		TranslationVector.ScaleBy(.5)
		Dim StartTextPoint As Point2d = StartPoint.Geometry.Copy
		StartTextPoint.TranslateBy(TranslationVector)'
		
		Dim EndTextPoint As Point2d = EndPoint.Geometry.Copy
		EndTextPoint.TranslateBy(TranslationVector) 
		
		'Dimension Constraints
		aSketch.DimensionConstraints.AddTwoPointDistance(StartPoint, newStartSketchPoint, Orientation, StartTextPoint, False).Parameter.Expression = String.Format("{0}/{1}", SpanningParameter.Name, (HoleQuantity-1))
		aSketch.DimensionConstraints.AddTwoPointDistance(EndPoint, newEndSketchPoint, Orientation , EndTextPoint, False).Parameter.Expression = String.Format("{0}/{1}", SpanningParameter.Name, (HoleQuantity-1))
		
		'Memory
		StartPoint = newStartSketchPoint
		EndPoint = newEndSketchPoint
		Counting +=1
	End While
	
End Sub 

I made some additions to the primary routine and added an array routine.  It only works for rectangles as is.  It could be rewritten to do polygons, with each line arrayed separately, but you would end up needing a user input for each line.  I did not spend time trying to develop a logical way to move the text point off the line.

 

Let me know if you have any questions, or if this is not working as intended

Message 12 of 17

harvey3ELEA
Collaborator
Collaborator

J-Camper, I can't thank you enough!  It works beautifully.

If you're ever in the Tampa area, I owe you a nice lunch!

 

Wish list if you're bored and need something to code: the same concept for a circular flange.  But I'll stop here and be thankful for your help.  It's deeply appreciated.

 

Harvey

0 Likes
Message 13 of 17

pball
Mentor
Mentor

I'm glad this topic has some good discussion going on. I was actually planning on adding the ability to have more holes along the rectangle, so it's nice to see someone else has the same idea.

Check out my style edits for the Autodesk forums
pball's Autodesk Forum Style

Userscript to edit forum links to jump to first unread post
Jump To First Post Userscript
Message 14 of 17

harvey3ELEA
Collaborator
Collaborator

pball, your original idea is an excellent one.  I'm very glad J-Camper was able to expand upon it.

We do enough here at my fab shop to recognize the need for this handy tool.

Thanks!

0 Likes
Message 15 of 17

J-Camper
Advisor
Advisor

@harvey3ELEA,

Glad you like it, and thanks for the offer.  I figured the circle wasn't too hard, so this should do it:

Public Sub SketchCreationCircle()
	Dim aeDoc As Document = ThisApplication.ActiveEditDocument
    'Prompt to select face to create new sketch
    Dim aSketch As PlanarSketch = aeDoc.ComponentDefinition.Sketches.Add(ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick face to add sketch"), True)
    If aSketch Is Nothing Then MessageBox.Show("No face selected to create a sketch on.", "Early Exit") :Exit Sub

    'get origin point in 2D space
    Dim oOriginSketchPoint As SketchPoint = aSketch.AddByProjectingEntity(aeDoc.ComponentDefinition.WorkPoints.Item(1))
    
    '[Get size of Circle
	Dim Diameter As Double = 1
	
	Dim Diameterinput As String = InputBox(Prompt :="Diameter of Circle [input as inches].", Title :="Diameter", DefaultResponse := Diameter)
	If Diameterinput Is String.Empty Then aSketch.Delete() : Exit Sub
	
	'get doubles from strings
	Try
		Diameter = Abs(CDbl(Diameterinput)) * 2.54 'convert expected inches to cm for database
	Catch
		MessageBox.Show(String.Format("User input: {0} could not be converted to Double.", Diameterinput), "Early Exit") : aSketch.Delete() : Exit Sub
	End Try

	'Exit if 0 is entered for Diameter
	If Diameter <= 0 Then MessageBox.Show(String.Format("Diameter({0}) needs to be non-zero.", Diameter), "Early Exit") : aSketch.Delete() : Exit Sub
	']	
	
	'[Get array count of circle
	Dim QTY As Integer = 0
	
	Dim QTYinput As String = InputBox(Prompt :="Quantity on holes on circle.", Title :="hole count", DefaultResponse := QTY)
		
	'get integers from strings
	Try
		QTY = Round(Abs(CDbl(QTYinput)))
	Catch : End Try

	If QTY < 0 Then QTY = 0 'Enforce min value
	']
	
	'[Create Initial Circle
			
    'Draw circle by center point.
    Dim aCircle As SketchCircle = aSketch.SketchCircles.AddByCenterRadius(oOriginSketchPoint, Diameter / 2)
    aSketch.GeometricConstraints.AddCoincident(oOriginSketchPoint, aCircle.CenterSketchPoint)
	
    'Add dimension to circle
	Dim TextPoint As Point2d = oOriginSketchPoint.Geometry.Copy 
	TextPoint.X += Diameter*.55 '5% beyond geometry
	
	aSketch.DimensionConstraints.AddDiameter(aCircle, TextPoint, False)
	
	If QTY < 1 Then aSketch.Solve() : Exit Sub 'No points	
	']
	
	'[Create array points
		
	'Create first point
	Dim RadialPoint As Point2d = oOriginSketchPoint.Geometry.Copy
	RadialPoint.X += Diameter / 2
	
	Dim RadialSketchPoint As SketchPoint = aSketch.SketchPoints.Add(RadialPoint, True)
	aSketch.GeometricConstraints.AddCoincident(RadialSketchPoint, aCircle)
	aSketch.GeometricConstraints.AddHorizontalAlign(oOriginSketchPoint, RadialSketchPoint)
	
	If QTY < 2 Then aSketch.Solve() : Exit Sub 'No arrays
		
	'Create 1 additional point if count = 2
	If QTY = 2
		
		Dim OppositeRadialPoint As Point2d = oOriginSketchPoint.Geometry.Copy
		OppositeRadialPoint.X -= Diameter / 2
		
		Dim OppositeRadialSketchPoint As SketchPoint = aSketch.SketchPoints.Add(OppositeRadialPoint, True)
		aSketch.GeometricConstraints.AddCoincident(OppositeRadialSketchPoint, aCircle)
		aSketch.GeometricConstraints.AddHorizontalAlign(RadialSketchPoint, OppositeRadialSketchPoint)
		
		aSketch.Solve()
		Exit Sub
	End If
	
	'Create 2 or more additional points
	Dim MemorySketchPoint As SketchPoint = Nothing
	Dim MemoryParameter As Inventor.Parameter = Nothing
	Dim Counting As Integer = 1
	
	Dim angleInRadians As Double = (360/QTY) * (Math.PI / 180)
    Dim cosTheta As Double = Math.Cos(angleInRadians)
    Dim sinTheta As Double = Math.Sin(angleInRadians)
		
	While Counting < QTY
		'StartFresh if no memory
		If MemorySketchPoint Is Nothing Then 
			MemorySketchPoint = RadialSketchPoint
		End If
		
		'Locate new Point
		Dim newPoint As Point2d = MemorySketchPoint.Geometry.Copy()
		newPoint.X = 	(cosTheta * (MemorySketchPoint.Geometry.X - oOriginSketchPoint.Geometry.X) - _
						 sinTheta * (MemorySketchPoint.Geometry.Y - oOriginSketchPoint.Geometry.Y) + oOriginSketchPoint.Geometry.X)
		newPoint.Y = 	(sinTheta * (MemorySketchPoint.Geometry.X - oOriginSketchPoint.Geometry.X) + _
            			 cosTheta * (MemorySketchPoint.Geometry.Y - oOriginSketchPoint.Geometry.Y) + oOriginSketchPoint.Geometry.Y)

		'Create new Points
		Dim newSketchPoint As SketchPoint = aSketch.SketchPoints.Add(newPoint, True)
		
		aSketch.GeometricConstraints.AddCoincident(newSketchPoint, aCircle)
		
		'Prep for TextPoint
		Dim MemoryVector As Vector2d = oOriginSketchPoint.Geometry.VectorTo(MemorySketchPoint.Geometry)
		Dim newVector As Vector2d = oOriginSketchPoint.Geometry.VectorTo(newSketchPoint.Geometry)
		
		MemoryVector.AddVector(newVector)
		MemoryVector.Normalize()
		MemoryVector.ScaleBy(Diameter*.25) 'places @ 50% of radius | .5 would be @ curve | >.5 would be beyond curve
		Dim AngleTextPoint As Point2d = oOriginSketchPoint.Geometry.Copy
		AngleTextPoint.TranslateBy(MemoryVector)
		
		'Array Constraint
		If MemoryParameter Is Nothing
			MemoryParameter = aSketch.DimensionConstraints.AddThreePointAngle(newSketchPoint, oOriginSketchPoint, MemorySketchPoint, AngleTextPoint, True).Parameter
		Else
			aSketch.DimensionConstraints.AddThreePointAngle(newSketchPoint, oOriginSketchPoint, MemorySketchPoint, AngleTextPoint, False).Parameter.Expression = MemoryParameter.Name
		End If 
		
		'Memory
		MemorySketchPoint = newSketchPoint
		Counting +=1
	End While
	
	'Prep for TextPoint
	Dim RememberedVector As Vector2d = oOriginSketchPoint.Geometry.VectorTo(MemorySketchPoint.Geometry)
	Dim RadialVector As Vector2d = oOriginSketchPoint.Geometry.VectorTo(RadialSketchPoint.Geometry)
	
	RememberedVector.AddVector(RadialVector)
	RememberedVector.Normalize()
	RememberedVector.ScaleBy(Diameter*.25) 'places @ 50% of radius | .5 would be @ curve | >.5 would be beyond curve
	Dim LastTextPoint As Point2d = oOriginSketchPoint.Geometry.Copy
	LastTextPoint.TranslateBy(RememberedVector)
	
	'add last dimension
	aSketch.DimensionConstraints.AddThreePointAngle(MemorySketchPoint, oOriginSketchPoint, RadialSketchPoint, LastTextPoint, False).Parameter.Expression = MemoryParameter.Name
	
	']
	
	aSketch.Solve()
End Sub

I maintained the format of the square code discussed earlier so they look similar. 

 

Message 16 of 17

harvey3ELEA
Collaborator
Collaborator

Wonderful stuff, J-Camper.  I can't thank you enough!

Go ahead and add a dinner to that lunch offer!

Harvey

0 Likes
Message 17 of 17

pball
Mentor
Mentor

@J-Camper big thanks for your examples. I learned quite a bit and was able to make a version that makes me quite happy.

Depending on the face selected X and Y can end up backwards to what you might expect, so entering the sketch solves that issue. I was able to make the subroutine adding points to the lines more simple and universal in my opinion. Inputting 1 for hole count will put 1 hole in the center of the horizontal or vertical line, 2 will put points on all corners, inputting more than 2 will put holes on all corners and evenly spaced along the lines.

Do note this code is not full proof and I already noticed that doing 1 horizontal and 2 vertical holes will give an odd result, but I'm not fixing it as inputting 3 horizontal and 2 vertical would give the intended result. Another thing I enjoyed doing was noticing the previous examples were adding 3 points at each line intersection. My newest code should only add 1 point at each location, which doesn't affect the end result. It just feels technically correct. I intend to port this over my VB.net addin where I can create a single dialog to input all of the values and likely add more options like circular hole patterns.

Public Sub Main()
	If (ThisApplication.ActiveEditDocument.DocumentType <> kPartDocumentObject) Then
		MsgBox ("Active item is not a part")
		Exit Sub
	End If
	Dim oPart As PartDocument = ThisApplication.ActiveEditDocument
	Dim oFace As Face
	
	Dim trans As Transaction = ThisApplication.TransactionManager.StartTransaction(oPart, "Add Hole Pattern")
    
	'Prompt to select face to create new sketch
	If (ThisApplication.ActiveDocument.DisplayName = oPart.DisplayName) Then
		'Selection in part document
		oFace = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick Planar Face")
	Else
		'Selection when editing part inside assembly
		Dim oFaceProxy As FaceProxy = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Pick Planar Face")
		oFace = oFaceProxy.NativeObject
	End If
	
	If (oFace Is Nothing) Then Exit Sub
	
	ThisApplication.ActiveDocument.SelectSet.Select(oFace)
	ThisApplication.CommandManager.ControlDefinitions.Item("AppLookAtCmd").Execute

    'Create sketch
    Dim Sketch As PlanarSketch = oPart.ComponentDefinition.Sketches.Add(oFace)

    ' Project the origin point onto the sketch.
    Dim oOriginSketchPoint As SketchPoint = sketch.AddByProjectingEntity(oPart.ComponentDefinition.WorkPoints.Item(1))

	Call Sketch.Edit
	
    'Get size of rectangle
    X = CDbl(InputBox("Horizontal dimension.", "X", "1")) * 2.54
    Y = CDbl(InputBox("Vertical dimension.", "Y", "1")) * 2.54
		
	If (X * Y = 0) Then
		MsgBox("Values cannot be zero")
		Exit Sub
	End If
	
	'Number of holes in each direction
	Xcount = CInt(InputBox("Number of Horizontal holes","X Holes","2"))
	Ycount = CInt(InputBox("Number of Vertical holes", "Y Holes", "2"))
	
    Dim RectangleCorner As Point2d = oOriginSketchPoint.Geometry.Copy
    RectangleCorner.X = RectangleCorner.X + X / 2
    RectangleCorner.Y = RectangleCorner.Y + Y / 2

    ' Draw rectangles by center point.
    Dim RectangleLines As SketchEntitiesEnumerator = sketch.SketchLines.AddAsTwoPointCenteredRectangle(oOriginSketchPoint, RectangleCorner)

    'Add dimensions to two sides of rectangle
    Dim TextPointHorizontal As Point2d = oOriginSketchPoint.Geometry.Copy
    TextPointHorizontal.Y += Y * 0.75
    Dim TextPointVertical As Point2d = oOriginSketchPoint.Geometry.Copy
    TextPointVertical.X += X * 0.75
	
    Dim HorParam As Inventor.Parameter = Sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(3).StartSketchPoint, RectangleLines.Item(3).EndSketchPoint, kAlignedDim, TextPointHorizontal, False).Parameter
    Dim VerParam As Inventor.Parameter = sketch.DimensionConstraints.AddTwoPointDistance(RectangleLines.Item(2).StartSketchPoint, RectangleLines.Item(2).EndSketchPoint, kAlignedDim, TextPointVertical, False).Parameter
    
    'Add center points four corners of rectangle
    Dim skLine As SketchLine
    For Each skLine In RectangleLines.oftype(Of SketchLine)
			If (skLine.StartSketchPoint.Geometry.Y = skLine.EndSketchPoint.Geometry.Y) Then
				AddPoints(Sketch,skLine,Xcount,HorParam)
			ElseIf (skLine.StartSketchPoint.Geometry.X = skLine.EndSketchPoint.Geometry.X) Then
				AddPoints(Sketch,skLine,Ycount,VerParam)
			End If
    Next
    
    Call sketch.Solve
	Call Sketch.ExitEdit
    trans.End
		
    ThisApplication.CommandManager.ControlDefinitions.Item("PartDMHoleCmd").Execute
End Sub

Private Sub AddPoints(Sketch As PlanarSketch, sKLine As SketchLine, HCount As Integer, DimParam As Inventor.Parameter)
	If (HCount = 1) Then
		Sketch.GeometricConstraints.AddMidpoint(Sketch.SketchPoints.Add(sKLine.StartSketchPoint.Geometry.Copy), sKLine)
	Else
		sKLine.StartSketchPoint.HoleCenter = True
		If (HCount > 2) Then
			Dim StartPoint As SketchPoint = sKLine.StartSketchPoint
			For Hc = 3 To HCount
				Dim TranVect As Vector2d = skLine.Geometry.Direction.AsVector
				TranVect.ScaleBy(CDbl(DimParam.Value) / (HCount - 1))
				'StartPoint.TranslateBy(TranVect) 
				Dim NewPoint2D As Point2d = StartPoint.Geometry.Copy
				NewPoint2D.TranslateBy(TranVect) 
				
				Dim NewPoint As SketchPoint = Sketch.SketchPoints.Add(NewPoint2D, True)
				Sketch.GeometricConstraints.AddCoincident(NewPoint, sKLine)
				
				TranVect.ScaleBy(.5)
				Dim SketchTextPoint As Point2d = StartPoint.Geometry.Copy
				SketchTextPoint.X +=  TranVect.X + (TranVect.Y * .75)
				SketchTextPoint.Y +=  TranVect.Y + (TranVect.X * .75)
				
				Sketch.DimensionConstraints.AddTwoPointDistance(StartPoint,NewPoint,kaligneddim,SketchTextPoint,False)
				
				StartPoint = NewPoint
			Next
		End If
	End If
End Sub

 

Check out my style edits for the Autodesk forums
pball's Autodesk Forum Style

Userscript to edit forum links to jump to first unread post
Jump To First Post Userscript