Hi all,
I'm working through a problem and wanted to check I hadn't missed something obvious within the API.
When working with the built-in tools manually, you are occasionally presented with a "direction" arrow within the UI:
These are client graphics I believe and I have found the following article useful:
But I have an issue and that is that I need to create a version of the arrow that can be flipped about a selected axis.
Is there something I am missing within the API that can do this for me or is it a manual task of creating/recreating the transient geometry as required?
here is a c# method I have cobbled together that takes several inputs I thought may be needed:
public class ClientGFX { private static readonly ILog log = LogManager.GetLogger(typeof(Parameters)); public static void ClientGraphics3DPrimitives(string clientGraphicsCollectionId, Application InventorApp, PartComponentDefinition compDef, Point origin, Point end, Line centreline, UnitVector arrowDirection) { try { Document oDoc = InventorApp.ActiveDocument; // Set a reference to component definition of the active document. // This assumes that a part or assembly document is active PartComponentDefinition oCompDef = compDef; // Check to see if the test graphics data object already exists. // If it does clean up by removing all associated of the client // graphics from the document. If it doesn't create it ClientGraphics oClientGraphics = null; try { oClientGraphics = oCompDef.ClientGraphicsCollection[clientGraphicsCollectionId]; } catch (Exception ex) { // An existing client graphics object was successfully // obtained so clean up oClientGraphics.Delete(); // Update the display to see the results InventorApp.ActiveView.Update(); log.Debug(ex.Message, ex); } finally { TransientGeometry oTransGeom = InventorApp.TransientGeometry; // Create the ClientGraphics object. if (oClientGraphics == null) { oClientGraphics = oCompDef.ClientGraphicsCollection.Add(clientGraphicsCollectionId); } // Create a new graphics node within the client graphics objects GraphicsNode oSurfacesNode = oClientGraphics.AddNode(1); TransientBRep oTransientBRep = InventorApp.TransientBRep; // Create a point representing the center of the bottom of // the cone Point coneBottom = origin; //Point coneBottom = InventorApp.TransientGeometry.CreatePoint(0, 0, 0); // Create a point representing the tip of the cone //Point oTop = end; Point coneTop = InventorApp.TransientGeometry.CreatePoint(0, 10, 0); // Create a point representing the base of the cylinder Point cylinderBottom = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); //sort out the direction we need to point. Matrix conePos = InventorApp.TransientGeometry.CreateMatrix(); Vector conePosVector = InventorApp.TransientGeometry.CreateVector(arrowDirection.X, arrowDirection.Y, arrowDirection.Z); conePos.SetTranslation(conePosVector); conePos.SetToRotateTo(coneTop.VectorTo(coneBottom), conePosVector); //move the necessary points coneTop.TransformBy(conePos); cylinderBottom.TransformBy(conePos); // Create a transient cone body //SurfaceBody oBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 5, 5, 0); SurfaceBody oBody = oTransientBRep.CreateSolidCylinderCone(coneBottom, coneTop, 5, 5, 0); // Reset the top point indicating the center of the top of // the cylinder //oTop = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); coneTop = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); // Create a transient cylinder body //SurfaceBody oCylBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 2.5, 2.5, 2.5); SurfaceBody oCylBody = oTransientBRep.CreateSolidCylinderCone(coneBottom, cylinderBottom, 2.5, 2.5, 2.5); // Union the cone and cylinder bodies oTransientBRep.DoBoolean(oBody, oCylBody, BooleanTypeEnum.kBooleanTypeUnion); // Create client graphics based on the transient body SurfaceGraphics oSurfaceGraphics = oSurfacesNode.AddSurfaceGraphics(oBody); // Update the view to see the resulting curves InventorApp.ActiveView.Update(); } } catch (Exception ex) { log.Error(ex.Message, ex); } } }
I think perhaps I have misunderstood the Matrix translation required in this instance.
Any pointers will be gratefully received!
Thanks,
Alex.
Hi all,
I'm working through a problem and wanted to check I hadn't missed something obvious within the API.
When working with the built-in tools manually, you are occasionally presented with a "direction" arrow within the UI:
These are client graphics I believe and I have found the following article useful:
But I have an issue and that is that I need to create a version of the arrow that can be flipped about a selected axis.
Is there something I am missing within the API that can do this for me or is it a manual task of creating/recreating the transient geometry as required?
here is a c# method I have cobbled together that takes several inputs I thought may be needed:
public class ClientGFX { private static readonly ILog log = LogManager.GetLogger(typeof(Parameters)); public static void ClientGraphics3DPrimitives(string clientGraphicsCollectionId, Application InventorApp, PartComponentDefinition compDef, Point origin, Point end, Line centreline, UnitVector arrowDirection) { try { Document oDoc = InventorApp.ActiveDocument; // Set a reference to component definition of the active document. // This assumes that a part or assembly document is active PartComponentDefinition oCompDef = compDef; // Check to see if the test graphics data object already exists. // If it does clean up by removing all associated of the client // graphics from the document. If it doesn't create it ClientGraphics oClientGraphics = null; try { oClientGraphics = oCompDef.ClientGraphicsCollection[clientGraphicsCollectionId]; } catch (Exception ex) { // An existing client graphics object was successfully // obtained so clean up oClientGraphics.Delete(); // Update the display to see the results InventorApp.ActiveView.Update(); log.Debug(ex.Message, ex); } finally { TransientGeometry oTransGeom = InventorApp.TransientGeometry; // Create the ClientGraphics object. if (oClientGraphics == null) { oClientGraphics = oCompDef.ClientGraphicsCollection.Add(clientGraphicsCollectionId); } // Create a new graphics node within the client graphics objects GraphicsNode oSurfacesNode = oClientGraphics.AddNode(1); TransientBRep oTransientBRep = InventorApp.TransientBRep; // Create a point representing the center of the bottom of // the cone Point coneBottom = origin; //Point coneBottom = InventorApp.TransientGeometry.CreatePoint(0, 0, 0); // Create a point representing the tip of the cone //Point oTop = end; Point coneTop = InventorApp.TransientGeometry.CreatePoint(0, 10, 0); // Create a point representing the base of the cylinder Point cylinderBottom = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); //sort out the direction we need to point. Matrix conePos = InventorApp.TransientGeometry.CreateMatrix(); Vector conePosVector = InventorApp.TransientGeometry.CreateVector(arrowDirection.X, arrowDirection.Y, arrowDirection.Z); conePos.SetTranslation(conePosVector); conePos.SetToRotateTo(coneTop.VectorTo(coneBottom), conePosVector); //move the necessary points coneTop.TransformBy(conePos); cylinderBottom.TransformBy(conePos); // Create a transient cone body //SurfaceBody oBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 5, 5, 0); SurfaceBody oBody = oTransientBRep.CreateSolidCylinderCone(coneBottom, coneTop, 5, 5, 0); // Reset the top point indicating the center of the top of // the cylinder //oTop = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); coneTop = InventorApp.TransientGeometry.CreatePoint(0, -40, 0); // Create a transient cylinder body //SurfaceBody oCylBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 2.5, 2.5, 2.5); SurfaceBody oCylBody = oTransientBRep.CreateSolidCylinderCone(coneBottom, cylinderBottom, 2.5, 2.5, 2.5); // Union the cone and cylinder bodies oTransientBRep.DoBoolean(oBody, oCylBody, BooleanTypeEnum.kBooleanTypeUnion); // Create client graphics based on the transient body SurfaceGraphics oSurfaceGraphics = oSurfacesNode.AddSurfaceGraphics(oBody); // Update the view to see the resulting curves InventorApp.ActiveView.Update(); } } catch (Exception ex) { log.Error(ex.Message, ex); } } }
I think perhaps I have misunderstood the Matrix translation required in this instance.
Any pointers will be gratefully received!
Thanks,
Alex.
Thinking about this overnight (in the car on the way home!) I might not need to do this after all - not that doing it in the future wouldn't be handy!
I have the following example component:
The selections for which are as follows:
Given that I select the end face:
This essentially gives me the Y axis for the sketch I need to create tangentially to the outer face.
I'm sure I have seen in recent days an example of how to get the x/y/z axes when presented with another perpendicular vector/axis.
Does anyone have an example of getting the x axis given a Y Direction (UnitVector or Face Normal)
Thanks,
Alex.
Thinking about this overnight (in the car on the way home!) I might not need to do this after all - not that doing it in the future wouldn't be handy!
I have the following example component:
The selections for which are as follows:
Given that I select the end face:
This essentially gives me the Y axis for the sketch I need to create tangentially to the outer face.
I'm sure I have seen in recent days an example of how to get the x/y/z axes when presented with another perpendicular vector/axis.
Does anyone have an example of getting the x axis given a Y Direction (UnitVector or Face Normal)
Thanks,
Alex.
Hi @AlexFielder,
The following blog would be helpful which talks about face normal.
Thanks and regards,
Hi @AlexFielder,
The following blog would be helpful which talks about face normal.
Thanks and regards,
Thanks @chandra.shekar.g,
I figured it out in the end with the following:
private static void CreateSketchForPoints() { try { if (selectedFace != null && selectedWorkPlane != null) { CreateCylinderDatumPoint(); originWP = partCompDef.WorkPoints[1]; newSketch = partCompDef.Sketches.Add(selectedWorkPlane); newSketch.Name = "Sketch: Imported Excel Points"; newSketch.OriginPoint = datumWorkPoint; //selectedAxis.GetSize(out Inventor.Point axisOrigin, out Inventor.Point axisEnd); //selectedWorkPlane.GetPosition(out Inventor.Point wpOrigin, out UnitVector wpXAxis, out UnitVector wpYAxis); Plane selectedFacePlane = selectedEndFace.Geometry; //the cylindernormal is the reverse normal of the selectedEndFace. cylinderNormal = TransGeom.CreateUnitVector(-selectedFacePlane.Normal.X, -selectedFacePlane.Normal.Y, -selectedFacePlane.Normal.Z); Vector newVector = TransGeom.CreateVector(cylinderNormal.X, cylinderNormal.Y, cylinderNormal.Z); //Cylinder cylinder = selectedFace.Geometry; //newSketch.AxisEntity = cylinder.AxisVector; newSketchYAxis = partCompDef.WorkAxes.AddByRevolvedFace(selectedFace); newSketchYAxis.Name = "Axis: Imported Excel Points Y"; newSketch.AxisEntity = newSketchYAxis; newSketch.AxisIsX = false; //NaturalAxisDirection defaults to true so only change it if we need to. if (!newSketchYAxis.Line.Direction.IsEqualTo(cylinderNormal, HoleTolerance)) { newSketch.NaturalAxisDirection = false; } foreach (SketchPoint sketchPoint in newSketch.SketchPoints) { if (sketchPoint.ReferencedEntity == datumWorkPoint) { OriginSketchPoint = sketchPoint; break; } } if (OriginSketchPoint == null) { OriginSketchPoint = (SketchPoint)newSketch.AddByProjectingEntity(datumWorkPoint); // partCompDef.WorkPoints[1]); } } } catch (Exception ex) { log.Error(ex.Message); } }
I also had to do some Matrix translations/rotations to get the points going in the correct orientation:
private static void CreateGeomForHolePositionComparisons() { try { //#if DEBUG // ClientGraphics debuggingGraphics = null; // try // { // debuggingGraphics = partCompDef.ClientGraphicsCollection["debuggingGraphics"]; // if (debuggingGraphics != null) // { // //delete the existing graphics // debuggingGraphics.Delete(); // //and then add new ones. // debuggingGraphics = partCompDef.ClientGraphicsCollection.Add("debuggingGraphics"); // } // } // catch (Exception) // { // debuggingGraphics = partCompDef.ClientGraphicsCollection.Add("debuggingGraphics"); // } //#endif ObjectCollection objCollection = PartDoc.AttributeManager.FindObjects("RadialHole", "HolePositionX"); originWP = partCompDef.WorkPoints[1]; double[] endfaceParams = new double[2]; double[] endFaceNormals = new double[3]; endfaceParams[0] = 0; endfaceParams[1] = 0; selectedEndFace.Evaluator.GetNormal(endfaceParams, endFaceNormals); Plane selectedFacePlane = selectedEndFace.Geometry; selectedFacePlane.Evaluator.GetNormal(endfaceParams, endFaceNormals); selectedWorkPlane.GetPosition(out Inventor.Point tmpWPPoint, out UnitVector tmpXAxis, out UnitVector tmpYAxis); double percent = 0; double progress = 0; for (int i = 1; i < objCollection.Count + 1; i++) { if (objCollection[i] is SketchPoint skpoint) { percent = (progress / objCollection.Count); Reporter.UpdateStatusBar(percent, "Creating 3D Points for comparison with Sketch Points."); AttributeSet AttSet = skpoint.AttributeSets[1]; Inventor.Attribute xPosAtt = null; double xPosition = 0; Inventor.Attribute yPosAtt = null; double yPosition = 0; xPosAtt = AttSet["HolePositionX"]; xPosition = Convert.ToDouble(xPosAtt.Value); yPosAtt = AttSet["HolePositionY"]; yPosition = Convert.ToDouble(yPosAtt.Value); Inventor.Attribute holeName = AttSet["HoleName"]; string ThisHoleName = holeName.Value.ToString(); //creates a basic point for translation. Inventor.Point tmpOriginPoint = TransGeom.CreatePoint(0, yPosition, datumWorkPoint.Point.Z); Matrix originMatrix = TransGeom.CreateMatrix(); Matrix destinationMatrix = TransGeom.CreateMatrix(); originMatrix.SetTranslation(originWP.Point.VectorTo(datumWorkPoint.Point)); Vector originYVector = TransGeom.CreateVector(0, 1, 0); originMatrix.SetToRotateTo(originYVector, cylinderNormal.AsVector()); tmpOriginPoint.TransformBy(originMatrix); tmpOriginPoint.TranslateBy(originWP.Point.VectorTo(datumWorkPoint.Point)); //Inventor.Point tmpOriginPoint = TransGeom.CreatePoint(datumWorkPoint.Point.X, yPosition, datumWorkPoint.Point.Z); double radius = selectedFace.Geometry.Radius; double pi = Math.PI; double circumference = ((2 * pi) * radius); double arcLength = xPosition; double arcAngle = (arcLength / ((2 * radius) * pi)) * 360; Arc3d tmpArc = null; 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) { holeDef.ComparisonPoint = tmpArc.EndPoint; } 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(); progress++; } } } catch (Exception ex) { log.Error(ex.Message); } //new3DSketch.curves }
So I'm pretty happy with the results so far.
Like I said earlier though, it would still be nice to figure out how to create a flip-able direction arrow - something I'm fairly confident I can do given that Matrices don't seem quite as challenging now the above is working.
Thanks,
Alex.
Thanks @chandra.shekar.g,
I figured it out in the end with the following:
private static void CreateSketchForPoints() { try { if (selectedFace != null && selectedWorkPlane != null) { CreateCylinderDatumPoint(); originWP = partCompDef.WorkPoints[1]; newSketch = partCompDef.Sketches.Add(selectedWorkPlane); newSketch.Name = "Sketch: Imported Excel Points"; newSketch.OriginPoint = datumWorkPoint; //selectedAxis.GetSize(out Inventor.Point axisOrigin, out Inventor.Point axisEnd); //selectedWorkPlane.GetPosition(out Inventor.Point wpOrigin, out UnitVector wpXAxis, out UnitVector wpYAxis); Plane selectedFacePlane = selectedEndFace.Geometry; //the cylindernormal is the reverse normal of the selectedEndFace. cylinderNormal = TransGeom.CreateUnitVector(-selectedFacePlane.Normal.X, -selectedFacePlane.Normal.Y, -selectedFacePlane.Normal.Z); Vector newVector = TransGeom.CreateVector(cylinderNormal.X, cylinderNormal.Y, cylinderNormal.Z); //Cylinder cylinder = selectedFace.Geometry; //newSketch.AxisEntity = cylinder.AxisVector; newSketchYAxis = partCompDef.WorkAxes.AddByRevolvedFace(selectedFace); newSketchYAxis.Name = "Axis: Imported Excel Points Y"; newSketch.AxisEntity = newSketchYAxis; newSketch.AxisIsX = false; //NaturalAxisDirection defaults to true so only change it if we need to. if (!newSketchYAxis.Line.Direction.IsEqualTo(cylinderNormal, HoleTolerance)) { newSketch.NaturalAxisDirection = false; } foreach (SketchPoint sketchPoint in newSketch.SketchPoints) { if (sketchPoint.ReferencedEntity == datumWorkPoint) { OriginSketchPoint = sketchPoint; break; } } if (OriginSketchPoint == null) { OriginSketchPoint = (SketchPoint)newSketch.AddByProjectingEntity(datumWorkPoint); // partCompDef.WorkPoints[1]); } } } catch (Exception ex) { log.Error(ex.Message); } }
I also had to do some Matrix translations/rotations to get the points going in the correct orientation:
private static void CreateGeomForHolePositionComparisons() { try { //#if DEBUG // ClientGraphics debuggingGraphics = null; // try // { // debuggingGraphics = partCompDef.ClientGraphicsCollection["debuggingGraphics"]; // if (debuggingGraphics != null) // { // //delete the existing graphics // debuggingGraphics.Delete(); // //and then add new ones. // debuggingGraphics = partCompDef.ClientGraphicsCollection.Add("debuggingGraphics"); // } // } // catch (Exception) // { // debuggingGraphics = partCompDef.ClientGraphicsCollection.Add("debuggingGraphics"); // } //#endif ObjectCollection objCollection = PartDoc.AttributeManager.FindObjects("RadialHole", "HolePositionX"); originWP = partCompDef.WorkPoints[1]; double[] endfaceParams = new double[2]; double[] endFaceNormals = new double[3]; endfaceParams[0] = 0; endfaceParams[1] = 0; selectedEndFace.Evaluator.GetNormal(endfaceParams, endFaceNormals); Plane selectedFacePlane = selectedEndFace.Geometry; selectedFacePlane.Evaluator.GetNormal(endfaceParams, endFaceNormals); selectedWorkPlane.GetPosition(out Inventor.Point tmpWPPoint, out UnitVector tmpXAxis, out UnitVector tmpYAxis); double percent = 0; double progress = 0; for (int i = 1; i < objCollection.Count + 1; i++) { if (objCollection[i] is SketchPoint skpoint) { percent = (progress / objCollection.Count); Reporter.UpdateStatusBar(percent, "Creating 3D Points for comparison with Sketch Points."); AttributeSet AttSet = skpoint.AttributeSets[1]; Inventor.Attribute xPosAtt = null; double xPosition = 0; Inventor.Attribute yPosAtt = null; double yPosition = 0; xPosAtt = AttSet["HolePositionX"]; xPosition = Convert.ToDouble(xPosAtt.Value); yPosAtt = AttSet["HolePositionY"]; yPosition = Convert.ToDouble(yPosAtt.Value); Inventor.Attribute holeName = AttSet["HoleName"]; string ThisHoleName = holeName.Value.ToString(); //creates a basic point for translation. Inventor.Point tmpOriginPoint = TransGeom.CreatePoint(0, yPosition, datumWorkPoint.Point.Z); Matrix originMatrix = TransGeom.CreateMatrix(); Matrix destinationMatrix = TransGeom.CreateMatrix(); originMatrix.SetTranslation(originWP.Point.VectorTo(datumWorkPoint.Point)); Vector originYVector = TransGeom.CreateVector(0, 1, 0); originMatrix.SetToRotateTo(originYVector, cylinderNormal.AsVector()); tmpOriginPoint.TransformBy(originMatrix); tmpOriginPoint.TranslateBy(originWP.Point.VectorTo(datumWorkPoint.Point)); //Inventor.Point tmpOriginPoint = TransGeom.CreatePoint(datumWorkPoint.Point.X, yPosition, datumWorkPoint.Point.Z); double radius = selectedFace.Geometry.Radius; double pi = Math.PI; double circumference = ((2 * pi) * radius); double arcLength = xPosition; double arcAngle = (arcLength / ((2 * radius) * pi)) * 360; Arc3d tmpArc = null; 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) { holeDef.ComparisonPoint = tmpArc.EndPoint; } 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(); progress++; } } } catch (Exception ex) { log.Error(ex.Message); } //new3DSketch.curves }
So I'm pretty happy with the results so far.
Like I said earlier though, it would still be nice to figure out how to create a flip-able direction arrow - something I'm fairly confident I can do given that Matrices don't seem quite as challenging now the above is working.
Thanks,
Alex.
That's great @AlexFielder!!!
I think, flip-able direction arrow can be achieved by Inverting Matrix (Matrix.Invert() API).
Thanks and regards,
That's great @AlexFielder!!!
I think, flip-able direction arrow can be achieved by Inverting Matrix (Matrix.Invert() API).
Thanks and regards,
Hi, Chandra,
Given the graphics sample of https://adndevblog.typepad.com/manufacturing/2015/01/create-transient-3d-arrow-with-clientgraphics.h... how do you flip the arrow direction using Matrix.Invert? I am quite confused with the use of Matrix.Invert method.
Hi, Chandra,
Given the graphics sample of https://adndevblog.typepad.com/manufacturing/2015/01/create-transient-3d-arrow-with-clientgraphics.h... how do you flip the arrow direction using Matrix.Invert? I am quite confused with the use of Matrix.Invert method.
Can't find what you're looking for? Ask the community or share your knowledge.