// PB: This implementation borrows the somewhat risky notions from the original Dynamo // implementation. In short, it has the ability to infer a sketch plane, // which might also mean deleting the original one. /// <summary> /// Initialize a ModelCurve element /// </summary> /// <param name="crv"></param> /// <param name="makeReferenceCurve"></param> private void InitModelCurve(Autodesk.Revit.DB.Curve crv, bool makeReferenceCurve) { //Phase 1 - Check to see if the object exists and should be rebound var mc = ElementBinder.GetElementFromTrace <Autodesk.Revit.DB.ModelCurve>(Document); //There was a modelcurve, try and set sketch plane // if you can't, rebuild if (mc != null) { InternalSetCurveElement(mc); InternalSetSketchPlaneFromCurve(crv); return; } ElementId oldId = (mc != null) ? mc.Id : ElementId.InvalidElementId; string oldUniqueId = (mc != null) ? mc.UniqueId : string.Empty; TransactionManager.Instance.EnsureInTransaction(Document); // (sic erat scriptum) var sp = GetSketchPlaneFromCurve(crv); var plane = sp.GetPlane(); if (CurveUtils.GetPlaneFromCurve(crv, true) == null) { var flattenCurve = Flatten3dCurveOnPlane(crv, plane); mc = Document.IsFamilyDocument ? Document.FamilyCreate.NewModelCurve(flattenCurve, sp) : Document.Create.NewModelCurve(flattenCurve, sp); setCurveMethod(mc, crv); } else { mc = Document.IsFamilyDocument ? Document.FamilyCreate.NewModelCurve(crv, sp) : Document.Create.NewModelCurve(crv, sp); } if (mc.SketchPlane.Id != sp.Id) { //THIS BIZARRE as Revit could use different existing SP, so if Revit had found better plane this sketch plane has no use DocumentManager.Instance.DeleteElement(new ElementUUID(sp.UniqueId)); } InternalSetCurveElement(mc); if (oldId != mc.Id && oldId != ElementId.InvalidElementId) { DocumentManager.Instance.DeleteElement(new ElementUUID(oldUniqueId)); } if (makeReferenceCurve) { mc.ChangeToReferenceLine(); } TransactionManager.Instance.TransactionTaskDone(); ElementBinder.SetElementForTrace(this.InternalElement); }
/// <summary> /// Set the curve internally. Returns false if this method failed to set the curve /// </summary> /// <param name="c"></param> /// <returns></returns> private bool InternalSetSketchPlaneFromCurve(Autodesk.Revit.DB.Curve c) { TransactionManager.Instance.EnsureInTransaction(Document); // Infer the sketch plane Autodesk.Revit.DB.Plane plane = CurveUtils.GetPlaneFromCurve(c, false); // attempt to change the sketch plane bool needsRemake = false; string idSpUnused = resetSketchPlaneMethod(this.InternalCurveElement, c, plane, out needsRemake); // if we got a valid id, delete the old sketch plane if (idSpUnused != String.Empty) { DocumentManager.Instance.DeleteElement(new ElementUUID(idSpUnused)); } TransactionManager.Instance.TransactionTaskDone(); return(!needsRemake); }
private static Curve Flatten3dCurveOnPlane(Curve c, Plane plane) { if (c is Autodesk.Revit.DB.HermiteSpline) { var hs = c as Autodesk.Revit.DB.HermiteSpline; plane = CurveUtils.GetPlaneFromCurve(c, false); var projPoints = new List <XYZ>(); foreach (var pt in hs.ControlPoints) { var proj = pt - (pt - plane.Origin).DotProduct(plane.Normal) * plane.Normal; projPoints.Add(proj); } return(Autodesk.Revit.DB.HermiteSpline.Create(projPoints, false)); } if (c is Autodesk.Revit.DB.NurbSpline) { var ns = c as Autodesk.Revit.DB.NurbSpline; if (plane == null) { var bestFitPlane = Autodesk.DesignScript.Geometry.Plane.ByBestFitThroughPoints( ns.CtrlPoints.ToList().ToPoints(false)); plane = bestFitPlane.ToPlane(false); } var projPoints = new List <XYZ>(); foreach (var pt in ns.CtrlPoints) { var proj = pt - (pt - plane.Origin).DotProduct(plane.Normal) * plane.Normal; projPoints.Add(proj); } return(Autodesk.Revit.DB.NurbSpline.Create(projPoints, ns.Weights.Cast <double>().ToList(), ns.Knots.Cast <double>().ToList(), ns.Degree, ns.isClosed, ns.isRational)); } return(c); }
/// <summary> /// Set the plane and the curve internally. /// </summary> private void InternalSetSketchPlaneFromCurve(Curve newCurve) { TransactionManager.Instance.EnsureInTransaction(Document); Plane newPlane = CurveUtils.GetPlaneFromCurve(newCurve, false); Plane oldPlane = InternalCurveElement.SketchPlane.GetPlane(); var angleBetweenPlanes = newPlane.Normal.AngleTo(oldPlane.Normal); var distanceBetweenOrigins = newPlane.Origin.DistanceTo(oldPlane.Origin); Autodesk.Revit.DB.SketchPlane sp = null; // Planes are different. if (angleBetweenPlanes > tolerance || distanceBetweenOrigins > tolerance) { sp = GetSketchPlaneFromCurve(newCurve); InternalCurveElement.SetSketchPlaneAndCurve(sp, newCurve); } // Planes are the same. else { InternalSetCurve(newCurve); } string idSpUnused = String.Empty; if (sp != null && InternalCurveElement.SketchPlane.Id != sp.Id) { idSpUnused = sp.UniqueId; } // if we got a valid id, delete the old sketch plane if (idSpUnused != String.Empty) { DocumentManager.Instance.DeleteElement(new ElementUUID(idSpUnused)); } TransactionManager.Instance.TransactionTaskDone(); }
private static Autodesk.Revit.DB.SketchPlane GetSketchPlaneFromCurve(Curve c) { Plane plane = CurveUtils.GetPlaneFromCurve(c, false); return(Autodesk.Revit.DB.SketchPlane.Create(Document, plane)); }
private static string resetSketchPlaneMethod(Autodesk.Revit.DB.CurveElement mc, Curve c, Autodesk.Revit.DB.Plane flattenedOnPlane, out bool needsSketchPlaneReset) { //do we need to reset? needsSketchPlaneReset = false; Autodesk.Revit.DB.Plane newPlane = flattenedOnPlane != null ? flattenedOnPlane : CurveUtils.GetPlaneFromCurve(c, false); Autodesk.Revit.DB.Plane curPlane = mc.SketchPlane.GetPlane(); bool resetPlane = false; { double llSqCur = curPlane.Normal.DotProduct(curPlane.Normal); double llSqNew = newPlane.Normal.DotProduct(newPlane.Normal); double dotP = newPlane.Normal.DotProduct(curPlane.Normal); double dotSqNormalized = (dotP / llSqCur) * (dotP / llSqNew); double angleTol = System.Math.PI / 1800.0; if (dotSqNormalized < 1.0 - angleTol * angleTol) { resetPlane = true; } } Autodesk.Revit.DB.SketchPlane sp = null; if (!resetPlane) { double originDiff = curPlane.Normal.DotProduct(curPlane.Origin - newPlane.Origin); double tolerance = 0.000001; if (originDiff > tolerance || originDiff < -tolerance) { sp = GetSketchPlaneFromCurve(c); mc.SketchPlane = GetSketchPlaneFromCurve(c); } return((sp == null || mc.SketchPlane.Id == sp.Id) ? "" : sp.UniqueId); } //do reset if method is available bool foundMethod = false; if (hasMethodResetSketchPlane) { Type CurveElementType = typeof(Autodesk.Revit.DB.CurveElement); MethodInfo[] curveElementMethods = CurveElementType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); System.String nameOfMethodSetCurve = "ResetSketchPlaneAndCurve"; System.String nameOfMethodSetCurveAlt = "SetSketchPlaneAndCurve"; foreach (MethodInfo m in curveElementMethods) { if (m.Name == nameOfMethodSetCurve || m.Name == nameOfMethodSetCurveAlt) { object[] argsM = new object[2]; sp = GetSketchPlaneFromCurve(c); argsM[0] = sp; argsM[1] = null; foundMethod = true; m.Invoke(mc, argsM); break; } } } if (!foundMethod) { //sp = dynRevitUtils.GetSketchPlaneFromCurve(c); hasMethodResetSketchPlane = false; needsSketchPlaneReset = true; //expect exception, so try to keep old plane? //mc.SketchPlane = sp; return(""); } if (sp != null && mc.SketchPlane.Id != sp.Id) { return(sp.UniqueId); } return(""); }