Constraint nested family location programmatically

Constraint nested family location programmatically

Anonymous
Not applicable
681 Views
1 Reply
Message 1 of 2

Constraint nested family location programmatically

Anonymous
Not applicable

Hi guys,

 

I'm trying to change the position of a family instance inside another family using parameters. I've seen that family instance class contains the parameter "Offset" which will shift the family instance regarding the plane where the instance was located. My question is how can I move the instance in the other two coordinates? I know how to do it by hand, for instance I can get one of the references of the family instance and align it to a Reference plane, later it will added a constrained dimension between that reference plane and another. This way the instance will move with the reference plane.

 

Programmatically (Revit 2017 API), I was trying to get a reference of a entity that it is inside the family instance, and I use NewAlignment to align that entity to a ReferencePlane object. Find below the code:

 

 

 

XYZ bubbleEnd = XYZ.BasisZ;
XYZ freeEnd = (-1) *  XYZ.BasisZ;
XYZ thirdPoint = (-1)* XYZ.BasisY;

ReferencePlane rpBase = _doc.FamilyCreate.NewReferencePlane2(bubbleEnd, freeEnd, thirdPoint, pView);

FamilyInstance instance = _doc.FamilyCreate.NewFamilyInstance(rpBase.GetReference(), XYZ.Zero, XYZ.BasisZ, s);
_doc.Regenerate();

Options opt = new Options();
opt.ComputeReferences = true;
opt.IncludeNonVisibleObjects = true;
GeometryElement geometryElement = instance.get_Geometry(opt);
GeometryInstance gInst = geometryElement.First() as GeometryInstance;

Line l1 = GetClosestLine(gInst.GetInstanceGeometry(), XYZ.Zero,  XYZ.BasisX, opt); //returns the nearest line of the family instance

XYZ freeEnd2 = l1.Origin;
XYZ bubbleEnd2 = l1.Origin + new XYZ(l1.Length * l1.Direction.X, l1.Length * l1.Direction.Y, l1.Length * l1.Direction.Z);
XYZ thirdPoint2 = (-1) * XYZ.BasisZ;

ReferencePlane rp = _doc.FamilyCreate.NewReferencePlane2(bubbleEnd2, freeEnd2, thirdPoint2, pView);
rp.Name = HottgenrothUtils.indexParametric.ToString() + "_" + strID + "_REF_XZ";

_doc.FamilyCreate.NewAlignment(pView, rp.GetReference(), l1.Reference);

...

public static Line GetClosestLine(GeometryElement e, XYZ p, XYZ direction, Options opt)
{
Line line = null;
double min_distance = double.MaxValue;

//GeometryObjectArray objects = geo.Objects; // 2012
//foreach( GeometryObject obj in objects ) // 2012

foreach (GeometryObject obj in e) // 2013
{
Line l = obj as Line;
if (l != null)
{
if ( IsParallel(direction, l.Direction) )
{
XYZ v = p - l.Origin;
double d = v.DotProduct(-l.Direction);
if (d < min_distance)
{
line = l;
min_distance = d;
}
}
}
}
return line;
}

 

 

NewAlignment function get into an exception : "Failed to create the alignment."

 

Could you help me to know why it could be not aligned?

 

If you know another way to modify the location of family instances using parameters, please, let me know.

 

 

Thanks in advance,

 

 

PD: find also attached the RFA file, that corresponds to the nested family.

 

 

0 Likes
682 Views
1 Reply
Reply (1)
Message 2 of 2

FAIR59
Advisor
Advisor

As you say, the process by hand consists of 2 steps. First the moving into place of the element (aligning), and second the locking of the constraint.

 

Despite its name the document.FamilyCreate.NewAlignment() method is the API version of the second step, and it requires the 2 elements in question to be aligned.

 

So before calling NewAlignment, you have to move the element into alignement. You can use:

 

            element.Location.Move()
            ElementTransformUtils.MoveElement()

0 Likes