/// <summary> /// Returns all polygon points from given airspace polygon object /// </summary> /// <param name="polygon">airspace polygon</param> /// <param name="floor">floor altitude</param> /// <returns>position list object with all polygon points</returns> private static Czml.PositionList GetPolygonPointsFromAirspacePolygon(Airspace.Polygon polygon, Altitude floor) { double height = HeightFromAltitude(floor); var positions = new Czml.PositionList(); foreach (var segment in polygon.Segments) { if (segment is Airspace.Polygon.PolygonPoint point) { positions.Add(point.Point.Latitude, point.Point.Longitude, height); } if (segment is Airspace.Polygon.PolygonArc arc) { var convertedArcSegment = ConvertPolygonArcToArcSegment(arc, height); AddArcSegmentPolygonPoints(convertedArcSegment, positions, height); positions.Add(arc.End.Latitude, arc.End.Longitude, height); } if (segment is Airspace.Polygon.PolygonArcSegment arcSegment) { AddArcSegmentPolygonPoints(arcSegment, positions, height); } } return(positions); }
/// <summary> /// Creates a Czml.Object from given airspace /// </summary> /// <param name="airspace">airspace to use</param> /// <returns>created CZML object</returns> private static Czml.Object CzmlObjectFromAirspace(Airspace.Airspace airspace) { double height = HeightFromAltitude(airspace.Ceiling) - HeightFromAltitude(airspace.Floor); if (airspace.Geometry is Circle circle) { return(new Czml.Object { Name = airspace.Name, Description = DescriptionFromAirspace(airspace), Position = PositionFromCoord(circle.Center, airspace.Floor), Cylinder = new Czml.Cylinder { BottomRadius = circle.Radius, TopRadius = circle.Radius, Length = height, HeightReference = HeightReferenceFromAltitude(airspace.Floor), Material = MaterialFromAirspace(airspace), Outline = true, OutlineColor = ColorFromAirspace(airspace, outlineColor: true), }, }); } if (airspace.Geometry is Airspace.Polygon polygon) { Czml.PositionList positions = GetPolygonPointsFromAirspacePolygon(polygon, airspace.Floor); if (!positions.CartographicDegrees.Any()) { return(null); } return(new Czml.Object { Name = airspace.Name, Description = DescriptionFromAirspace(airspace), Polygon = new Czml.Polygon { Positions = positions, Height = HeightFromAltitude(airspace.Floor), ExtrudedHeight = HeightFromAltitude(airspace.Ceiling), HeightReference = HeightReferenceFromAltitude(airspace.Floor), Material = MaterialFromAirspace(airspace), Outline = true, OutlineColor = ColorFromAirspace(airspace, outlineColor: true), }, }); } throw new FormatException("invalid airspace geometry"); }
/// <summary> /// Generates all points for a PolygonArcSegment object and adds it to the positions /// </summary> /// <param name="arcSegment">arc segment to use</param> /// <param name="positions">positions to add to</param> /// <param name="height">height value</param> private static void AddArcSegmentPolygonPoints( Airspace.Polygon.PolygonArcSegment arcSegment, Czml.PositionList positions, double height) { var center = arcSegment.Center.ToMapPoint(height); bool isClockwise = arcSegment.Direction == Airspace.Polygon.ArcDirection.Clockwise; double endAngle = arcSegment.EndAngle; double startAngle = arcSegment.StartAngle; // adjust angles so that we don't have to deal with wrap around if (isClockwise && startAngle > endAngle) { endAngle += 360.0; } if (!isClockwise && startAngle < endAngle) { startAngle += 360.0; } bool isAtEnd; double step = (isClockwise ? 1.0 : -1.0) * ArcSegmentAngleStepByRadius(arcSegment.Radius); double bearing = startAngle; do { var point = center.PolarOffset(arcSegment.Radius, -bearing, height); positions.Add(point.Latitude, point.Longitude, height); bearing += step; isAtEnd = isClockwise ? bearing > endAngle : bearing < endAngle; }while (!isAtEnd); // add end point when the step angle didn't hit the end angle directly if (Math.Abs(bearing - arcSegment.EndAngle) > 1e-6) { var point = center.PolarOffset(arcSegment.Radius, -arcSegment.EndAngle, height); positions.Add(point.Latitude, point.Longitude, height); } }