Wrap to Surface API Implementation

Wrap to Surface API Implementation

AlexFielder
Advisor Advisor
2,457 Views
16 Replies
Message 1 of 17

Wrap to Surface API Implementation

AlexFielder
Advisor
Advisor

Hi all,

 

I have recently been looking into the above and it seems that despite there being API implementations for project along Vector and Project To Closest Point, there is nothing available for Wrap to surface.

 

The best information I could find is this post from a while back by @Anonymous: but since he's off doing all-things-Forge these days I have needed to cobble together my own implementation:

 

private static void createGeomForHolePositions()
        {
            try
            {
#if DEBUG
                ClientGraphics debuggingGraphics = null;
                try
                {
                    debuggingGraphics = partCompDef.ClientGraphicsCollection["debuggingGraphics"];
                }
                catch (Exception)
                {
                    debuggingGraphics = partCompDef.ClientGraphicsCollection.Add("debuggingGraphics");
                }
#endif
                new3DSketch = partCompDef.Sketches3D.Add();

                ObjectCollection objCollection = partDoc.AttributeManager.FindObjects("RadialHole", "HolePositionX");
                for (int i = 1; i < objCollection.Count + 1; i++)
                {
                    if(objCollection[i] is SketchPoint)
                    {
                        SketchPoint skpoint = (SketchPoint)objCollection[i];
                        AttributeSet AttSet = skpoint.AttributeSets[1];
                        Inventor.Attribute holeName = AttSet["HoleName"];
                        string ThisHoleName = holeName.Value;
                        Inventor.Attribute xPosAtt = AttSet["HolePositionX"];
                        double xPosition = xPosAtt.Value;
                        Inventor.Attribute yPosAtt = AttSet["HolePositionY"];
                        double yPosition = yPosAtt.Value;
                        Inventor.Point tmpOriginPoint = transGeom.CreatePoint(0, yPosition, 0);
                        Inventor.Point tmpWPPoint = null;
                        UnitVector tmpXAxis = null;
                        UnitVector tmpYAxis = null;
                        UnitVector cylinderNormal = null;

                        selectedWorkPlane.GetPosition(out tmpWPPoint, out tmpXAxis, out tmpYAxis);
                        double radius = selectedFace.Geometry.Radius;
                        double pi = Math.PI;
                        double circumference = ((2 * pi) * radius);
                        double arcLength = xPosition;
                        double arcAngle = (arcLength / ((2 * radius) * pi)) * 360;
                        //default vectors
                        UnitVector xPositive = transGeom.CreateUnitVector(1, 0, 0);
                        UnitVector xNegative = transGeom.CreateUnitVector(-1, 0, 0);
                        UnitVector yPositive = transGeom.CreateUnitVector(0, 1, 0);
                        UnitVector yNegative = transGeom.CreateUnitVector(0, -1, 0);
                        UnitVector zPositive = transGeom.CreateUnitVector(0, 0, 1);
                        UnitVector zNegative = transGeom.CreateUnitVector(0, 0, -1);

                        //this needs more work in case things aren't quite perpendicular to the origin axes...
                        // or for occasions when the part is modelled in a different direction.
                        if (tmpXAxis.IsParallelTo(xPositive))
                        {
                            cylinderNormal = xPositive;
                        }
                        else if (tmpXAxis.IsParallelTo(yPositive))
                        {
                            cylinderNormal = yPositive;
                        }
                        else
                        {
                            cylinderNormal = zPositive;
                        }

                        Arc3d tmpArc = transGeom.CreateArc3d(tmpOriginPoint, cylinderNormal, selectedWorkPlane.Plane.Normal, radius, 0, (arcAngle * (pi / 180)));
#if DEBUG
                        GraphicsNode graphicsNode = debuggingGraphics.AddNode(1);
                        CurveGraphics curveGraphics2 = graphicsNode.AddCurveGraphics(tmpArc);
#endif
                        RadialHoleDefinition holeDef = (from RadialHoleDefinition hole in radialHoles
                                                       where hole.HoleName == ThisHoleName
                                                       select hole).FirstOrDefault();
                        if(holeDef?.HoleName.Length > 0)
                        {
                            Inventor.Point tmpPoint = tmpArc.EndPoint;
                            WorkPoint newWorkPoint = partCompDef.WorkPoints.AddFixed(tmpPoint, false);
                            newWorkPoint.Name = ThisHoleName;
                            newWorkPoint.Visible = false;
                            holeDef.HoleWorkPoint = newWorkPoint;
                            SurfaceBody CylinderSurface = selectedFace.SurfaceBody;
                            Sketch3D tmpSketch3D = partCompDef.Sketches3D.Add();
                            SketchPoint3D tmpSketchPt3d = tmpSketch3D.SketchPoints3D.Add(tmpPoint);
                            WorkAxis newWorkAxis = partCompDef.WorkAxes.AddByNormalToSurface(selectedFace, tmpSketchPt3d);
                            newWorkAxis.Name = "Work Axis: " + ThisHoleName;
                            newWorkAxis.Visible = false;
                            holeDef.HoleWorkAxis = newWorkAxis;
                            tmpSketch3D.Delete();
                        }
                        else
                        {
                            log.Error("One of the HoleDefinitions is incomplete.");
                            reporter.UpdateStatusBar("One of the HoleDefinitions is incomplete, check the spreadsheet and run again!");
                        }
                        RadialHoles.m_InventorApp.ActiveView.Update();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }


            //new3DSketch.curves
        }

 

Is there an API method I have overlooked that simplifies the above?

 

Thanks,

 

Alex.

 

 

PS. Another minor issue is that currently my method above ONLY works on cylindrical surfaces and doesn't create a link between the SketchPoint objects and WorkPoints it creates; because of the lack of a link I think that it could probably be massively simplified forgoing the use of Attributes and AttributeSets (which have their own special ways to trip you up...)

0 Likes
2,458 Views
16 Replies
Replies (16)
Message 2 of 17

wayne.brill
Collaborator
Collaborator

Hi Alex,

 

I do not have anything to suggest after looking at your code and I believe there is not any API method that directly wraps a curve to a surface like the UI can do.

 

Could you explain more about what part of the code you are trying to simplify? Also a description of the workflow that the user would take and what the code is doing may help.  I see a WorkPoint and a WorkAxis being created but I am not seeing where a curve is being created on a surface.

 

This post seems related but not sure if it will help:

http://modthemachine.typepad.com/my_weblog/2016/06/projecting-points-onto-a-solid.html

 

Thanks,

Wayne

 

 



Wayne Brill
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 3 of 17

AlexFielder
Advisor
Advisor

Hi Wayne,

 

(Wall-of-text follows)

 

It was really just a question of seeing whether there is any effort underway to allow access to an API version of the wrap to surface tool available inside 3D sketches - which you have said doesn't exist (yet?). 😞

 

When I look at the manual way of doing it, I can see that the created 3D Sketch points are grouped into one feature which obviously updates should the source geometry change.

 

Thinking about it further, I would need to do similar in order to have my points update should the source information be updated. For the time being, I have the tool create a 2D sketch that contains the hole positions from a spreadsheet (see below) but there's no link between that any of the SketchPoint3D objects created after that so it could be misleading to the user.

 

The (manual) workflow this is required to replace is this:

 

  • User has a cylindrical tube that requires lots (possibly 100s) of radial holes
  • User creates a spreadsheet with X & Y hole positions, sizes and names like this:

2017-04-04 08_49_30-test points.xlsx - Excel.png

  • User creates a 2D sketch on a tangential workplane and imports data into it as a series of sketch points
  • User creates a 3D Sketch and uses Wrap to surface command to create multiple SketchPoint3D objects
  • User then creates workpoints at each SketchPoint3D <= one of the most time consuming parts as there is no "group select" available...?
  • User creates Work axes normal to cylindrical surface using each workpoint location as a reference
  • Finally, the User runs the "hole on point" feature to create a hole using the size information and name above

All-told, creating even 15 holes using the above workflow takes about ~30 minutes.

 

My initial implementation of the addin can do all of that in <=1 minute:

 

(There is a weird delay sometimes when opening the accompanying Excel file using Excel 2016 on my system, but that's a topic for another thread I think!)

 

I guess the instruction will be simply "If you need to update the holes after having run the addin, you will need to move the EOP marker, delete everything below and re-run" which of course would screw up any geometry created after the tool is run.

 

Unless of course you can show me how to link the wrapped SketchPoint3D objects to the Excel data or perhaps to the 2D sketch points I'm currently creating?

 

To counter this flaw I suppose I could split the functionality:

 

  1. Automate the point import to create the 2D Sketch & SketchPoints.
  2. Have the customer create a 3D Sketch and then use the built-in Wrap to surface function to create the SketchPoint3D objects linked to 1).
  3. Use the API's SelectionFilterEnum.kSketch3DPointFilter inside of the CommandManager.Pick() command to have the user create a collection of points based on 2) above.
  4. Take that collection of points and create at each location Workpoints, workaxes and holes the same as above video.

 I guess there is no way of providing selectset(s) into the UI's existing tools? (I'm thinking the previously-selected cylindrical face and the newly created SketchPoints in the case of the Wrap-to-Surface command)

 

Thanks,

 

Alex.

0 Likes
Message 4 of 17

wayne.brill
Collaborator
Collaborator

Hi Alex,

 

I vote for splitting the workflow and using the built-in Wrap to surface function.

 

If the face and the points are selected they should be used by the command. ("Sketch3DProjectCmd") Your code could select them with the Document.SelectSet.Select method and run the command. The user would just have to click "Wrap to Surface" and "Ok".  Below is VBA code I tested this with.

 

I created this ticket with Inventor Engineering:

"Need an API that does what Wrap to Surface in the UI Does"

 

 

'The part just had a cylinder and the sketch had some sketch points. The cylinder face and the sketch points are selected by code. The command is run and it uses the face and points. 

Public Sub Test()
    Dim odoc As PartDocument
    Set odoc = ThisApplication.ActiveDocument

    Dim oDef As PartComponentDefinition
    Set oDef = odoc.ComponentDefinition
   
    Dim oSketch As PlanarSketch
    Set oSketch = oDef.Sketches(2)
   
    Dim oSkPnt As SketchPoint
    For Each oSkPnt In oSketch.SketchPoints
        Call odoc.SelectSet.Select(oSkPnt)
    Next oSkPnt
    
    Dim oFace As Face
    Set oFace = oDef.SurfaceBodies(1).Faces(1)
    Call odoc.SelectSet.Select(oFace)
   
    Dim oControlDef As ControlDefinition
    Call oControlDef.Execute

End Sub

 

 

Thanks,

Wayne



Wayne Brill
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 5 of 17

AlexFielder
Advisor
Advisor

Hi Wayne,

 

That's great, thank you! 

 

(I will reply to your engineering ticket email later today!)

 

In the meantime, I can have my addin import the Excel data, create the necessary sketches and sketchpoints and the Wrap to Surface tool runs correctly.

 

My conundrum now is how to immediately resume my add-in function once that completes; I guess I could have an event set up for either OnActivateCommand or OnTerminateCommand.

 

The problem there is that if I check for either in relation to the "Sketch3DProjectCmd" it could cause my addin to run if/when the user runs that tool manually.

 

Is there a way of allowing my addin to duck in/duck out of process* in the same way a modal window locks focus whilst it is open?

 

NinjEdit: I was able to answer my own question by using the ControlDefinition.Execute2(true) method.

 

Also, I notice that despite having the Event Watcher running when I clicked on my Ribbon button, it doesn't register it as an OnActivateCommand event - should it?

 

Thanks,

 

Alex.

 

 

0 Likes
Message 6 of 17

AlexFielder
Advisor
Advisor

And now for my next question:

 

Because there is no exposed method for creating and therefore(?) accessing the WrapToSurface object, I seem to be unable to identify the referenced SketchPoint using the following code:

 

ObjectCollection objCollection = partDoc.AttributeManager.FindObjects("RadialHole", "HolePositionX");
            ObjectCollection sketchPointsColl = RadialHoles.m_InventorApp.TransientObjects.CreateObjectCollection();
            for (int i = 1; i < objCollection.Count + 1; i++)
            {
                if (objCollection[i] is SketchPoint)
                {
                    //may need to cast this to a temporary object to prevent errors?
                    SketchPoint tmpSketchPoint = objCollection[i];
                    sketchPointsColl.Add(tmpSketchPoint);
                }
            }
            partDoc.SelectSet.SelectMultiple(sketchPointsColl);
            partDoc.SelectSet.Select(selectedFace);

            ControlDefinition Sketch3DWrapToSurface = RadialHoles.m_InventorApp.CommandManager.ControlDefinitions["Sketch3DProjectCmd"];
            //.Execute2(true) means we can continue afterwards!
            Sketch3DWrapToSurface.Execute2(true);
            if(new3DSketch.SketchPoints3D.Count > 0)
            {
                foreach (SketchPoint3D item in new3DSketch.SketchPoints3D)
                {
                    /*next line returns null; the item.reference property is true but item.ReferencedEntity = null
                    */
                    SketchPoint referencedSkPoint = (from SketchPoint skp in sketchPointsColl
                                                     where item.ReferencedEntity == skp
                                                     select skp).FirstOrDefault();

Looks like I will need to create transient geometry points in the same way I did before, store their X,Y,Z coordinates and then compare those locations to each wrapped SketchPoint3D to identify the correct location and it's resultant hole information (size, name etc.).

 

Unless there's a method for querying the original SketchPoint objects to see what they are referenced by?

 

Cheers,

 

Alex.

0 Likes
Message 7 of 17

wayne.brill
Collaborator
Collaborator

Hi Alex,

 

I am able to recreate the behavior where ReferencedEntity property is nothing for SketchPoint3D. I am not finding a way to get the SketchPoint objects that are referenced by the SketchPoint3D they were projected from.

 

I logged this ticket with Inventor Engineering:

"ReferencedEntity is nothing for SketchPoint3D created by “Project to Surface” with “Wrap to Surface”"

 

 

Thanks,

Wayne



Wayne Brill
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 8 of 17

AlexFielder
Advisor
Advisor

Hi Wayne,

 

That's great, thanks.

 

I did solve this using the method I described earlier in the thread such that the tool now runs as so:

 

  1. The user clicks the ribbon button
  2. The user waits whilst Excel opens and collects the necessary data - I may swap Excel for something else (json or XML perhaps); it depends on the customer really.
  3. The user selects an exterior Cylindrical surface (outside of the tube)
  4. The user selects an interior Cylindrical surface (inside of the tube)
  5. The user selects a tangential work plane
  6. The user selects a work axis to drive the "X" direction

Once these selections are in place, the code continues by making a sketch containing our 2D locations, before creating a 3D sketch and then firing the built-in Wrap to Surface command. Once that happens the code waits for the user to select the Wrap to Surface option and click continue (as per your earlier suggestion, so thanks for that!).

 

With this selection complete and the necessary inputs filtered to our SelectSet, Inventor creates the resultant 3D Sketch points that retain a "normal" link (albeit without the exposed ReferencedEntity information) to the original 2D Sketch.

 

When this is complete we quickly create the same transient points ourselves and then run a comparison between each 3D Sketch point geometry and the transient point (within a tolerance) to determine which hole goes where.

 

Once the comparison is complete, a series of work points and normal-to-surface work axes (at those points) are created, renamed and stored for later use by the hole creation method.

 

Overall, I'm really happy with the resultant tool-set.

 

As a worst-case stress test I built a spreadsheet that allowed me to create 500 holes using this tool in around 30-35 minutes. I think that could probably be sped up by removing a few view.updates I have dotted around though. (Unless you have a better suggestion?)

 

The difficulty in doing that is that the user may be inclined to think that Inventor has stopped responding if there's no on-screen activity for an extended period.

 

One thing I'm not checking for currently is a situation where the X position value (from 0) of any hole is greater than the circumference of the destination cylindrical face; I'm pretty sure that the Wrap to surface command supports this but from the limited testing I have carried out so far, the transient geometry method I have (drawing an arc with an angle) doesn't allow you to have an arc whose angle is > 360°. And frankly why should it.

 

Thanks again,

 

Alex.

0 Likes
Message 9 of 17

AlexFielder
Advisor
Advisor

Hi @wayne.brill,

 

I realise it's been a while since we last spoke on this.

 

Has there been any movement on the tickets you mentioned? (Apologies if there has and I've missed a notification or something)

 

Thanks,

 

Alex.

0 Likes
Message 10 of 17

xiaodong_liang
Autodesk Support
Autodesk Support

Hi Alex,

 

Are you checking the issue Wayne logged?  'ReferencedEntity is nothing for SketchPoint3D created by “Project to Surface” with “Wrap to Surface”'

 

It seems Wayne did not make a note on the ticket number. I am asking engineer team about this. 

 

 

 

 

0 Likes
Message 11 of 17

xiaodong_liang
Autodesk Support
Autodesk Support

I got the ticket number now:  INVGEN-2946. While our expert has commented it as designed. Hope it helps to explain the issue in this thread.

 

This is the API Help description:
SketchPoint3D.ReferencedEntity Property

Parent Object: SketchPoint3D

 

Property that returns the object this entity is dependent on. When sketch entities are created by projecting model edges or intersecting the model, the resulting entities are driven by the original model entities and cannot be modified. This property returns the model entity the sketch entity is dependent on. The Reference property indicates whether the sketch entity is driven by a model entity or not. If the sketch entity is not referencing a model entity, this property will return Nothing. This property can also return nothing even when the sketch entity is referencing a model entity in the case where the model entity has been consumed by some subsequent modeling operation.

0 Likes
Message 12 of 17

AlexFielder
Advisor
Advisor

Hi @xiaodong_liang, that is one of the issues I was checking up on. I guess nothing has changed on that.

 

The main issue however is the inability of the API to mimic what you can manually create in terms of the Wrap to Surface tool.

 

I have the basis of a working solution as I stated in my previous post here:

 

https://forums.autodesk.com/t5/inventor-customization/wrap-to-surface-api-implementation/m-p/7011353...

 

I just wondered if that functionality had been looked at in the time since that post.

 

 

I would prefer to know it's missing (from the API) than miss that it has been added in the interim.

 

Thanks,

 

Alex.

0 Likes
Message 13 of 17

xiaodong_liang
Autodesk Support
Autodesk Support

Hi Alex,

 

my apology for my late response. 

 

I found the wish INVGEN-5343 'As a user, I need an API that does what Wrap to Surface in the UI Does' which is logged exactly on behalf of you. Sorry, however I do not see any status with this wish. I added one more vote to the wish, but I cannot guarantee when the engineer team would start to address as this depends on the wish priority. Thank you for your understanding..

Message 14 of 17

AlexFielder
Advisor
Advisor

HI @xiaodong_liang,

 

Thanks for taking the time to look into this.

 

Like I have stated previously, the lack of this as a function within the API hasn't prevented me from automating around it, it just means a couple more clicks for the user.

 

Hopefully one day it'll be added.

0 Likes
Message 15 of 17

AlexFielder
Advisor
Advisor

Hi All,

 

I know it's been a while, but, start of a new decade and all, maybe this will get added finally?

Maybe it's already been added..? (How DO I check the INVGEN-2946 & INVGEN-5343 ticket statuses? - can I even check their status?)

 

Thanks,

 

Alex.

0 Likes
Message 16 of 17

johnsonshiue
Community Manager
Community Manager

Hi Alex,

 

I check the status of the two reported issues on our internal tracking system. Unfortunately, it is not yet resolved. The API has not yet been added based on the current status.

I have read the entire thread. It is unclear to me the priority of the request, compared to other requests. Please feel free to approach me directly (johnson.shiue@autodesk.com) if you would like to elaborate the urgency.

Many thanks and Happy New Year!

 

 

 



Johnson Shiue (johnson.shiue@autodesk.com)
Software Test Engineer
Message 17 of 17

johnsonshiue
Community Manager
Community Manager

Hi Alex,

 

I just got an update from the project team. The 3D Sketch Wrap-to-Surface API is indeed work in progress. Please sign up Inventor Beta (https://bit.ly/InventorBeta) to access Inventor Beta build.

Many thanks!



Johnson Shiue (johnson.shiue@autodesk.com)
Software Test Engineer
0 Likes