/// <summary> /// Creates a new <see cref="LineStyle"/> instance. /// </summary> /// <param name="name">The line style name.</param> /// <param name="isCurved">The flag indicating whether line is curved.</param> /// <param name="curvature">The line curvature.</param> /// <param name="curveOrientation">The curve orientation.</param> /// <param name="fixedLength">The line style fixed length.</param> /// <returns>The new instance of the <see cref="LineStyle"/> class.</returns> public static LineStyle Create( string name = "", bool isCurved = false, double curvature = 50.0, CurveOrientation curveOrientation = CurveOrientation.Auto, LineFixedLength fixedLength = null) { return(new LineStyle() { Name = name, IsCurved = isCurved, Curvature = curvature, CurveOrientation = curveOrientation, FixedLength = fixedLength ?? LineFixedLength.Create() }); }
/// <summary> /// Creates a new <see cref="LineStyle"/> instance. /// </summary> /// <param name="name">The line style name.</param> /// <param name="isCurved">The flag indicating whether line is curved.</param> /// <param name="curvature">The line curvature.</param> /// <param name="curveOrientation">The curve orientation.</param> /// <param name="fixedLength">The line style fixed length.</param> /// <returns>The new instance of the <see cref="LineStyle"/> class.</returns> public static LineStyle Create( string name = "", bool isCurved = false, double curvature = 50.0, CurveOrientation curveOrientation = CurveOrientation.Auto, LineFixedLength fixedLength = null) { return new LineStyle() { Name = name, IsCurved = isCurved, Curvature = curvature, CurveOrientation = curveOrientation, FixedLength = fixedLength ?? LineFixedLength.Create() }; }
private Curve InnerLoop(Curve boundary, double offset) { CurveOrientation ot = boundary.ClosedCurveOrientation(Plane.WorldXY); double offsetDistance = offset; var segments = boundary.DuplicateSegments(); for (int i = 0; i < segments.Length; i++) { Vector3d v = segments[i].TangentAtStart; v.Rotate(-Math.PI / 2, Vector3d.ZAxis); Curve temp = segments[i].DuplicateCurve(); temp.Translate(v * offsetDistance); segments[i] = temp; } List <Point3d> toPoly = new List <Point3d>(); for (int i = 0; i < segments.Length; i++) { int j = (i + 1) % segments.Length; Line l1 = new Line(segments[i].PointAtStart, segments[i].PointAtEnd); Line l2 = new Line(segments[j].PointAtStart, segments[j].PointAtEnd); double p1; double p2; Rhino.Geometry.Intersect.Intersection.LineLine(l1, l2, out p1, out p2); toPoly.Add(l1.PointAt(p1)); } toPoly.Add(toPoly[0]); Curve merged = new Polyline(toPoly).ToNurbsCurve(); var intersection = Rhino.Geometry.Intersect.Intersection.CurveSelf(merged, 0); var parameters = intersection.Select(n => n.ParameterA).ToList(); parameters.AddRange(intersection.Select(n => n.ParameterB)); var spltd = merged.Split(parameters); var joined = CommonFunc.NewJoin(spltd); return(joined.Where(n => n.ClosedCurveOrientation(Plane.WorldXY) == ot).ToList()[0]); }
private SKPath CreateCurveGeometry(SKPoint p0, SKPoint p1, double curvature, CurveOrientation orientation, PointAlignment pt0a, PointAlignment pt1a) { var curveGeometry = new SKPath(); curveGeometry.MoveTo(new SKPoint((float)p0.X, (float)p0.Y)); double p0x = p0.X; double p0y = p0.Y; double p1x = p1.X; double p1y = p1.Y; LineShapeExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt0a, pt1a, ref p0x, ref p0y, ref p1x, ref p1y); var point1 = new SKPoint((float)p0x, (float)p0y); var point2 = new SKPoint((float)p1x, (float)p1y); var point3 = new SKPoint(p1.X, p1.Y); curveGeometry.CubicTo(point1, point2, point3); return(curveGeometry); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { ///Gather GHA inputs Curve boundary = null; DA.GetData <Curve>(0, ref boundary); string osmFilePath = string.Empty; DA.GetData <string>("OSM Data Location", ref osmFilePath); //string userSRStext = "WGS84"; //DA.GetData<string>(2, ref userSRStext); List <string> filterWords = new List <string>(); DA.GetDataList <string>(2, filterWords); List <string> filterKeyValue = new List <string>(); DA.GetDataList <string>(3, filterKeyValue); Transform xformToMetric = new Transform(Rhino.RhinoMath.UnitScale(RhinoDoc.ActiveDoc.ModelUnitSystem, Rhino.UnitSystem.Meters)); Transform xformFromMetric = new Transform(Rhino.RhinoMath.UnitScale(Rhino.UnitSystem.Meters, RhinoDoc.ActiveDoc.ModelUnitSystem)); ///Declare trees Rectangle3d recs = new Rectangle3d(); GH_Structure <GH_String> fieldNames = new GH_Structure <GH_String>(); GH_Structure <GH_String> fieldValues = new GH_Structure <GH_String>(); GH_Structure <IGH_GeometricGoo> geometryGoo = new GH_Structure <IGH_GeometricGoo>(); GH_Structure <IGH_GeometricGoo> buildingGoo = new GH_Structure <IGH_GeometricGoo>(); Point3d max = new Point3d(); Point3d min = new Point3d(); if (boundary != null) { Point3d maxM = boundary.GetBoundingBox(true).Corner(true, false, true); max = Heron.Convert.XYZToWGS(maxM); Point3d minM = boundary.GetBoundingBox(true).Corner(false, true, true); min = Heron.Convert.XYZToWGS(minM); } /// get extents (why is this not part of OsmSharp?) System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.Load(osmFilePath); if (xdoc.Root.Element("bounds") != null) { double minlat = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlat").Value); double minlon = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlon").Value); double maxlat = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlat").Value); double maxlon = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlon").Value); Point3d boundsMin = Heron.Convert.WGSToXYZ(new Point3d(minlon, minlat, 0)); Point3d boundsMax = Heron.Convert.WGSToXYZ(new Point3d(maxlon, maxlat, 0)); recs = new Rectangle3d(Plane.WorldXY, boundsMin, boundsMax); } else { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Cannot determine the extents of the OSM file. A 'bounds' element may not be present in the file."); } using (var fileStreamSource = File.OpenRead(osmFilePath)) { /// create a source. OsmSharp.Streams.XmlOsmStreamSource source = new OsmSharp.Streams.XmlOsmStreamSource(fileStreamSource); /// filter by bounding box OsmSharp.Streams.OsmStreamSource sourceClipped = source; if (clipped) { sourceClipped = source.FilterBox((float)max.X, (float)max.Y, (float)min.X, (float)min.Y, true); } /// create a dictionary of elements OsmSharp.Db.Impl.MemorySnapshotDb sourceMem = new OsmSharp.Db.Impl.MemorySnapshotDb(sourceClipped); /// filter the source var filtered = from osmGeos in sourceClipped where osmGeos.Tags != null select osmGeos; if (filterWords.Any()) { filtered = from osmGeos in filtered where osmGeos.Tags.ContainsAnyKey(filterWords) select osmGeos; } if (filterKeyValue.Any()) { List <Tag> tags = new List <Tag>(); foreach (string term in filterKeyValue) { string[] kv = term.Split(','); Tag tag = new Tag(kv[0], kv[1]); tags.Add(tag); } filtered = from osmGeos in filtered where osmGeos.Tags.Intersect(tags).Any() select osmGeos; } source.Dispose(); /// loop over all objects and count them. int nodes = 0, ways = 0, relations = 0; foreach (OsmSharp.OsmGeo osmGeo in filtered) { //NODES if (osmGeo.Type == OsmGeoType.Node) { OsmSharp.Node n = (OsmSharp.Node)osmGeo; GH_Path nodesPath = new GH_Path(0, nodes); //populate Fields and Values for each node fieldNames.AppendRange(GetKeys(osmGeo), nodesPath); fieldValues.AppendRange(GetValues(osmGeo), nodesPath); //get geometry for node Point3d nPoint = Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0)); geometryGoo.Append(new GH_Point(nPoint), nodesPath); //increment nodes nodes++; } //////////////////////////////////////////////////////////// //WAYS if (osmGeo.Type == OsmGeoType.Way) { OsmSharp.Way w = (OsmSharp.Way)osmGeo; GH_Path waysPath = new GH_Path(1, ways); //populate Fields and Values for each way fieldNames.AppendRange(GetKeys(osmGeo), waysPath); fieldValues.AppendRange(GetValues(osmGeo), waysPath); //get polyline geometry for way List <Point3d> wayNodes = new List <Point3d>(); foreach (long j in w.Nodes) { OsmSharp.Node n = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, j); wayNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0))); } PolylineCurve pL = new PolylineCurve(wayNodes); if (pL.IsClosed) { //create base surface Brep[] breps = Brep.CreatePlanarBreps(pL, DocumentTolerance()); geometryGoo.Append(new GH_Brep(breps[0]), waysPath); } else { geometryGoo.Append(new GH_Curve(pL), waysPath); } //building massing if (w.Tags.ContainsKey("building") || w.Tags.ContainsKey("building:part")) { if (pL.IsClosed) { CurveOrientation orient = pL.ClosedCurveOrientation(Plane.WorldXY); if (orient != CurveOrientation.CounterClockwise) { pL.Reverse(); } Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo)); hVec.Transform(xformFromMetric); Extrusion ex = Extrusion.Create(pL, hVec.Z, true); IGH_GeometricGoo bldgGoo = GH_Convert.ToGeometricGoo(ex); buildingGoo.Append(bldgGoo, waysPath); } } //increment ways ways++; } /////////////////////////////////////////////////////////// //RELATIONS if (osmGeo.Type == OsmGeoType.Relation) { OsmSharp.Relation r = (OsmSharp.Relation)osmGeo; GH_Path relationPath = new GH_Path(2, relations); //populate Fields and Values for each relation fieldNames.AppendRange(GetKeys(osmGeo), relationPath); fieldValues.AppendRange(GetValues(osmGeo), relationPath); List <Curve> pLines = new List <Curve>(); // start members loop for (int mem = 0; mem < r.Members.Length; mem++) { GH_Path memberPath = new GH_Path(2, relations, mem); OsmSharp.RelationMember rMem = r.Members[mem]; OsmSharp.OsmGeo rMemGeo = sourceMem.Get(rMem.Type, rMem.Id); if (rMemGeo != null) { //get geometry for node if (rMemGeo.Type == OsmGeoType.Node) { long memNodeId = rMem.Id; OsmSharp.Node memN = (OsmSharp.Node)sourceMem.Get(rMem.Type, rMem.Id); Point3d memPoint = Heron.Convert.WGSToXYZ(new Point3d((double)memN.Longitude, (double)memN.Latitude, 0)); geometryGoo.Append(new GH_Point(memPoint), memberPath); } //get geometry for way if (rMem.Type == OsmGeoType.Way) { long memWayId = rMem.Id; OsmSharp.Way memWay = (OsmSharp.Way)rMemGeo; //get polyline geometry for way List <Point3d> memNodes = new List <Point3d>(); foreach (long memNodeId in memWay.Nodes) { OsmSharp.Node memNode = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, memNodeId); memNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)memNode.Longitude, (double)memNode.Latitude, 0))); } PolylineCurve memPolyline = new PolylineCurve(memNodes); geometryGoo.Append(new GH_Curve(memPolyline.ToNurbsCurve()), memberPath); CurveOrientation orient = memPolyline.ClosedCurveOrientation(Plane.WorldXY); if (orient != CurveOrientation.CounterClockwise) { memPolyline.Reverse(); } pLines.Add(memPolyline.ToNurbsCurve()); } //get nested relations if (rMem.Type == OsmGeoType.Relation) { ///not sure if this is needed } } } //end members loop bool allClosed = true; foreach (Curve pc in pLines) { if (!pc.IsClosed) { allClosed = false; } } if (pLines.Count > 0 && allClosed) { //create base surface Brep[] breps = Brep.CreatePlanarBreps(pLines, DocumentTolerance()); geometryGoo.RemovePath(relationPath); foreach (Brep b in breps) { geometryGoo.Append(new GH_Brep(b), relationPath); //building massing if (r.Tags.ContainsKey("building") || r.Tags.ContainsKey("building:part")) { Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo)); hVec.Transform(xformFromMetric); //create extrusion from base surface buildingGoo.Append(new GH_Brep(Brep.CreateFromOffsetFace(b.Faces[0], hVec.Z, DocumentTolerance(), false, true)), relationPath); } } } //increment relations relations++; } ///end relation loop } ///end filtered loop } ///end osm source loop if (recs.IsValid) { DA.SetData(0, recs); } DA.SetDataTree(1, fieldNames); DA.SetDataTree(2, fieldValues); DA.SetDataTree(3, geometryGoo); DA.SetDataTree(4, buildingGoo); } ///end SolveInstance
/// <summary> /// Get curved line bezier curve control points. /// </summary> /// <param name="orientation">The curved line orientation.</param> /// <param name="offset">The curved line offset.</param> /// <param name="p1a">The line start point alignment.</param> /// <param name="p2a">The line end point alignment.</param> /// <param name="p1x">The adjusted X coordinate for curve start control point.</param> /// <param name="p1y">The adjusted Y coordinate for curve start control point.</param> /// <param name="p2x">The adjusted X coordinate for curve end control point.</param> /// <param name="p2y">The adjusted Y coordinate for curve end control point.</param> public static void GetCurvedLineBezierControlPoints(CurveOrientation orientation, double offset, PointAlignment p1a, PointAlignment p2a, ref double p1x, ref double p1y, ref double p2x, ref double p2y) { if (orientation == CurveOrientation.Auto) { switch (p1a) { case PointAlignment.None: { switch (p2a) { case PointAlignment.None: break; case PointAlignment.Left: p2x -= offset; p1x += offset; break; case PointAlignment.Right: p2x += offset; p1x -= offset; break; case PointAlignment.Top: p2y -= offset; p1y += offset; break; case PointAlignment.Bottom: p2y += offset; p1y -= offset; break; } } break; case PointAlignment.Left: { switch (p2a) { case PointAlignment.None: p1x -= offset; p2x += offset; break; case PointAlignment.Left: p1x -= offset; p2x -= offset; break; case PointAlignment.Right: p1x -= offset; p2x += offset; break; case PointAlignment.Top: p1x -= offset; break; case PointAlignment.Bottom: p2y += offset; break; } } break; case PointAlignment.Right: { switch (p2a) { case PointAlignment.None: p1x += offset; p2x -= offset; break; case PointAlignment.Left: p1x += offset; p2x -= offset; break; case PointAlignment.Right: p1x += offset; p2x += offset; break; case PointAlignment.Top: p1x += offset; break; case PointAlignment.Bottom: p2y += offset; break; } } break; case PointAlignment.Top: { switch (p2a) { case PointAlignment.None: p1y -= offset; p2y += offset; break; case PointAlignment.Left: p2x -= offset; break; case PointAlignment.Right: p2x += offset; break; case PointAlignment.Top: p1y -= offset; p2y -= offset; break; case PointAlignment.Bottom: p1y -= offset; p2y += offset; break; } } break; case PointAlignment.Bottom: { switch (p2a) { case PointAlignment.None: p1y += offset; p2y -= offset; break; case PointAlignment.Left: p1y += offset; break; case PointAlignment.Right: p1y += offset; break; case PointAlignment.Top: p1y += offset; p2y -= offset; break; case PointAlignment.Bottom: p1y += offset; p2y += offset; break; } } break; } } else if (orientation == CurveOrientation.Horizontal) { p1x += offset; p2x -= offset; } else if (orientation == CurveOrientation.Vertical) { p1y += offset; p2y -= offset; } }
// <Custom additional code> //Calculation of 45° roof with differents valley //Type = 0 => Round : Constant slope (sand) //Type = 1 => Butt : Angular (roof) //Type = 2 => Square : Simple public List <Brep> SandDune(Polyline polyline, int type, bool isV6, bool parallel) { List <Brep> output = new List <Brep>(); //By default round type if (type < 0) { type = 0; } if (type > 2) { type = 0; } if (polyline != null) { double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance; bool isClosed = polyline.IsClosedWithinTolerance(tol); //Polyline is closed if not closed if (!isClosed) { polyline.Add(polyline[0]); } //Just in case polyline.CollapseShortSegments(tol * 2); Curve polylineCurve = polyline.ToNurbsCurve(); //Definition of orientation of polyline int orientation = 1; if (isV6) { //CurveOrientation (inverted in RH5 vs RH6 // Undefined 0 Orientation is undefined. // Clockwise -1 The curve's orientation is clockwise in the xy plane. // CounterClockwise 1 The curve's orientation is counter clockwise in the xy plane CurveOrientation curveOrientation = polylineCurve.ClosedCurveOrientation(Plane.WorldXY); if (curveOrientation == CurveOrientation.Clockwise) { orientation = -1; } else { orientation = 1; } } else { //Use of classical surface calculation of polyline if (SurfaceOnXYplane(polyline) > 0) { orientation = -1; } else { orientation = 1; } } //Bounding box calculation in order to have the max horizontal distances for the roofs surfaces (before cut) BoundingBox bb = polylineCurve.GetBoundingBox(false); double maxLength = bb.Diagonal.Length; //List of brep representing the roof before cut List <Brep> breps = new List <Brep>(); //Side of roof for (int i = 0; i < (polyline.Count - 1); i++) { //Calculate direction of line Point3d p1 = polyline[i]; Point3d p2 = polyline[(i + 1)]; Vector3d direction12 = (p2 - p1) * orientation; direction12.Unitize(); //Calculate a perpendicular Vector3d perp12 = Vector3d.CrossProduct(direction12, Vector3d.ZAxis); perp12.Unitize(); //Because move is one unit horizontal (per12) + one unit in Z => 45° //if you want other angle put a coefficient on perp12 (0 => 90°) Vector3d move = perp12 + Vector3d.ZAxis; move *= maxLength; //Make a sweep var sweep = new Rhino.Geometry.SweepOneRail(); sweep.AngleToleranceRadians = RhinoDoc.ActiveDoc.ModelAngleToleranceRadians; sweep.ClosedSweep = false; sweep.SweepTolerance = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance; Brep[] sideBreps = sweep.PerformSweep(new LineCurve(p1, p1 + move), new LineCurve(p1, p2)); if (sideBreps.Length > 0) { breps.Add(sideBreps[0]); } } //Valley parts of the roof for (int i = 0; i < (polyline.Count - 1); i++) { //Calculate direction of line int index; if (i == 0) { index = polyline.Count - 2; } else { index = i - 1; } Point3d p1 = polyline[index]; Point3d p2 = polyline[i]; Point3d p3 = polyline[i + 1]; Vector3d direction12 = (p2 - p1); direction12.Unitize(); Vector3d direction23 = (p3 - p2); direction23.Unitize(); Brep rp = new Brep(); //Round type if (type == 0) { rp = ValleyRound(p2, direction12, direction23, maxLength, orientation); if (rp.IsValid) { breps.Add(rp); } } //Butt type if (type == 1) { Brep[] vv = ValleyButt(p2, direction12, direction23, maxLength, orientation); if (vv.Length >= 2) { if (vv[0].IsValid) { breps.Add(vv[0]); } if (vv[1].IsValid) { breps.Add(vv[1]); } } } //Square type if (type == 2) { rp = ValleySquare(p2, direction12, direction23, maxLength, orientation); if (rp.IsValid) { breps.Add(rp); } } } output = CutBreps(breps, tol, polylineCurve, parallel); } return(output); }
private static void DrawLineCurveInternal(AM.DrawingContext _dc, AM.Pen pen, bool isStroked, ref A.Point pt1, ref A.Point pt2, double curvature, CurveOrientation orientation, PointAlignment pt1a, PointAlignment pt2a) { if (isStroked) { var sg = new AM.StreamGeometry(); using (var sgc = sg.Open()) { sgc.BeginFigure(new A.Point(pt1.X, pt1.Y), false); double p1x = pt1.X; double p1y = pt1.Y; double p2x = pt2.X; double p2y = pt2.Y; LineShapeExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt1a, pt2a, ref p1x, ref p1y, ref p2x, ref p2y); sgc.CubicBezierTo( new A.Point(p1x, p1y), new A.Point(p2x, p2y), new A.Point(pt2.X, pt2.Y)); sgc.EndFigure(false); } _dc.DrawGeometry(null, pen, sg); } }
private static void DrawLineCurveInternal(XGraphics gfx, XPen pen, bool isStroked, ref XPoint pt1, ref XPoint pt2, double curvature, CurveOrientation orientation, Core2D.Shape.PointAlignment pt1a, Core2D.Shape.PointAlignment pt2a) { if (isStroked) { var path = new XGraphicsPath(); double p1x = pt1.X; double p1y = pt1.Y; double p2x = pt2.X; double p2y = pt2.Y; LineShapeExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt1a, pt2a, ref p1x, ref p1y, ref p2x, ref p2y); path.AddBezier( pt1.X, pt1.Y, p1x, p1y, p2x, p2y, pt2.X, pt2.Y); gfx.DrawPath(pen, path); } }
private AM.StreamGeometry CreateCurveGeometry(A.Point p0, A.Point p1, double curvature, CurveOrientation orientation, PointAlignment pt0a, PointAlignment pt1a) { var curveGeometry = new AM.StreamGeometry(); using (var geometryContext = curveGeometry.Open()) { geometryContext.BeginFigure(new A.Point(p0.X, p0.Y), false); double p0x = p0.X; double p0y = p0.Y; double p1x = p1.X; double p1y = p1.Y; LineShapeExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt0a, pt1a, ref p0x, ref p0y, ref p1x, ref p1y); var point1 = new A.Point(p0x, p0y); var point2 = new A.Point(p1x, p1y); var point3 = new A.Point(p1.X, p1.Y); geometryContext.CubicBezierTo(point1, point2, point3); geometryContext.EndFigure(false); } return(curveGeometry); }
private void DrawLineCurveInternal(SKCanvas canvas, SKPaint pen, bool isStroked, ref SKPoint pt1, ref SKPoint pt2, double curvature, CurveOrientation orientation, PointAlignment pt1a, PointAlignment pt2a) { if (isStroked) { using (var path = new SKPath()) { path.MoveTo(pt1.X, pt1.Y); double p1x = pt1.X; double p1y = pt1.Y; double p2x = pt2.X; double p2y = pt2.Y; XLineExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt1a, pt2a, ref p1x, ref p1y, ref p2x, ref p2y); path.CubicTo( (float)p1x, (float)p1y, (float)p2x, (float)p2y, pt2.X, pt2.Y); canvas.DrawPath(path, pen); } } }
/// <summary> /// Using clipper /// </summary> /// <param name="breps"></param> /// <param name="dist"></param> /// <returns></returns> public static List <Brep> BrepsToOffsetBreps(List <Brep> breps, double dist) { List <Brep> brepsOut = new List <Brep>(); //List<Polyline> polyOut2 = new List<Polyline>(); double tolerance = Units.ConvertFromMeter(0.01); var openType = new List <Polyline3D.OpenFilletType> { Polyline3D.OpenFilletType.Butt }; List <Polyline3D.ClosedFilletType> closedType = new List <Polyline3D.ClosedFilletType>() { Polyline3D.ClosedFilletType.Miter }; double miter = Units.ConvertFromMeter(0.5); for (int i = 0; i < breps.Count; i++) { List <Curve> allEdges = new List <Curve>(); if (dist > 0) { Curve[] innerEdges = Curve.JoinCurves(breps[i].DuplicateNakedEdgeCurves(false, true)); Curve[] outerEdges = Curve.JoinCurves(breps[i].DuplicateNakedEdgeCurves(true, false)); outerEdges[0].TryGetPlane(out Plane pln, tolerance); if (pln.ZAxis.Z < 0) { pln.Flip(); } List <Polyline> polylineInner = new List <Polyline>(); for (int j = 0; j < innerEdges.Length; j++) { innerEdges[j].TryGetPolyline(out Polyline polyEdge); if (polyEdge != null) { var crv = polyEdge.ToNurbsCurve(); CurveOrientation dir = crv.ClosedCurveOrientation(pln); if (dir == CurveOrientation.Clockwise) { polyEdge.Reverse(); } polylineInner.Add(polyEdge); //polyOut.Add(polyEdge); } } List <Polyline> polylineOuter = new List <Polyline>(); for (int j = 0; j < outerEdges.Length; j++) { outerEdges[j].TryGetPolyline(out Polyline polyEdge); if (polyEdge != null) { var crv = polyEdge.ToNurbsCurve(); CurveOrientation dir = crv.ClosedCurveOrientation(pln); if (dir == CurveOrientation.Clockwise) { polyEdge.Reverse(); } polylineOuter.Add(polyEdge); } } Polyline3D.Offset(polylineInner, openType, closedType, pln, tolerance, new List <double> { dist }, miter, arcTolerance: 0.25, outContour: out List <List <Polyline> > brepHoles, out _, EndType.etClosedLine); Polyline3D.Offset(polylineOuter, openType, closedType, pln, tolerance, new List <double> { dist }, miter, arcTolerance: 0.25, out _, outHoles: out List <List <Polyline> > brepEdges, EndType.etClosedLine); var holesCrvs = brepHoles.SelectMany(p => p).Select(p => (Curve)p.ToPolylineCurve()).ToList(); var edgeCrvs = brepEdges.SelectMany(p => p).Select(p => (Curve)p.ToPolylineCurve()).ToList(); var result = Polyline3D.Boolean(ClipType.ctDifference, brepEdges[0], brepHoles[0], pln, tolerance, true);//var polylinesB = Polyline3D.ConvertCurvesToPolyline(curvesB).ToList(); allEdges.AddRange(result.Select(p => (Curve)p.ToPolylineCurve()).ToList()); //polyOut2.AddRange(brepHoles.SelectMany(p => p)); //polyOut2.AddRange(brepEdges.SelectMany(p => p)); brepsOut.AddRange(InputGeometries.UpwardsPointingBrepsFromCurves(allEdges)); } else { brepsOut.Add(breps[i].TurnUp()); } } return(brepsOut); }
private void FindMajorEdgeOrientation(Curve polygon, ref double orientation, int numCategories, bool debug) { List <Curve> segments = polygon.DuplicateSegments().ToList(); CurveOrientation co = CurveOrientation.Clockwise; List <double> lengthTable = CreateTable(numCategories); Dictionary <int, int> curveTable = new Dictionary <int, int>(); Vector3d xyVector = Vector3d.XAxis; double angleBinSize = ((2.0 * Math.PI) / numCategories); if (numCategories < segments.Count) { numCategories = segments.Count; } for (int i = 0; i < segments.Count; i++) { if (segments[i].ClosedCurveOrientation() == co) { segments[i].Reverse(); } double currLength = segments[i].GetLength(); Vector3d segmentVector = Vector3d.Subtract(new Vector3d(segments[i].PointAtEnd), new Vector3d(segments[i].PointAtStart)); Vector3d cross = Vector3d.CrossProduct(xyVector, segmentVector); double currAngle = Vector3d.VectorAngle(segmentVector, xyVector, cross); int category = (int)(currAngle / angleBinSize); if (!curveTable.ContainsKey(category)) { curveTable[category] = i; } if (debug) { Rhino.RhinoApp.WriteLine("INDEX " + i.ToString()); Rhino.RhinoApp.WriteLine("ANGLE " + Rhino.RhinoMath.ToDegrees(currAngle).ToString()); Rhino.RhinoApp.WriteLine("CATEGORY " + category.ToString()); } lengthTable[category] += currLength; } // Find maximum element in length array double max = lengthTable.Max(); int argmax = Array.IndexOf(lengthTable.ToArray(), max); if (debug) { Rhino.RhinoApp.WriteLine("max " + max.ToString()); Rhino.RhinoApp.WriteLine("argmax " + argmax.ToString()); } orientation = argmax * ((2.0 * Math.PI) / numCategories); // Double-check curve orientation Curve maxCurve = segments[curveTable[argmax]]; Vector3d maxCurveVector = Vector3d.Subtract(new Vector3d(maxCurve.PointAtEnd), new Vector3d(maxCurve.PointAtStart)); Line checkLine = new Line(maxCurve.PointAtStart, xyVector); checkLine.Transform(Transform.Rotation(orientation, maxCurve.PointAtStart)); double angle = Vector3d.VectorAngle(maxCurveVector, checkLine.Direction); if (angle > angleBinSize) { orientation = Math.PI - orientation; } }
private static void DrawLineCurveInternal(Graphics gfx, Pen pen, bool isStroked, ref PointF pt1, ref PointF pt2, double curvature, CurveOrientation orientation, PointAlignment pt1a, PointAlignment pt2a) { if (isStroked) { double p1x = pt1.X; double p1y = pt1.Y; double p2x = pt2.X; double p2y = pt2.Y; XLineExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt1a, pt2a, ref p1x, ref p1y, ref p2x, ref p2y); gfx.DrawBezier( pen, pt1.X, pt1.Y, (float)p1x, (float)p1y, (float)p2x, (float)p2y, pt2.X, pt2.Y); } }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { ///Gather GHA inputs Curve boundary = null; DA.GetData <Curve>(0, ref boundary); string osmFilePath = string.Empty; DA.GetData <string>("OSM Data Location", ref osmFilePath); //string userSRStext = "WGS84"; //DA.GetData<string>(2, ref userSRStext); List <string> filterWords = new List <string>(); DA.GetDataList <string>(2, filterWords); List <string> filterKeyValue = new List <string>(); DA.GetDataList <string>(3, filterKeyValue); Transform xformToMetric = new Transform(scaleToMetric); Transform xformFromMetric = new Transform(scaleFromMetric); ///Declare trees Rectangle3d recs = new Rectangle3d(); GH_Structure <GH_String> fieldNames = new GH_Structure <GH_String>(); GH_Structure <GH_String> fieldValues = new GH_Structure <GH_String>(); GH_Structure <IGH_GeometricGoo> geometryGoo = new GH_Structure <IGH_GeometricGoo>(); GH_Structure <IGH_GeometricGoo> buildingGoo = new GH_Structure <IGH_GeometricGoo>(); Point3d max = new Point3d(); Point3d min = new Point3d(); if (boundary != null) { Point3d maxM = boundary.GetBoundingBox(true).Corner(true, false, true); max = Heron.Convert.XYZToWGS(maxM); Point3d minM = boundary.GetBoundingBox(true).Corner(false, true, true); min = Heron.Convert.XYZToWGS(minM); } /// get extents (why is this not part of OsmSharp?) System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.Load(osmFilePath); if (xdoc.Root.Element("bounds") != null) { double minlat = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlat").Value); double minlon = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlon").Value); double maxlat = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlat").Value); double maxlon = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlon").Value); Point3d boundsMin = Heron.Convert.WGSToXYZ(new Point3d(minlon, minlat, 0)); Point3d boundsMax = Heron.Convert.WGSToXYZ(new Point3d(maxlon, maxlat, 0)); recs = new Rectangle3d(Plane.WorldXY, boundsMin, boundsMax); } else { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Cannot determine the extents of the OSM file. A 'bounds' element may not be present in the file. " + "Try turning off clipping in this component's menu."); } using (var fileStreamSource = File.OpenRead(osmFilePath)) { /// create a source. OsmSharp.Streams.XmlOsmStreamSource source = new OsmSharp.Streams.XmlOsmStreamSource(fileStreamSource); /// filter by bounding box OsmSharp.Streams.OsmStreamSource sourceClipped = source; if (clipped) { sourceClipped = source.FilterBox((float)max.X, (float)max.Y, (float)min.X, (float)min.Y, true); } /// create a dictionary of elements OsmSharp.Db.Impl.MemorySnapshotDb sourceMem = new OsmSharp.Db.Impl.MemorySnapshotDb(sourceClipped); /// filter the source var filtered = from osmGeos in sourceClipped where osmGeos.Tags != null select osmGeos; if (filterWords.Any()) { filtered = from osmGeos in filtered where osmGeos.Tags.ContainsAnyKey(filterWords) select osmGeos; } if (filterKeyValue.Any()) { List <Tag> tags = new List <Tag>(); foreach (string term in filterKeyValue) { string[] kv = term.Split(','); Tag tag = new Tag(kv[0], kv[1]); tags.Add(tag); } filtered = from osmGeos in filtered where osmGeos.Tags.Intersect(tags).Any() select osmGeos; } source.Dispose(); /// loop over all objects and count them. int nodes = 0, ways = 0, relations = 0; Dictionary <PolylineCurve, GH_Path> bldgOutlines = new Dictionary <PolylineCurve, GH_Path>(); List <BuildingPart> buildingParts = new List <BuildingPart>(); foreach (OsmSharp.OsmGeo osmGeo in filtered) { //NODES if (osmGeo.Type == OsmGeoType.Node) { OsmSharp.Node n = (OsmSharp.Node)osmGeo; GH_Path nodesPath = new GH_Path(0, nodes); //populate Fields and Values for each node fieldNames.AppendRange(GetKeys(osmGeo), nodesPath); fieldValues.AppendRange(GetValues(osmGeo), nodesPath); //get geometry for node Point3d nPoint = Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0)); geometryGoo.Append(new GH_Point(nPoint), nodesPath); //increment nodes nodes++; } //////////////////////////////////////////////////////////// //WAYS if (osmGeo.Type == OsmGeoType.Way) { OsmSharp.Way w = (OsmSharp.Way)osmGeo; GH_Path waysPath = new GH_Path(1, ways); //populate Fields and Values for each way fieldNames.AppendRange(GetKeys(osmGeo), waysPath); fieldValues.AppendRange(GetValues(osmGeo), waysPath); //get polyline geometry for way List <Point3d> wayNodes = new List <Point3d>(); foreach (long j in w.Nodes) { OsmSharp.Node n = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, j); wayNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0))); } PolylineCurve pL = new PolylineCurve(wayNodes); if (pL.IsClosed) { //create base surface Brep[] breps = Brep.CreatePlanarBreps(pL, DocumentTolerance()); geometryGoo.Append(new GH_Brep(breps[0]), waysPath); } else { geometryGoo.Append(new GH_Curve(pL), waysPath); } //building massing if ((w.Tags.ContainsKey("building") || w.Tags.ContainsKey("building:part")))// && !w.Tags.ContainsKey("construction")) { if (pL.IsClosed) { ///Populate dictionary for sorting building parts later if (w.Tags.ContainsKey("building")) { bldgOutlines.Add(pL, waysPath); } CurveOrientation orient = pL.ClosedCurveOrientation(Plane.WorldXY); if (orient != CurveOrientation.CounterClockwise) { pL.Reverse(); } ///Move polylines to min height double minHeightWay = GetMinBldgHeight(osmGeo); Vector3d minVec = new Vector3d(0, 0, minHeightWay); //minVec.Transform(xformFromMetric); if (minHeightWay > 0.0) { var minHeightTranslate = Transform.Translation(minVec); pL.Transform(minHeightTranslate); } Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo) - minHeightWay); //hVec.Transform(xformFromMetric); Extrusion ex = Extrusion.Create(pL, hVec.Z, true); IGH_GeometricGoo bldgGoo = GH_Convert.ToGeometricGoo(ex); ///Save building parts for sorting later and remove part from geometry goo tree if (w.Tags.ContainsKey("building:part")) { BuildingPart bldgPart = new BuildingPart(pL, bldgGoo, fieldNames[waysPath], fieldValues[waysPath], osmGeo); buildingParts.Add(bldgPart); fieldNames.RemovePath(waysPath); fieldValues.RemovePath(waysPath); geometryGoo.RemovePath(waysPath); ways = ways - 1; } else { buildingGoo.Append(bldgGoo, waysPath); } } } //increment ways ways++; } /////////////////////////////////////////////////////////// //RELATIONS if (osmGeo.Type == OsmGeoType.Relation) { OsmSharp.Relation r = (OsmSharp.Relation)osmGeo; GH_Path relationPath = new GH_Path(2, relations); //populate Fields and Values for each relation fieldNames.AppendRange(GetKeys(osmGeo), relationPath); fieldValues.AppendRange(GetValues(osmGeo), relationPath); List <Curve> pLines = new List <Curve>(); // start members loop for (int mem = 0; mem < r.Members.Length; mem++) { GH_Path memberPath = new GH_Path(2, relations, mem); OsmSharp.RelationMember rMem = r.Members[mem]; OsmSharp.OsmGeo rMemGeo = sourceMem.Get(rMem.Type, rMem.Id); if (rMemGeo != null) { //get geometry for node if (rMemGeo.Type == OsmGeoType.Node) { long memNodeId = rMem.Id; OsmSharp.Node memN = (OsmSharp.Node)sourceMem.Get(rMem.Type, rMem.Id); Point3d memPoint = Heron.Convert.WGSToXYZ(new Point3d((double)memN.Longitude, (double)memN.Latitude, 0)); geometryGoo.Append(new GH_Point(memPoint), memberPath); } //get geometry for way if (rMem.Type == OsmGeoType.Way) { long memWayId = rMem.Id; OsmSharp.Way memWay = (OsmSharp.Way)rMemGeo; //get polyline geometry for way List <Point3d> memNodes = new List <Point3d>(); foreach (long memNodeId in memWay.Nodes) { OsmSharp.Node memNode = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, memNodeId); memNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)memNode.Longitude, (double)memNode.Latitude, 0))); } PolylineCurve memPolyline = new PolylineCurve(memNodes); geometryGoo.Append(new GH_Curve(memPolyline.ToNurbsCurve()), memberPath); CurveOrientation orient = memPolyline.ClosedCurveOrientation(Plane.WorldXY); if (orient != CurveOrientation.CounterClockwise) { memPolyline.Reverse(); } pLines.Add(memPolyline.ToNurbsCurve()); } //get nested relations if (rMem.Type == OsmGeoType.Relation) { ///not sure if this is needed } } } //end members loop bool allClosed = true; foreach (Curve pc in pLines) { if (!pc.IsClosed) { allClosed = false; } } if (pLines.Count > 0 && allClosed) { ///Move polylines to min height double minHeight = GetMinBldgHeight(osmGeo); if (minHeight > 0.0) { Vector3d minVec = new Vector3d(0, 0, minHeight); //minVec.Transform(xformFromMetric); var minHeightTranslate = Transform.Translation(minVec); for (int i = 0; i < pLines.Count; i++) { pLines[i].Transform(minHeightTranslate); } } ///Create base surface Brep[] breps = Brep.CreatePlanarBreps(pLines, DocumentTolerance()); geometryGoo.RemovePath(relationPath); foreach (Brep b in breps) { geometryGoo.Append(new GH_Brep(b), relationPath); ///Building massing if (r.Tags.ContainsKey("building") || r.Tags.ContainsKey("building:part")) { Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo) - minHeight); //hVec.Transform(xformFromMetric); ///Create extrusion from base surface buildingGoo.Append(new GH_Brep(Brep.CreateFromOffsetFace(b.Faces[0], hVec.Z, DocumentTolerance(), false, true)), relationPath); } } } ///Increment relations relations++; } ///End relation loop } ///End filtered loop ///Add building parts to sub-branches under main building for (int partIndex = 0; partIndex < buildingParts.Count; partIndex++) { BuildingPart bldgPart = buildingParts[partIndex]; Point3d partPoint = bldgPart.PartFootprint.PointAtStart; partPoint.Z = 0; bool replaceBuidingMass = false; GH_Path mainBuildingMassPath = new GH_Path(); PolylineCurve massOutline = new PolylineCurve(); bool isRoof = bldgPart.PartOsmGeo.Tags.TryGetValue("roof:shape", out string isRoofString); if (isRoof) { bldgPart.PartGoo = BldgPartToRoof(bldgPart); } foreach (KeyValuePair <PolylineCurve, GH_Path> pair in bldgOutlines) { PointContainment pc = pair.Key.Contains(partPoint, Plane.WorldXY, DocumentTolerance()); if (pc != PointContainment.Outside) { ///Create new sub-branch int numSubBranches = 0; GH_Path partPath = pair.Value.AppendElement(numSubBranches); while (buildingGoo.PathExists(partPath)) { numSubBranches++; partPath = pair.Value.AppendElement(numSubBranches); } ///Add data to sub-branch fieldNames.AppendRange(bldgPart.PartFieldNames, partPath); fieldValues.AppendRange(bldgPart.PartFieldValues, partPath); buildingGoo.Append(bldgPart.PartGoo, partPath); ///Remove the main building mass replaceBuidingMass = true; mainBuildingMassPath = pair.Value; massOutline = pair.Key; } } ///Remove the main building mass if (replaceBuidingMass) { buildingGoo.RemovePath(mainBuildingMassPath); buildingGoo.Append(new GH_Curve(massOutline), mainBuildingMassPath); } else { GH_Path extrasPath = new GH_Path(3, partIndex); buildingGoo.Append(bldgPart.PartGoo, extrasPath); fieldNames.AppendRange(bldgPart.PartFieldNames, extrasPath); fieldValues.AppendRange(bldgPart.PartFieldValues, extrasPath); } } } ///end osm source loop if (recs.IsValid) { DA.SetData(0, recs); } DA.SetDataTree(1, fieldNames); DA.SetDataTree(2, fieldValues); DA.SetDataTree(3, geometryGoo); DA.SetDataTree(4, buildingGoo); } ///end SolveInstance
private static void DrawLineCurveInternal(AM.DrawingContext _dc, AM.Pen pen, bool isStroked, ref A.Point pt1, ref A.Point pt2, double curvature, CurveOrientation orientation, PointAlignment pt1a, PointAlignment pt2a) { if (isStroked) { var sg = new AM.StreamGeometry(); using (var sgc = sg.Open()) { sgc.BeginFigure(new A.Point(pt1.X, pt1.Y), false); double p1x = pt1.X; double p1y = pt1.Y; double p2x = pt2.X; double p2y = pt2.Y; XLineExtensions.GetCurvedLineBezierControlPoints(orientation, curvature, pt1a, pt2a, ref p1x, ref p1y, ref p2x, ref p2y); sgc.CubicBezierTo( new A.Point(p1x, p1y), new A.Point(p2x, p2y), new A.Point(pt2.X, pt2.Y)); sgc.EndFigure(false); } _dc.DrawGeometry(null, pen, sg); } }