public override FScheme.Value Evaluate(FSharpList <FScheme.Value> args) { var t = (Transform)((FScheme.Value.Container)args[0]).Item; double width = ((FScheme.Value.Number)args[1]).Item; double height = ((FScheme.Value.Number)args[2]).Item; //ccw from upper right var p0 = new XYZ(width / 2, height / 2, 0); var p3 = new XYZ(-width / 2, height / 2, 0); var p2 = new XYZ(-width / 2, -height / 2, 0); var p1 = new XYZ(width / 2, -height / 2, 0); p0 = t.OfPoint(p0); p1 = t.OfPoint(p1); p2 = t.OfPoint(p2); p3 = t.OfPoint(p3); var l1 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p0, p1); var l2 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p1, p2); var l3 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p2, p3); var l4 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p3, p0); var cl = new Autodesk.Revit.DB.CurveLoop(); cl.Append(l1); cl.Append(l2); cl.Append(l3); cl.Append(l4); return(FScheme.Value.NewContainer(cl)); }
public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { var t = (Transform)((FScheme.Value.Container)args[0]).Item; double width = ((FScheme.Value.Number)args[1]).Item; double height = ((FScheme.Value.Number)args[2]).Item; //ccw from upper right var p0 = new XYZ(width / 2, height / 2, 0); var p3 = new XYZ(-width / 2, height / 2, 0); var p2 = new XYZ(-width / 2, -height / 2, 0); var p1 = new XYZ(width / 2, -height / 2, 0); p0 = t.OfPoint(p0); p1 = t.OfPoint(p1); p2 = t.OfPoint(p2); p3 = t.OfPoint(p3); var l1 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p0, p1); var l2 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p1, p2); var l3 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p2, p3); var l4 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p3, p0); var cl = new Autodesk.Revit.DB.CurveLoop(); cl.Append(l1); cl.Append(l2); cl.Append(l3); cl.Append(l4); return FScheme.Value.NewContainer(cl); }
public override Value Evaluate(FSharpList <Value> args) { Curve curve = (Curve)((Value.Container)args[0]).Item; double thickness = ((Value.Number)args[1]).Item; XYZ normal = (XYZ)((Value.Container)args[2]).Item; Autodesk.Revit.DB.CurveLoop thickenLoop = Autodesk.Revit.DB.CurveLoop.CreateViaThicken(curve.Clone(), thickness, normal); if (thickenLoop == null) { throw new Exception("Could not offset curve"); } CurveLoopIterator CLiter = thickenLoop.GetCurveLoopIterator(); Curve result = null; //relying heavily on the order of curves in the resulting curve loop, based on internal implemen for (int index = 0; CLiter.MoveNext(); index++) { if (index == 2) { result = CLiter.Current.Clone(); } } if (result == null) { throw new Exception("Could not offset curve"); } return(Value.NewContainer(result)); }
/// <summary> /// Internal constructor making a solid by revolve /// </summary> /// <param name="loop"></param> /// <param name="trans"></param> /// <param name="start">The start angle</param> /// <param name="end">The end angle</param> internal Solid(CurveLoop loop, Transform trans, double start, double end) { var loopList = new List<Autodesk.Revit.DB.CurveLoop> { loop }; var thisFrame = new Autodesk.Revit.DB.Frame(); thisFrame.Transform(trans); var result = GeometryCreationUtilities.CreateRevolvedGeometry(thisFrame, loopList, start, end); this.InternalSolid = result; }
public override Value Evaluate(FSharpList <Value> args) { Curve curve = (Curve)((Value.Container)args[0]).Item; double thickness = ((Value.Number)args[1]).Item; XYZ normal = (XYZ)((Value.Container)args[2]).Item; Autodesk.Revit.DB.CurveLoop result = Autodesk.Revit.DB.CurveLoop.CreateViaThicken(curve.Clone(), thickness, normal); if (result == null) { throw new Exception("Could not thicken curve"); } return(Value.NewContainer(result)); }
/// <summary> /// Converts a <see cref="DB.CurveLoop"/> into a Rhino <see cref="Curve"/> /// </summary> public static Curve ToCurve(this DB.CurveLoop value) { if (value.NumberOfCurves() == 1) { return(value.First().ToCurve()); } var polycurve = new PolyCurve(); foreach (var curve in value) { polycurve.AppendSegment(curve.ToCurve()); } return(polycurve); }
public override Value Evaluate(FSharpList <Value> args) { Autodesk.Revit.DB.CurveLoop curveLoop = (Autodesk.Revit.DB.CurveLoop)((Value.Container)args[0]).Item; CurveLoopIterator CLiter = curveLoop.GetCurveLoopIterator(); List <Curve> listCurves = new List <Curve>(); for (; CLiter.MoveNext();) { listCurves.Add(CLiter.Current.Clone()); } var result = FSharpList <Value> .Empty; for (int indexCurve = listCurves.Count - 1; indexCurve > -1; indexCurve--) { result = FSharpList <Value> .Cons(Value.NewContainer(listCurves[indexCurve]), result); } return(Value.NewList(result)); }
public override Value Evaluate(FSharpList <Value> args) { var curves = ((Value.List)args[0]).Item.Select( x => ((Curve)((Value.Container)x).Item)).ToList(); List <Curve> curvesWithFlip = new List <Curve>(); bool bStart = true; XYZ prevEnd = new XYZ(); double tolMax = 0.0001; double tolMin = 0.00001; foreach (Curve c in curves) { if (!bStart) { XYZ thisEnd = c.Evaluate(1.0, true); XYZ thisStart = c.Evaluate(0.0, true); double thisDist = thisStart.DistanceTo(prevEnd); if (thisDist > tolMax && thisEnd.DistanceTo(prevEnd) < tolMin && (c is Line)) { prevEnd = thisStart; Curve flippedCurve = /* Line.CreateBound */ dynRevitSettings.Revit.Application.Create.NewLineBound(thisEnd, thisStart); curvesWithFlip.Add(flippedCurve); continue; } } else { bStart = false; prevEnd = c.Evaluate(1.0, true); if (curves.Count > 1) { XYZ nextStart = curves[1].Evaluate(0.0, true); double thisDist = prevEnd.DistanceTo(nextStart); if (thisDist > tolMax) { XYZ nextEnd = curves[1].Evaluate(1.0, true); if (nextEnd.DistanceTo(prevEnd) > tolMax) { XYZ thisStart = c.Evaluate(0.0, true); if (thisStart.DistanceTo(nextEnd) < tolMin || thisStart.DistanceTo(nextStart) < tolMin) { if (c is Line) { Curve flippedCurve = /* Line.CreateBound */ dynRevitSettings.Revit.Application.Create.NewLineBound(prevEnd, thisStart); prevEnd = thisStart; curvesWithFlip.Add(flippedCurve); continue; } } } } } } prevEnd = c.Evaluate(1.0, true); curvesWithFlip.Add(c); } Autodesk.Revit.DB.CurveLoop result = Autodesk.Revit.DB.CurveLoop.Create(curvesWithFlip); return(Value.NewContainer(result)); }
public override Value Evaluate(FSharpList<Value> args) { this.ClearPreviousResults(); //unwrap the values IEnumerable<double> nvals = ((Value.List)args[0]).Item.Select(q => (double)((Value.Number)q).Item); var curve = (Curve)((Value.Container)args[1]).Item; SpatialFieldManager = (Autodesk.Revit.DB.Analysis.SpatialFieldManager)((Value.Container)args[2]).Item; if (!SpatialFieldManager.IsResultSchemaNameUnique(DYNAMO_TEMP_CURVES_SCHEMA, -1)) { IList<int> arses = SpatialFieldManager.GetRegisteredResults(); foreach (int i in arses) { AnalysisResultSchema arsTest = SpatialFieldManager.GetResultSchema(i); if (arsTest.Name == DYNAMO_TEMP_CURVES_SCHEMA) { schemaId = i; break; } } } else { var ars = new AnalysisResultSchema(DYNAMO_TEMP_CURVES_SCHEMA, "Temporary curves from Dynamo."); schemaId = SpatialFieldManager.RegisterResult(ars); } Transform trf = Transform.Identity; //http://thebuildingcoder.typepad.com/blog/2012/09/sphere-creation-for-avf-and-filtering.html#3 var create = dynRevitSettings.Doc.Application.Application.Create; Transform t = curve.ComputeDerivatives(0, true); XYZ x = t.BasisX.Normalize(); XYZ y = t.BasisX.IsAlmostEqualTo(XYZ.BasisZ) ? t.BasisX.CrossProduct(XYZ.BasisY).Normalize() : t.BasisX.CrossProduct(XYZ.BasisZ).Normalize(); XYZ z = x.CrossProduct(y); Autodesk.Revit.DB.Ellipse arc1 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y,z,-Math.PI, 0); Autodesk.Revit.DB.Ellipse arc2 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y, z, 0, Math.PI); var pathLoop = new Autodesk.Revit.DB.CurveLoop(); pathLoop.Append(curve); var profileLoop = new Autodesk.Revit.DB.CurveLoop(); profileLoop.Append(arc1); profileLoop.Append(arc2); double curveDomain = curve.get_EndParameter(1) - curve.get_EndParameter(0); int idx = -1; var s = GeometryCreationUtilities.CreateSweptGeometry(pathLoop, 0, 0, new List<Autodesk.Revit.DB.CurveLoop>{profileLoop}); foreach (Face face in s.Faces) { //divide the V domain by the number of incoming BoundingBoxUV domain = face.GetBoundingBox(); double vSpan = domain.Max.V - domain.Min.V; //analysis values idx = SpatialFieldManager.AddSpatialFieldPrimitive(face, trf); //a list to hold the analysis points IList<UV> uvPts = new List<UV>(); //a list to hold the analysis values IList<ValueAtPoint> valList = new List<ValueAtPoint>(); //int count = nvals.Count(); //this is creating a lot of sample points, but if we used less //sampling points, AVF would draw the two surfaces as if there was a hard //edge between them. this provides a better blend. int count = 10; for (int i = 0; i < count; i ++) { //get a UV point on the face //find its XYZ location and project to //the underlying curve. find the value which corresponds //to the location on the curve var uv = new UV(domain.Min.U, domain.Min.V + vSpan / count*(double) i); var uv1 = new UV(domain.Max.U, domain.Min.V + vSpan / count * (double)i); uvPts.Add(uv); uvPts.Add(uv1); XYZ facePt = face.Evaluate(uv); IntersectionResult ir = curve.Project(facePt); double curveParam = curve.ComputeNormalizedParameter(ir.Parameter); if (curveParam < 0) curveParam = 0; if (curveParam > 1) curveParam = 1; var valueIndex = (int)Math.Floor(curveParam * (double)nvals.Count()); if (valueIndex >= nvals.Count()) valueIndex = nvals.Count() - 1; //create list of values at this point - currently supporting only one //var doubleList = new List<double> { nvals.ElementAt(i) }; var doubleList = new List<double> { nvals.ElementAt(valueIndex) }; //add value at point object containing the value list valList.Add(new ValueAtPoint(doubleList)); valList.Add(new ValueAtPoint(doubleList)); } var pnts = new FieldDomainPointsByUV(uvPts); var vals = new FieldValues(valList); SpatialFieldManager.UpdateSpatialFieldPrimitive( idx, pnts, vals, schemaId); PastResultIds.Add(idx); } return Value.NewNumber(idx); }
public override Value Evaluate(FSharpList <Value> args) { this.ClearPreviousResults(); //unwrap the values IEnumerable <double> nvals = ((Value.List)args[0]).Item.Select(q => (double)((Value.Number)q).Item); var curve = (Curve)((Value.Container)args[1]).Item; SpatialFieldManager = (Autodesk.Revit.DB.Analysis.SpatialFieldManager)((Value.Container)args[2]).Item; if (!SpatialFieldManager.IsResultSchemaNameUnique(DYNAMO_TEMP_CURVES_SCHEMA, -1)) { IList <int> arses = SpatialFieldManager.GetRegisteredResults(); foreach (int i in arses) { AnalysisResultSchema arsTest = SpatialFieldManager.GetResultSchema(i); if (arsTest.Name == DYNAMO_TEMP_CURVES_SCHEMA) { schemaId = i; break; } } } else { var ars = new AnalysisResultSchema(DYNAMO_TEMP_CURVES_SCHEMA, "Temporary curves from Dynamo."); schemaId = SpatialFieldManager.RegisterResult(ars); } Transform trf = Transform.Identity; //http://thebuildingcoder.typepad.com/blog/2012/09/sphere-creation-for-avf-and-filtering.html#3 var create = dynRevitSettings.Doc.Application.Application.Create; Transform t = curve.ComputeDerivatives(0, true); XYZ x = t.BasisX.Normalize(); XYZ y = t.BasisX.IsAlmostEqualTo(XYZ.BasisZ) ? t.BasisX.CrossProduct(XYZ.BasisY).Normalize() : t.BasisX.CrossProduct(XYZ.BasisZ).Normalize(); XYZ z = x.CrossProduct(y); Autodesk.Revit.DB.Ellipse arc1 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y, z, -Math.PI, 0); Autodesk.Revit.DB.Ellipse arc2 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y, z, 0, Math.PI); var pathLoop = new Autodesk.Revit.DB.CurveLoop(); pathLoop.Append(curve); var profileLoop = new Autodesk.Revit.DB.CurveLoop(); profileLoop.Append(arc1); profileLoop.Append(arc2); double curveDomain = curve.get_EndParameter(1) - curve.get_EndParameter(0); int idx = -1; var s = GeometryCreationUtilities.CreateSweptGeometry(pathLoop, 0, 0, new List <Autodesk.Revit.DB.CurveLoop> { profileLoop }); foreach (Face face in s.Faces) { //divide the V domain by the number of incoming BoundingBoxUV domain = face.GetBoundingBox(); double vSpan = domain.Max.V - domain.Min.V; //analysis values idx = SpatialFieldManager.AddSpatialFieldPrimitive(face, trf); //a list to hold the analysis points IList <UV> uvPts = new List <UV>(); //a list to hold the analysis values IList <ValueAtPoint> valList = new List <ValueAtPoint>(); //int count = nvals.Count(); //this is creating a lot of sample points, but if we used less //sampling points, AVF would draw the two surfaces as if there was a hard //edge between them. this provides a better blend. int count = 10; for (int i = 0; i < count; i++) { //get a UV point on the face //find its XYZ location and project to //the underlying curve. find the value which corresponds //to the location on the curve var uv = new UV(domain.Min.U, domain.Min.V + vSpan / count * (double)i); var uv1 = new UV(domain.Max.U, domain.Min.V + vSpan / count * (double)i); uvPts.Add(uv); uvPts.Add(uv1); XYZ facePt = face.Evaluate(uv); IntersectionResult ir = curve.Project(facePt); double curveParam = curve.ComputeNormalizedParameter(ir.Parameter); if (curveParam < 0) { curveParam = 0; } if (curveParam > 1) { curveParam = 1; } var valueIndex = (int)Math.Floor(curveParam * (double)nvals.Count()); if (valueIndex >= nvals.Count()) { valueIndex = nvals.Count() - 1; } //create list of values at this point - currently supporting only one //var doubleList = new List<double> { nvals.ElementAt(i) }; var doubleList = new List <double> { nvals.ElementAt(valueIndex) }; //add value at point object containing the value list valList.Add(new ValueAtPoint(doubleList)); valList.Add(new ValueAtPoint(doubleList)); } var pnts = new FieldDomainPointsByUV(uvPts); var vals = new FieldValues(valList); SpatialFieldManager.UpdateSpatialFieldPrimitive( idx, pnts, vals, schemaId); PastResultIds.Add(idx); } return(Value.NewNumber(idx)); }
public override void Evaluate(FSharpList <Value> args, Dictionary <PortData, Value> outPuts) { var crv = (Curve)((Value.Container)args[0]).Item; Face face = null; Autodesk.Revit.DB.Plane thisPlane = null; var geo = ((Value.Container)args[1]).Item; if (geo is Face) { face = geo as Face; } else if (geo is Autodesk.Revit.DB.Plane) { #region plane processing thisPlane = geo as Autodesk.Revit.DB.Plane; // tesselate curve and find uv envelope in projection to the plane IList <XYZ> tessCurve = crv.Tessellate(); var curvePointEnum = tessCurve.GetEnumerator(); var corner1 = new XYZ(); var corner2 = new XYZ(); bool cornersSet = false; for (; curvePointEnum.MoveNext();) { if (!cornersSet) { corner1 = curvePointEnum.Current; corner2 = curvePointEnum.Current; cornersSet = true; } else { for (int coord = 0; coord < 3; coord++) { if (corner1[coord] > curvePointEnum.Current[coord]) { corner1 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner1[coord], coord == 1 ? curvePointEnum.Current[coord] : corner1[coord], coord == 2 ? curvePointEnum.Current[coord] : corner1[coord]); } if (corner2[coord] < curvePointEnum.Current[coord]) { corner2 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner2[coord], coord == 1 ? curvePointEnum.Current[coord] : corner2[coord], coord == 2 ? curvePointEnum.Current[coord] : corner2[coord]); } } } } double dist1 = thisPlane.Origin.DistanceTo(corner1); double dist2 = thisPlane.Origin.DistanceTo(corner2); double sizeRect = 2.0 * (dist1 + dist2) + 100.0; var cLoop = new Autodesk.Revit.DB.CurveLoop(); for (int index = 0; index < 4; index++) { double coord0 = (index == 0 || index == 3) ? -sizeRect : sizeRect; double coord1 = (index < 2) ? -sizeRect : sizeRect; XYZ pnt0 = thisPlane.Origin + coord0 * thisPlane.XVec + coord1 * thisPlane.YVec; double coord3 = (index < 2) ? sizeRect : -sizeRect; double coord4 = (index == 0 || index == 3) ? -sizeRect : sizeRect; XYZ pnt1 = thisPlane.Origin + coord3 * thisPlane.XVec + coord4 * thisPlane.YVec; Line cLine = dynRevitSettings.Revit.Application.Create.NewLineBound(pnt0, pnt1); cLoop.Append(cLine); } var listCLoops = new List <Autodesk.Revit.DB.CurveLoop> { cLoop }; Solid tempSolid = GeometryCreationUtilities.CreateExtrusionGeometry(listCLoops, thisPlane.Normal, 100.0); //find right face FaceArray facesOfExtrusion = tempSolid.Faces; for (int indexFace = 0; indexFace < facesOfExtrusion.Size; indexFace++) { Face faceAtIndex = facesOfExtrusion.get_Item(indexFace); if (faceAtIndex is PlanarFace) { var pFace = faceAtIndex as PlanarFace; if (Math.Abs(thisPlane.Normal.DotProduct(pFace.Normal)) < 0.99) { continue; } if (Math.Abs(thisPlane.Normal.DotProduct(thisPlane.Origin - pFace.Origin)) > 0.1) { continue; } face = faceAtIndex; break; } } if (face == null) { throw new Exception("Curve Face Intersection could not process supplied Plane."); } #endregion } IntersectionResultArray xsects; var result = face.Intersect(crv, out xsects); //var xsect_results = FSharpList<Value>.Empty; var xsect_xyzs = FSharpList <Value> .Empty; var xsect_face_uvs = FSharpList <Value> .Empty; var xsect_params = FSharpList <Value> .Empty; var xsect_edges = FSharpList <Value> .Empty; var xsect_edge_params = FSharpList <Value> .Empty; var results = FSharpList <Value> .Empty; if (xsects != null) { foreach (IntersectionResult ir in xsects) { var xsect = FSharpList <Value> .Empty; try { xsect_edge_params = FSharpList <Value> .Cons(Value.NewNumber(ir.EdgeParameter), xsect_edge_params); } catch { xsect_edge_params = FSharpList <Value> .Cons(Value.NewNumber(0), xsect_edge_params); } xsect_edges = FSharpList <Value> .Cons(Value.NewContainer(ir.EdgeObject), xsect_edges); xsect_params = FSharpList <Value> .Cons(Value.NewNumber(ir.Parameter), xsect_params); if (thisPlane != null) { UV planeUV = new UV(thisPlane.XVec.DotProduct(ir.XYZPoint - thisPlane.Origin), thisPlane.YVec.DotProduct(ir.XYZPoint - thisPlane.Origin)); xsect_face_uvs = FSharpList <Value> .Cons(Value.NewContainer(planeUV), xsect_face_uvs); } else { xsect_face_uvs = FSharpList <Value> .Cons(Value.NewContainer(ir.UVPoint), xsect_face_uvs); } xsect_xyzs = FSharpList <Value> .Cons(Value.NewContainer(ir.XYZPoint), xsect_xyzs); //xsect_results = FSharpList<Value>.Cons(Value.NewList(xsect), xsect_results); } } outPuts[_edgeTPort] = Value.NewList(xsect_edge_params); outPuts[_edgePort] = Value.NewList(xsect_edges); outPuts[_tPort] = Value.NewList(xsect_params); outPuts[_uvPort] = Value.NewList(xsect_face_uvs); outPuts[_xyzPort] = Value.NewList(xsect_xyzs); outPuts[_resultPort] = Value.NewString(result.ToString()); }
public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { var pathLoop = CurveLoopFromContainer((FScheme.Value.Container)args[0]); int attachementIndex = (int)((FScheme.Value.Number)args[1]).Item; double attachementPar = ((FScheme.Value.Number)args[2]).Item; Autodesk.Revit.DB.CurveLoop profileLoop = (Autodesk.Revit.DB.CurveLoop)((FScheme.Value.Container)args[3]).Item; List<Autodesk.Revit.DB.CurveLoop> loopList = new List<Autodesk.Revit.DB.CurveLoop>(); if (profileLoop.HasPlane()) { Autodesk.Revit.DB.Plane profileLoopPlane = profileLoop.GetPlane(); Autodesk.Revit.DB.CurveLoopIterator CLiter = pathLoop.GetCurveLoopIterator(); for (int indexCurve = 0; indexCurve < attachementIndex && CLiter.MoveNext(); indexCurve++) { CLiter.MoveNext(); } Autodesk.Revit.DB.Curve pathCurve = CLiter.Current; if (pathCurve != null) { double angleTolerance = Math.PI / 1800.0; Transform pathTrf = pathCurve.ComputeDerivatives(attachementPar, false); XYZ pathDerivative = pathTrf.BasisX.Normalize(); double distAttachment = profileLoopPlane.Normal.DotProduct(profileLoopPlane.Origin - pathTrf.Origin); if (Math.Abs(distAttachment) > 0.000001 || Math.Abs(profileLoopPlane.Normal.DotProduct(pathDerivative)) < 1.0 - angleTolerance * angleTolerance ) { //put profile at proper plane double distOrigin = profileLoopPlane.Normal.DotProduct(profileLoopPlane.Origin); XYZ fromPoint = pathTrf.Origin; if (Math.Abs(distAttachment) > 0.000001 + Math.Abs(distOrigin)) fromPoint = (-distOrigin) * profileLoopPlane.Normal; else fromPoint = pathTrf.Origin - (pathTrf.Origin - profileLoopPlane.Origin).DotProduct(profileLoopPlane.Normal) * profileLoopPlane.Normal; XYZ fromVecOne = profileLoopPlane.Normal; if (fromVecOne.DotProduct(pathDerivative) < -angleTolerance) fromVecOne = -fromVecOne; XYZ toVecOne = pathDerivative; XYZ fromVecTwo = XYZ.BasisZ.CrossProduct(fromVecOne); if (fromVecTwo.IsZeroLength()) fromVecTwo = XYZ.BasisX; else fromVecTwo = fromVecTwo.Normalize(); XYZ toVecTwo = XYZ.BasisZ.CrossProduct(pathDerivative); if (toVecTwo.IsZeroLength()) toVecTwo = XYZ.BasisX; else toVecTwo = toVecTwo.Normalize(); if (toVecTwo.DotProduct(fromVecTwo) < -angleTolerance) toVecTwo = -toVecTwo; Transform trfToAttach = Transform.CreateTranslation(pathTrf.Origin); trfToAttach.BasisX = toVecOne; trfToAttach.BasisY = toVecTwo; trfToAttach.BasisZ = toVecOne.CrossProduct(toVecTwo); Transform trfToProfile = Transform.CreateTranslation(fromPoint); trfToProfile.BasisX = fromVecOne; trfToProfile.BasisY = fromVecTwo; trfToProfile.BasisZ = fromVecOne.CrossProduct(fromVecTwo); Transform trfFromProfile = trfToProfile.Inverse; Transform combineTrf = trfToAttach.Multiply(trfFromProfile); //now get new curve loop Autodesk.Revit.DB.CurveLoop transformedCurveLoop = new Autodesk.Revit.DB.CurveLoop(); Autodesk.Revit.DB.CurveLoopIterator CLiterT = profileLoop.GetCurveLoopIterator(); for (; CLiterT.MoveNext(); ) { Curve curCurve = CLiterT.Current; Curve curCurveTransformed = curCurve.CreateTransformed(combineTrf); transformedCurveLoop.Append(curCurveTransformed); } profileLoop = transformedCurveLoop; } } } loopList.Add(profileLoop); Solid result = GeometryCreationUtilities.CreateSweptGeometry(pathLoop, attachementIndex, attachementPar, loopList); return FScheme.Value.NewContainer(result); }
public static Autodesk.Revit.DB.CurveLoop CurveLoopFromContainer(FScheme.Value.Container curveOrCurveLoop) { var pathLoopBoxed = curveOrCurveLoop.Item; Autodesk.Revit.DB.CurveLoop curveLoop; var loop = pathLoopBoxed as Autodesk.Revit.DB.CurveLoop; if (loop != null) { curveLoop = loop; } else { curveLoop = new Autodesk.Revit.DB.CurveLoop(); curveLoop.Append((Autodesk.Revit.DB.Curve)pathLoopBoxed); } return curveLoop; }
public static Solid AlignedBoxByTwoCorners(XYZ bottomInput, XYZ topInput) { XYZ top, bottom; if (bottomInput.Z > topInput.Z) { top = bottomInput; bottom = topInput; } else { top = topInput; bottom = bottomInput; } // obtain coordinates of base rectangle var p0 = bottom; var p1 = p0 + new XYZ(top.X - bottom.X, 0, 0); var p2 = p1 + new XYZ(0, top.Y - bottom.Y, 0); var p3 = p2 - new XYZ(top.X - bottom.X, 0, 0); // form edges of base rect var l1 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p0, p1); var l2 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p1, p2); var l3 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p2, p3); var l4 = dynRevitSettings.Doc.Application.Application.Create.NewLineBound(p3, p0); // form curve loop from lines of base rect var cl = new Autodesk.Revit.DB.CurveLoop(); cl.Append(l1); cl.Append(l2); cl.Append(l3); cl.Append(l4); // get height of box var height = top.Z - bottom.Z; // extrude the curve and return return GeometryCreationUtilities.CreateExtrusionGeometry(new List<Autodesk.Revit.DB.CurveLoop>() { cl }, XYZ.BasisZ, height); }
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; }
public static Face buildFaceOnPlaneByCurveExtensions(Curve crv, Autodesk.Revit.DB.Plane thisPlane) { Face face = null; // tesselate curve and find uv envelope in projection to the plane IList<XYZ> tessCurve = crv.Tessellate(); var curvePointEnum = tessCurve.GetEnumerator(); var corner1 = new XYZ(); var corner2 = new XYZ(); bool cornersSet = false; for (; curvePointEnum.MoveNext(); ) { if (!cornersSet) { corner1 = curvePointEnum.Current; corner2 = curvePointEnum.Current; cornersSet = true; } else { for (int coord = 0; coord < 3; coord++) { if (corner1[coord] > curvePointEnum.Current[coord]) corner1 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner1[coord], coord == 1 ? curvePointEnum.Current[coord] : corner1[coord], coord == 2 ? curvePointEnum.Current[coord] : corner1[coord]); if (corner2[coord] < curvePointEnum.Current[coord]) corner2 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner2[coord], coord == 1 ? curvePointEnum.Current[coord] : corner2[coord], coord == 2 ? curvePointEnum.Current[coord] : corner2[coord]); } } } double dist1 = thisPlane.Origin.DistanceTo(corner1); double dist2 = thisPlane.Origin.DistanceTo(corner2); double sizeRect = 2.0 * (dist1 + dist2) + 100.0; var cLoop = new Autodesk.Revit.DB.CurveLoop(); for (int index = 0; index < 4; index++) { double coord0 = (index == 0 || index == 3) ? -sizeRect : sizeRect; double coord1 = (index < 2) ? -sizeRect : sizeRect; XYZ pnt0 = thisPlane.Origin + coord0 * thisPlane.XVec + coord1 * thisPlane.YVec; double coord3 = (index < 2) ? sizeRect : -sizeRect; double coord4 = (index == 0 || index == 3) ? -sizeRect : sizeRect; XYZ pnt1 = thisPlane.Origin + coord3 * thisPlane.XVec + coord4 * thisPlane.YVec; Line cLine = dynRevitSettings.Revit.Application.Create.NewLineBound(pnt0, pnt1); cLoop.Append(cLine); } var listCLoops = new List<Autodesk.Revit.DB.CurveLoop> { cLoop }; Solid tempSolid = GeometryCreationUtilities.CreateExtrusionGeometry(listCLoops, thisPlane.Normal, 100.0); //find right face FaceArray facesOfExtrusion = tempSolid.Faces; for (int indexFace = 0; indexFace < facesOfExtrusion.Size; indexFace++) { Face faceAtIndex = facesOfExtrusion.get_Item(indexFace); if (faceAtIndex is PlanarFace) { var pFace = faceAtIndex as PlanarFace; if (Math.Abs(thisPlane.Normal.DotProduct(pFace.Normal)) < 0.99) continue; if (Math.Abs(thisPlane.Normal.DotProduct(thisPlane.Origin - pFace.Origin)) > 0.1) continue; face = faceAtIndex; break; } } if (face == null) throw new Exception("Curve Face Intersection could not process supplied Plane."); return face; }
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 static Face buildFaceOnPlaneByCurveExtensions(Curve crv, Autodesk.Revit.DB.Plane thisPlane) { Face face = null; // tesselate curve and find uv envelope in projection to the plane IList <XYZ> tessCurve = crv.Tessellate(); var curvePointEnum = tessCurve.GetEnumerator(); var corner1 = new XYZ(); var corner2 = new XYZ(); bool cornersSet = false; for (; curvePointEnum.MoveNext();) { if (!cornersSet) { corner1 = curvePointEnum.Current; corner2 = curvePointEnum.Current; cornersSet = true; } else { for (int coord = 0; coord < 3; coord++) { if (corner1[coord] > curvePointEnum.Current[coord]) { corner1 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner1[coord], coord == 1 ? curvePointEnum.Current[coord] : corner1[coord], coord == 2 ? curvePointEnum.Current[coord] : corner1[coord]); } if (corner2[coord] < curvePointEnum.Current[coord]) { corner2 = new XYZ(coord == 0 ? curvePointEnum.Current[coord] : corner2[coord], coord == 1 ? curvePointEnum.Current[coord] : corner2[coord], coord == 2 ? curvePointEnum.Current[coord] : corner2[coord]); } } } } double dist1 = thisPlane.Origin.DistanceTo(corner1); double dist2 = thisPlane.Origin.DistanceTo(corner2); double sizeRect = 2.0 * (dist1 + dist2) + 100.0; var cLoop = new Autodesk.Revit.DB.CurveLoop(); for (int index = 0; index < 4; index++) { double coord0 = (index == 0 || index == 3) ? -sizeRect : sizeRect; double coord1 = (index < 2) ? -sizeRect : sizeRect; XYZ pnt0 = thisPlane.Origin + coord0 * thisPlane.XVec + coord1 * thisPlane.YVec; double coord3 = (index < 2) ? sizeRect : -sizeRect; double coord4 = (index == 0 || index == 3) ? -sizeRect : sizeRect; XYZ pnt1 = thisPlane.Origin + coord3 * thisPlane.XVec + coord4 * thisPlane.YVec; Line cLine = dynRevitSettings.Revit.Application.Create.NewLineBound(pnt0, pnt1); cLoop.Append(cLine); } var listCLoops = new List <Autodesk.Revit.DB.CurveLoop> { cLoop }; Solid tempSolid = GeometryCreationUtilities.CreateExtrusionGeometry(listCLoops, thisPlane.Normal, 100.0); //find right face FaceArray facesOfExtrusion = tempSolid.Faces; for (int indexFace = 0; indexFace < facesOfExtrusion.Size; indexFace++) { Face faceAtIndex = facesOfExtrusion.get_Item(indexFace); if (faceAtIndex is PlanarFace) { var pFace = faceAtIndex as PlanarFace; if (Math.Abs(thisPlane.Normal.DotProduct(pFace.Normal)) < 0.99) { continue; } if (Math.Abs(thisPlane.Normal.DotProduct(thisPlane.Origin - pFace.Origin)) > 0.1) { continue; } face = faceAtIndex; break; } } if (face == null) { throw new Exception("Curve Face Intersection could not process supplied Plane."); } return(face); }
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)); } 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]); var bestFitPlane = Autodesk.DesignScript.Geometry.Plane.ByBestFitThroughPoints(xyzs.ToPoints(false)); return bestFitPlane.ToPlane(false); }