public Result Execute( ExternalCommandData commandData, ref String message, ElementSet elements) { Util.ListForgeTypeIds(); UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; Element e = Util.SelectSingleElement( uidoc, "a line or wall"); LocationCurve curve = null; if (null == e) { message = "No element selected"; } else { curve = e.Location as LocationCurve; } if (null == curve) { message = "No curve available"; } else { XYZ p = curve.Curve.GetEndPoint(0); XYZ q = curve.Curve.GetEndPoint(1); Debug.WriteLine("Start point " + Util.PointString(p)); Debug.WriteLine("End point " + Util.PointString(q)); // the angle between the vectors from the project origin // to the start and end points of the wall is pretty irrelevant: double a = p.AngleTo(q); Debug.WriteLine( "Angle between start and end point vectors = " + Util.AngleString(a)); XYZ v = q - p; XYZ vx = XYZ.BasisX; a = vx.AngleTo(v); Debug.WriteLine( "Angle between points measured from X axis = " + Util.AngleString(a)); XYZ z = XYZ.BasisZ; a = vx.AngleOnPlaneTo(v, z); Debug.WriteLine( "Angle around measured from X axis = " + Util.AngleString(a)); if (e is Wall) { Wall wall = e as Wall; XYZ w = z.CrossProduct(v).Normalize(); if (wall.Flipped) { w = -w; } a = vx.AngleOnPlaneTo(w, z); Debug.WriteLine( "Angle pointing out of wall = " + Util.AngleString(a)); } } foreach (ProjectLocation location in doc.ProjectLocations) { //ProjectPosition projectPosition // = location.get_ProjectPosition( XYZ.Zero ); // 2017 ProjectPosition projectPosition = location.GetProjectPosition(XYZ.Zero); // 2018 double pna = projectPosition.Angle; Debug.WriteLine( "Angle between project north and true north " + Util.AngleString(pna)); } return(Result.Failed); }