public static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return(new Plane(norm, p0)); } CurveLoop cLoop = new CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return(cLoop.GetPlane()); } if (planarOnly) { return(null); } IList <XYZ> points = c.Tessellate(); List <XYZ> xyzs = new List <XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) { xyzs.Add(points[iPoint]); } //var v1 = p1 - p0; //var v2 = p2 - p0; //var norm = v1.CrossProduct(v2).Normalize(); ////Normal can be zero length in the case of a straight line ////or a curve whose three parameter points as measured above ////happen to lie along the same line. In this case, project ////the last point down to a plane and use the projected vector ////and one of the vectors from above to calculate a normal. //if (norm.IsZeroLength()) //{ // if (p0.Z == p2.Z) // { // norm = XYZ.BasisZ; // } // else // { // var p3 = new XYZ(p2.X, p2.Y, p0.Z); // var v3 = p3 - p0; // norm = v1.CrossProduct(v3); // } //} //var curvePlane = new Plane(norm, p0); XYZ meanPt; List <XYZ> orderedEigenvectors; BestFitLine.PrincipalComponentsAnalysis(xyzs, out meanPt, out orderedEigenvectors); var normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]); var plane = dynRevitSettings.Doc.Application.Application.Create.NewPlane(normal, meanPt); return(plane); }
private static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (System.Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return new Plane(norm, p0); } Autodesk.Revit.DB.CurveLoop cLoop = new Autodesk.Revit.DB.CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return cLoop.GetPlane(); } if (planarOnly) return null; IList<XYZ> points = c.Tessellate(); List<XYZ> xyzs = new List<XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) xyzs.Add(points[iPoint]); XYZ meanPt; List<XYZ> orderedEigenvectors; PrincipalComponentsAnalysis(xyzs, out meanPt, out orderedEigenvectors); var normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]); var plane = Document.Application.Create.NewPlane(normal, meanPt); return plane; }
private static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (System.Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return(new Plane(norm, p0)); } Autodesk.Revit.DB.CurveLoop cLoop = new Autodesk.Revit.DB.CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return(cLoop.GetPlane()); } if (planarOnly) { return(null); } IList <XYZ> points = c.Tessellate(); List <XYZ> xyzs = new List <XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) { xyzs.Add(points[iPoint]); } XYZ meanPt; List <XYZ> orderedEigenvectors; PrincipalComponentsAnalysis(xyzs, out meanPt, out orderedEigenvectors); var normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]); var plane = Document.Application.Create.NewPlane(normal, meanPt); return(plane); }
public override FScheme.Value Evaluate(FSharpList <FScheme.Value> args) { Autodesk.Revit.DB.CurveLoop cl = (Autodesk.Revit.DB.CurveLoop)((FScheme.Value.Container)args[0]).Item; if (cl == null) { throw new InvalidOperationException("No curve loop"); } Autodesk.Revit.DB.Plane plane = cl.GetPlane(); if (plane == null) { throw new InvalidOperationException("Curve loop is not planar"); } var mcs = new System.Collections.Generic.List <Autodesk.Revit.DB.ModelCurve>(); var listCurves = new System.Collections.Generic.List <Curve> (); CurveLoopIterator CLiter = cl.GetCurveLoopIterator(); for (; CLiter.MoveNext();) { listCurves.Add(CLiter.Current.Clone()); } int numCurves = listCurves.Count; Autodesk.Revit.DB.SketchPlane sp = null; for (int index = 0; index < numCurves; index++) { //instead of changing Revit curve keep it "as is" //user might have trouble modifying curve in Revit if it is off the sketch plane Autodesk.Revit.DB.ModelCurve mc = null; if (this.Elements.Any() && index < this.Elements.Count) { bool needsRemake = false; if (dynUtils.TryGetElement(this.Elements[index], out mc)) { ElementId idSpUnused = ModelCurve.resetSketchPlaneMethod(mc, listCurves[index], plane, out needsRemake); if (idSpUnused != ElementId.InvalidElementId && index == numCurves - 1) { this.DeleteElement(idSpUnused); } if (!needsRemake) { if (!mc.GeometryCurve.IsBound && listCurves[index].IsBound) { listCurves[index] = listCurves[index].Clone(); listCurves[index].MakeUnbound(); } ModelCurve.setCurveMethod(mc, listCurves[index]); // mc.GeometryCurve = c; } else { this.DeleteElement(this.Elements[index]); } } else { needsRemake = true; } if (needsRemake) { if (sp == null) { sp = dynRevitSettings.Doc.Document.IsFamilyDocument ? dynRevitSettings.Doc.Document.FamilyCreate.NewSketchPlane(plane) : dynRevitSettings.Doc.Document.Create.NewSketchPlane(plane); } if (dynRevitUtils.GetPlaneFromCurve(listCurves[index], true) == null) { mc = this.UIDocument.Document.IsFamilyDocument ? this.UIDocument.Document.FamilyCreate.NewModelCurve(listCurves[index], sp) : this.UIDocument.Document.Create.NewModelCurve(listCurves[index], sp); ModelCurve.setCurveMethod(mc, listCurves[index]); } else { mc = this.UIDocument.Document.IsFamilyDocument ? this.UIDocument.Document.FamilyCreate.NewModelCurve(listCurves[index], sp) : this.UIDocument.Document.Create.NewModelCurve(listCurves[index], sp); } if (index < this.Elements.Count) { this.Elements[index] = mc.Id; } else { this.Elements.Add(mc.Id); } if (mc.SketchPlane.Id != sp.Id && index == numCurves - 1) { //THIS BIZARRE as Revit could use different existing SP, so if Revit had found better plane this sketch plane has no use this.DeleteElement(sp.Id); } } } else { if (sp == null) { sp = dynRevitSettings.Doc.Document.IsFamilyDocument ? dynRevitSettings.Doc.Document.FamilyCreate.NewSketchPlane(plane) : dynRevitSettings.Doc.Document.Create.NewSketchPlane(plane); } if (dynRevitUtils.GetPlaneFromCurve(listCurves[index], true) == null) { mc = this.UIDocument.Document.IsFamilyDocument ? this.UIDocument.Document.FamilyCreate.NewModelCurve(listCurves[index], sp) : this.UIDocument.Document.Create.NewModelCurve(listCurves[index], sp); ModelCurve.setCurveMethod(mc, listCurves[index]); } else { mc = this.UIDocument.Document.IsFamilyDocument ? this.UIDocument.Document.FamilyCreate.NewModelCurve(listCurves[index], sp) : this.UIDocument.Document.Create.NewModelCurve(listCurves[index], sp); } this.Elements.Add(mc.Id); if (mc.SketchPlane.Id != sp.Id && index == numCurves - 1) { //found better plane this.DeleteElement(sp.Id); } } if (mc != null) { mcs.Add(mc); } } FSharpList <FScheme.Value> results = FSharpList <FScheme.Value> .Empty; foreach (var mc in mcs) { results = FSharpList <FScheme.Value> .Cons(FScheme.Value.NewContainer(mc), results); } return(FScheme.Value.NewList(Utils.SequenceToFSharpList(results.Reverse()))); }
public static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return new Plane(norm, p0); } Autodesk.Revit.DB.CurveLoop cLoop = new Autodesk.Revit.DB.CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return cLoop.GetPlane(); } if (planarOnly) return null; IList<XYZ> points = c.Tessellate(); List<XYZ> xyzs = new List<XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) xyzs.Add(points[iPoint]); //var v1 = p1 - p0; //var v2 = p2 - p0; //var norm = v1.CrossProduct(v2).Normalize(); ////Normal can be zero length in the case of a straight line ////or a curve whose three parameter points as measured above ////happen to lie along the same line. In this case, project ////the last point down to a plane and use the projected vector ////and one of the vectors from above to calculate a normal. //if (norm.IsZeroLength()) //{ // if (p0.Z == p2.Z) // { // norm = XYZ.BasisZ; // } // else // { // var p3 = new XYZ(p2.X, p2.Y, p0.Z); // var v3 = p3 - p0; // norm = v1.CrossProduct(v3); // } //} //var curvePlane = new Plane(norm, p0); XYZ meanPt; List<XYZ> orderedEigenvectors; BestFitLine.PrincipalComponentsAnalysis(xyzs, out meanPt, out orderedEigenvectors); var normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]); var plane = dynRevitSettings.Doc.Application.Application.Create.NewPlane(normal, meanPt); return plane; }
private static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (System.Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return new Plane(norm, p0); } Autodesk.Revit.DB.CurveLoop cLoop = new Autodesk.Revit.DB.CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return cLoop.GetPlane(); } if (planarOnly) return null; IList<XYZ> points = c.Tessellate(); List<XYZ> xyzs = new List<XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) xyzs.Add(points[iPoint]); var bestFitPlane = Autodesk.DesignScript.Geometry.Plane.ByBestFitThroughPoints(xyzs.ToPoints(false)); return bestFitPlane.ToPlane(false); }