Direction of Reference (Reference Plane or Reference Line)

Direction of Reference (Reference Plane or Reference Line)

desdinova
Advocate Advocate
8,351 Views
17 Replies
Message 1 of 18

Direction of Reference (Reference Plane or Reference Line)

desdinova
Advocate
Advocate
FamilyInstance familyInstance = element as FamilyInstance;

IList<Reference> familyInstanceReferences = familyInstance.GetReferences(FamilyInstanceReferenceType.StrongReference);

foreach (Reference familyInstanceReference in familyInstanceReferences)
{
// I want to get direction of reference
}

Hello friends,

 

In 2018 version i can get the reference in familyinstance directly.

But i want to get the direction of references(reference planes or reference lines) 

How can i achieve this?

 

 

Line line = doc.GetElement(reference).GetGeometryObjectFromReference(reference) as Line;

didnt work for me.

Thanks in advance...

0 Likes
Accepted solutions (1)
8,352 Views
17 Replies
Replies (17)
Message 2 of 18

IbrahimNaeem
Advocate
Advocate

 

//Have you tried to get the location and acquire the line from there. 
LocationCurve loc = doc.GetElement(ref).Location as LocationCurve;
XYZ Frst = loc.Curve.GetEndPoint(0);

 

 

Thanks, Ibrahim Naeem 

 

0 Likes
Message 3 of 18

desdinova
Advocate
Advocate

Thanks.

I tried.

it didnt work

0 Likes
Message 4 of 18

IbrahimNaeem
Advocate
Advocate

Are you sure that these family instances are created as line based  ? 

 

Thanks, Ibrahim Naeem 

0 Likes
Message 5 of 18

desdinova
Advocate
Advocate

 

 
I think 
there is no need to use line based family
 
my code is
 
try
            {
                Line dimensionLine = null;

                ReferenceArray firstArray = new ReferenceArray();

                FamilyInstance familyInstance = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element)) as FamilyInstance;

                XYZ point = uidoc.Selection.PickPoint("Select first point");

                XYZ difference = new XYZ(200, 0, 0);

                dimensionLine = DimensionUtils.CreateLine(doc, point, difference);

                IList<Reference> familyInstanceReferences = familyInstance.GetReferences(FamilyInstanceReferenceType.StrongReference);

                foreach (Reference familyInstanceReference in familyInstanceReferences)
                {
                    firstArray.Append(familyInstanceReference);
                }

                using (Transaction t = new Transaction(doc, "Add Dimension"))
                {
                    t.Start();
                    Dimension dimension = doc.Create.NewDimension(doc.ActiveView, dimensionLine, firstArray);
                    t.Commit();
                }
            }

            catch(Exception ex)
            {
                TaskDialog.Show("Error", ex.Message);
            }
 
0 Likes
Message 6 of 18

FAIR59
Advisor
Advisor
Accepted solution

I think an adepted version of my answer to the discussion on a  Dimension on Hatch Pattern Slab https://forums.autodesk.com/t5/revit-api-forum/dimension-on-hatch-pattern-slab/m-p/7079252#M22790 will work for you.

 

Here's my code

        public XYZ GetReferenceDirection(Reference ref1, Document doc)
        // returns the direction perpendicular to reference
        // returns XYZ.Zero on error;
        {
            XYZ res = XYZ.Zero;
            XYZ workPlaneNormal = doc.ActiveView.SketchPlane.GetPlane().Normal;
            if (ref1.ElementId == ElementId.InvalidElementId) return res;
            Element elem = doc.GetElement(ref1.ElementId);
            if (elem == null) return res;
            if (ref1.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE || ref1.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR)
            {
                // make a dimension to a point for direction

                XYZ bEnd = new XYZ(10, 10, 10);
                ReferenceArray refArr = new ReferenceArray();
                refArr.Append(ref1);
                Dimension dim = null;
                using (Transaction t = new Transaction(doc, "test"))
                {
                    t.Start();
                    using (SubTransaction st = new SubTransaction(doc))
                    {
                        st.Start();
                        ReferencePlane refPlane = doc.Create.NewReferencePlane(XYZ.Zero, bEnd, bEnd.CrossProduct(XYZ.BasisZ).Normalize(), doc.ActiveView);
                        ModelCurve mc = doc.Create.NewModelCurve(Line.CreateBound(XYZ.Zero, new XYZ(10, 10, 10)), SketchPlane.Create(doc, refPlane.Id));
                        refArr.Append(mc.GeometryCurve.GetEndPointReference(0));
                        dim = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(XYZ.Zero, new XYZ(10, 0, 0)), refArr);
                        ElementTransformUtils.MoveElement(doc, dim.Id, new XYZ(0, 0.1, 0));
                        st.Commit();
                    }
                    if (dim != null)
                    {
                        Curve cv = dim.Curve;
                        cv.MakeBound(0, 1);
                        XYZ pt1 = cv.GetEndPoint(0);
                        XYZ pt2 = cv.GetEndPoint(1);
                        res = pt2.Subtract(pt1).Normalize();
                    }
                    t.RollBack();
                }
            }
            return res;
        }

 

 

Message 7 of 18

desdinova
Advocate
Advocate

Thank you FAIR59,

It is working...

0 Likes
Message 8 of 18

Anonymous
Not applicable

Did you modify FAIR59's code or are using the posted version? I am trying to get the direction of the reference but FAIR59's version returns the direction perpendicular direction whilst I am looking for the direction itself (parallel).

 

thanks in advance.

0 Likes
Message 9 of 18

desdinova
Advocate
Advocate

I use FAIR59's code 

for check the direction, i use this

 FamilyInstance familyInstance = element as FamilyInstance;

                            IList<Reference> familyInstanceReferences = familyInstance.GetReferences(FamilyInstanceReferenceType.StrongReference);

                            foreach (Reference familyInstanceReference in familyInstanceReferences)
                            {
                                if (DimensionUtils.GetReferenceDirection(doc, familyInstanceReference).ToString() == XYZ.BasisX.ToString() ||
                                   DimensionUtils.GetReferenceDirection(doc, familyInstanceReference).ToString() == XYZ.BasisX.Negate().ToString())
                                {
                                    firstArray.Append(familyInstanceReference);
                                }
                            }
0 Likes
Message 10 of 18

Anonymous
Not applicable

Hi FAIR59,

 

Your code is returning the perpendicular direction perfectly, but can this be modified to return the parallel direction? I am trying tot modify this but I am stuck at the moment.

 

Thanks in advance,

Raymond

 

0 Likes
Message 11 of 18

FAIR59
Advisor
Advisor

to get a 90 degree different direction, you need to establish the plane in which to "rotate".

The most obvious plane is off course the sketch plane of the view.

the normal for that plane is: doc.ActiveView.ViewDirection

 

instead of :

    return res;

use:

    return doc.ActiveView.ViewDirection.CrossProduct(res);

0 Likes
Message 12 of 18

Anonymous
Not applicable
That easy huh :). Will give it a shot.
0 Likes
Message 13 of 18

Anonymous
Not applicable

Thanks!!

0 Likes
Message 14 of 18

mastjaso
Advocate
Advocate

Hey @FAIR59 this code does seem to work well for returning the normal of the reference plane, provided that the reference plane is oriented vertically. But this doesn't seem to work if your reference plane is horizontal. I've looked through it, and I think I somewhat understand how your function is working (somewhat.), but I can't figure out how it could be adapted to truly work in any direction. I suspect it's not possible based on the fact that you're having to use a dimension created in this view, however, I was wondering if you had any ideas?

0 Likes
Message 15 of 18

FAIR59
Advisor
Advisor

The function makes the temporary dimension in the active view. If the active view is a planview, then yes only the vertical planes will be found.

To make the function more general, you could loop through all the views in the document, in the hope of finding a view that gives a result. ( no garanties )

 

IEnumerable<View> views = new FilteredElementCollector(doc)
				.OfClass(typeof(View));
foreach(View v in views)
{
	if (v.IsTemplate) continue;
	XYZ rightdirection = v.RightDirection;
	dim = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(XYZ.Zero, rightdirection.Multiply(10)), refArr);
	if (dim!=null) break;
}
if (dim !=null)
{
     ElementTransformUtils.MoveElement(doc, dim.Id, new XYZ(0, 0.1, 0));
    .....
}
0 Likes
Message 16 of 18

paolomod3nese
Enthusiast
Enthusiast

Hi desdinova!

 

I'm trying to achieve exactly what you wanted to do: get the direction of references in a FamilyInstance.

 

I can't seem to find the

DimensionUtils

class in the API. Is this a custom class? If so, can you point me to the right direction on what class or method should I be searching for to get the direction of a reference?

 

Cheers,

 

Paolo

0 Likes
Message 17 of 18

desdinova
Advocate
Advocate

Hi Paolo,

Yes it is a custom class.

You can use

public static XYZ GetReferenceDirection(Document doc, Reference reference)
        {
            XYZ res = XYZ.Zero;
            XYZ workPlaneNormal = doc.ActiveView.SketchPlane.GetPlane().Normal;
            if (reference.ElementId == ElementId.InvalidElementId)
            {
                return res;
            }

            Element elem = doc.GetElement(reference.ElementId);
            if (elem == null)
            {
                return res;
            }
            if (reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE || reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR)
            {
                XYZ bEnd = new XYZ(10, 10, 10);
                ReferenceArray refArr = new ReferenceArray();
                refArr.Append(reference);
                Dimension dim = null;
                using (Transaction t = new Transaction(doc, "test"))
                {
                    t.Start();
                    using (SubTransaction st = new SubTransaction(doc))
                    {
                        st.Start();
                        ReferencePlane refPlane = doc.Create.NewReferencePlane(XYZ.Zero, bEnd, bEnd.CrossProduct(XYZ.BasisZ).Normalize(), doc.ActiveView);
                        ModelCurve mc = doc.Create.NewModelCurve(Line.CreateBound(XYZ.Zero, new XYZ(10, 10, 10)), SketchPlane.Create(doc, refPlane.Id));
                        refArr.Append(mc.GeometryCurve.GetEndPointReference(0));
                        dim = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(XYZ.Zero, new XYZ(10, 0, 0)), refArr);
                        ElementTransformUtils.MoveElement(doc, dim.Id, new XYZ(0, 0.1, 0));
                        st.Commit();
                    }
                    if (dim != null)
                    {
                        Curve cv = dim.Curve;
                        cv.MakeBound(0, 1);
                        XYZ pt1 = cv.GetEndPoint(0);
                        XYZ pt2 = cv.GetEndPoint(1);
                        res = pt2.Subtract(pt1).Normalize();
                    }
                    t.RollBack();
                }
            }
            return res;
        }

It works for me.

Cheers

Message 18 of 18

BKSpurgeon
Collaborator
Collaborator

Hi @FAIR59 

 

Thanks for your answer + the code you are providing.

 

It isn't altogether clear (to me) what you are doing (and why) in certain parts of your code? 

 

 

 

 

0 Likes