If I have two parts as occurrences in an assembly, how can I programatically constraint two workplanes (one from each part) to a flush constraint.
In C++ would be lovely, but any help happily accepted!
My problem is that I can get the Occurrences, say ...
CComPtr<ComponentOccurrence> pTube1Occ = ...
CComPtr<ComponentOccurrence> pTube2Occ = ...
...but I don't know how to delve into these two pointers to get hold of two named workplanes within them. I'd then pass the two workplanes (somehow?!) to the AddFlushConstraint function.
get_SurfaceBodies doesn't seem right and neither does get_SubOccurrences.
Solved! Go to Solution.
Solved by philippe.leefsma. Go to Solution.
A sample is provided in the API Help Files that does exactly this. Please take a look there before asking questions:
Public Sub MateConstraintOfWorkPlanes() Dim oAsmCompDef As AssemblyComponentDefinition Set oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition ' Get references to the two occurrences to constrain. ' This arbitrarily gets the first and second occurrence. Dim oOcc1 As ComponentOccurrence Set oOcc1 = oAsmCompDef.Occurrences.Item(1) Dim oOcc2 As ComponentOccurrence Set oOcc2 = oAsmCompDef.Occurrences.Item(2) ' Get the XY plane from each occurrence. This goes to the ' component definition of the part to get this information. ' This is the same as accessing the part document directly. ' The work plane obtained is in the context of the part, ' not the assembly. Dim oPartPlane1 As WorkPlane Set oPartPlane1 = oOcc1.Definition.WorkPlanes.Item(3) Dim oPartPlane2 As WorkPlane Set oPartPlane2 = oOcc2.Definition.WorkPlanes.Item(3) ' Because we need the work plane in the context of the assembly ' we need to create proxies for the work planes. The proxies ' represent the work planes in the context of the assembly. Dim oAsmPlane1 As WorkPlaneProxy Call oOcc1.CreateGeometryProxy(oPartPlane1, oAsmPlane1) Dim oAsmPlane2 As WorkPlaneProxy Call oOcc2.CreateGeometryProxy(oPartPlane2, oAsmPlane2) ' Create the constraint using the work plane proxies. Call oAsmCompDef.Constraints.AddMateConstraint(oAsmPlane1, oAsmPlane2, 0) End Sub
Regards,
Philippe.
I did search for examples, but found non in C++. In C++ how is that done?
Set oPartPlane2 = oOcc2.Definition.WorkPlanes.Item(3)
The above is fine for VB, but in C++ how I can get the part definition?
CComPtr<ComponentDefinition> pCompDef = nullptr ; pOcc->get_Definition(&pCompDef) ; // How to get the workplane list from the pCompDef???
pCompDef does not have a member Workplanes or get_Workplanes.
This, for example, does not work:
CComPtr<PartComponentDefinition> pPartCompDef = pCompDef ;
The cast does not compile.
Here is a sample that should help:
HRESULT GetOccurrenceCenter( CComPtr<ComponentOccurrence>& pCompOcc, CComPtr<Point>& center) { HRESULT hr = S_OK; CComPtr<PartComponentDefinition> pCompDef; pCompDef = CComQIPtr<PartComponentDefinition>(pCompOcc->Definition); if(pCompDef == NULL) return E_FAIL; CComPtr<MassProperties> MassProps; hr = pCompDef->get_MassProperties(&MassProps); CComPtr<Point> centerOfMass; hr = MassProps->get_CenterOfMass(¢erOfMass); CComPtr<Matrix> occTransfo; hr = pCompOcc->get_Transformation(&occTransfo); hr = centerOfMass->TransformBy(occTransfo); center = centerOfMass; return hr; }
Philippe.
Aha! You mean this:
CComQIPtr<PartComponentDefinition> pCompDef = CComQIPtr<PartComponentDefinition>(pOcc->Definition); pCompDef->get_WorkPlanes (...) ;
Yes, that is a big help
Sorry to bother you again, but my poor brain is not sure of the correct cast of the workplane pointers as parameters to the AddFlushConstraint function. I'm doing this...
CComPtr<WorkPlane> pWorkPlaneA = ... ; CComPtr<WorkPlane> pWorkPlaneb = ... ; CComVariant varEmpty, varReal(0.0); CComPtr<FlushConstraint> pFC = nullptr ; hRes = pConstraintList->AddFlushConstraint (pWorkPlaneA, pWorkPlanebB, varReal, varEmpty, varEmpty,&pFC);
The COM error is 80004005, unspecified error. Do I need to cast the workplane pointers or...? Maybe I need to wrap those pointers? Is there a C++ example of a call like this?
When I do the operation by hand, manually, it works.
C++ is hard to do some prototyping work in Inventor, I would recommend that you test before with a much simpler approach, like VBA for example.
Below is an example of Flush Constraint creation, once you've got the VBA code working, you can try translating into C++.
' Creates two WorkPlanes in an assembly ' and offset them by creating a FlushConstraint Private Sub CreateWPlanesWithFlush() Dim doc As AssemblyDocument Set doc = ThisApplication.ActiveDocument Dim compDef As AssemblyComponentDefinition Set compDef = doc.ComponentDefinition Dim wps As WorkPlanes Set wps = compDef.WorkPlanes Dim wp1 As workplane Set wp1 = wps.AddFixed(compDef.WorkPoints(1).point, _ compDef.WorkAxes(1).line.direction, _ compDef.WorkAxes(2).line.direction) Dim wp2 As workplane Set wp2 = wps.AddFixed(compDef.WorkPoints(1).point, _ compDef.WorkAxes(1).line.direction, _ compDef.WorkAxes(2).line.direction) Dim fc As FlushConstraint Set fc = compDef.Constraints.AddFlushConstraint(wp1, wp2, 0) fc.offset.value = fc.offset.value + 10 'Update is needed doc.Update End Sub
You shouldn't have to cast the WorkPlane pointers in order to get it to work. The issue must come from some where else. If you still have issues to get this done, please provide a code sample that is usable, i.e complete.
Thanks,
Philippe.
I'll do both things, I'll try to get a VB example going and I'll also show you a much simplified C++ function which illustrates my problem, see the two attachments.
The function opens an empty assembly, C:\TEST\Cylinders.iam
Then it inserts C:\TEST\Cyl1.ipt and C:\TEST\Cyl2.ipt
Then it tries to make a flush constraint between the "base" workplanes of the two cylinders, "XY Plane" and "YZ Plane" respectively.
The two parts and the assembly are in the attached zip, along with two jpegs.
The sources in in the attacched cpp. AddFlushConstraint is called near the end of the function.
Argh! I think the problem may be that I am not using Proxies for the worplanes in the call to AddFlushConstraint...
Well if you don't use proxies that will definitely not work: you always need to create constraints based on entities in the same assembly context as the one you want to create the constraint. If you have workplanes from parts or sub-assemblies, you need to create proxies for those at the assembly level where you create the constraint.