62 #region Events and Delegates
77 internal static void BroadcastCesiumCartographicPolygonLoadFailure(
88 internal static readonly List<double2> emptyList =
new List<double2>();
91 private SplineContainer _splineContainer;
114 this._source = value;
115 this.LoadFromSource();
120 private string _url =
"";
137 this.LoadFromSource();
143 private int _polygonIndex = 0;
156 get => this._polygonIndex;
159 this._polygonIndex = value;
160 this.LoadFromSource();
165 private int _featureIndex = 0;
178 get => this._featureIndex;
181 this._featureIndex = value;
182 this.LoadFromSource();
187 private long _ionAssetID = 0;
198 get => this._ionAssetID;
201 this._ionAssetID = value;
204 this.LoadFromSource();
210 private string _ionAccessToken =
"";
222 get => this._ionAccessToken;
225 this._ionAccessToken = value;
228 this.LoadFromSource();
247 if (this._ionServer ==
null)
249 return this._ionServer;
254 this._ionServer = value;
257 this.LoadFromSource();
273 get => this._document;
276 this._document = value;
278 this.ApplyDocument(value);
286 [NonSerialized]
internal bool _isUpdatingSplineInternally =
false;
291 internal bool IsSplineOwned(Spline spline)
293 if (this._splineContainer ==
null)
298 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
299 for (
int i = 0; i < splines.Count; i++)
301 if (splines[i] == spline)
314 this._splineContainer = this.GetComponent<SplineContainer>();
315 this._globeAnchor = this.GetComponent<CesiumGlobeAnchor>();
320 if (this._splineContainer ==
null)
322 this._splineContainer = this.gameObject.AddComponent<SplineContainer>();
327 if (this._globeAnchor ==
null)
329 this._globeAnchor = this.gameObject.AddComponent<CesiumGlobeAnchor>();
334 this.LoadFromSource();
337#elif UNITY_2022_2_OR_NEWER
338 Debug.LogError(
"CesiumCartographicPolygon requires the Splines package, which is currently not installed " +
339 "in the project. Install the Splines package using the Package Manager.");
341 Debug.LogError(
"CesiumCartographicPolygon requires the Splines package, which is not available " +
342 "in this version of Unity.");
346#if SUPPORTS_SPLINES && UNITY_EDITOR
349 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
350 for (
int i = splines.Count - 1; i >= 0; i--)
352 this._splineContainer.RemoveSpline(splines[i]);
355 Spline defaultSpline =
new Spline();
357 BezierKnot[] knots =
new BezierKnot[] {
358 new BezierKnot(
new float3(-100.0f, 0f, -100.0f)),
359 new BezierKnot(
new float3(100.0f, 0f, -100.0f)),
360 new BezierKnot(
new float3(100.0f, 0f, 100.0f)),
361 new BezierKnot(
new float3(-100.0f, 0f, 100.0f)),
364 defaultSpline.Knots = knots;
365 defaultSpline.Closed =
true;
366 defaultSpline.SetTangentMode(TangentMode.Linear);
368 this._splineContainer.AddSpline(defaultSpline);
387 this.RefreshDependentOverlays();
397 private void RefreshDependentOverlays()
400 for (
int i = 0; i < overlays.Length; i++)
403 if (overlay ==
null || overlay.
polygons ==
null)
405 if (overlay.
polygons.Contains(
this))
413 private void LoadFromSource(){}
415 private async
void LoadFromSource()
417 CesiumGeoJsonDocument loaded =
null;
418 bool hasEmptySource =
false;
419 switch (this._source)
424 loaded = this._document;
427 if (!
string.IsNullOrEmpty(this._url))
428 loaded = await CesiumGeoJsonDocument.LoadFromUrlAsync(this._url);
430 hasEmptySource =
true;
433 if (this._ionAssetID > 0)
434 loaded = await CesiumGeoJsonDocument.LoadFromCesiumIonAsync(
435 this._ionAssetID, this._ionAccessToken, this.
ionServer);
437 hasEmptySource =
true;
444 this._source == CesiumCartographicPolygonSource.FromCesiumIon
445 ? CesiumCartographicPolygonLoadType.CesiumIon
448 BroadcastCesiumCartographicPolygonLoadFailure(
449 new CesiumCartographicPolygonLoadFailureDetails(
452 "CesiumCartographicPolygon: failed to load the GeoJSON."));
456 if (!this.isActiveAndEnabled)
461 this.ApplyDocument(loaded);
465 this.RefreshDependentOverlays();
487 private static List<double2> GetPolygonRingPoints(CesiumGeoJsonDocument geoJsonDocument,
int featureIndex,
int polygonIndex)
490 if (geoJsonDocument ==
null)
493 CesiumGeoJsonObject obj = geoJsonDocument.GetRootObject();
499 CesiumGeoJsonObject geometry = obj;
502 CesiumGeoJsonFeature feature = obj.GetObjectAsFeature();
503 geometry = feature?.GetGeometry();
507 CesiumGeoJsonFeature[] features = obj.GetObjectAsFeatureCollection();
516 if (geometry ==
null)
519 CesiumGeoJsonLineString[] rings =
null;
524 rings = geometry.GetObjectAsPolygon()?.rings;
528 CesiumGeoJsonPolygon[] polys = geometry.GetObjectAsMultiPolygon();
537 if (rings ==
null || rings.Length == 0 || rings[0] ==
null || rings[0].points.Length < 3)
540 List<double2> result =
new List<double2>(rings[0].points.Length);
541 foreach (double3 p
in rings[0].points)
542 result.Add(
new double2(p.x, p.y));
549 private void ApplyDocument(CesiumGeoJsonDocument geoJsonDocument)
552 List<double2> points = GetPolygonRingPoints(geoJsonDocument, this._featureIndex, this._polygonIndex);
553 if (points ==
null || points.Count < 3)
556 this._isUpdatingSplineInternally =
true;
559 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
560 for (
int i = splines.Count - 1; i >= 0; i--)
562 this._splineContainer.RemoveSpline(splines[i]);
567 this._isUpdatingSplineInternally =
false;
573 CesiumGeoreference georeference = this._globeAnchor.GetComponentInParent<CesiumGeoreference>();
574 if (georeference ==
null)
576 Debug.LogError(
"CesiumCartographicPolygon could not find a CesiumGeoreference in its " +
577 "parent hierarchy, so the GeoJSON source could not be applied.");
581 georeference.Initialize();
584 if (points.Count > 3)
586 double2 first = points[0];
587 double2 last = points[points.Count - 1];
588 if (math.abs(first.x - last.x) < 1e-9 && math.abs(first.y - last.y) < 1e-9)
590 points.RemoveAt(points.Count - 1);
594 Matrix4x4 worldToLocal = this.transform.worldToLocalMatrix;
596 BezierKnot[] knots =
new BezierKnot[points.Count];
597 for (
int i = 0; i < points.Count; i++)
599 double3 cartographic =
new double3(points[i].x, points[i].y, 0.0);
600 double3 ecef = georeference.ellipsoid.LongitudeLatitudeHeightToCenteredFixed(cartographic);
601 double3 unityPosition = georeference.TransformEarthCenteredEarthFixedPositionToUnity(ecef);
602 Vector3 localPosition = worldToLocal.MultiplyPoint3x4(
603 new Vector3((
float)unityPosition.x, (
float)unityPosition.y, (
float)unityPosition.z));
604 knots[i] =
new BezierKnot(
new float3(localPosition.x, localPosition.y, localPosition.z));
607 Spline newSpline =
new Spline();
608 newSpline.Knots = knots;
609 newSpline.Closed =
true;
610 newSpline.SetTangentMode(TangentMode.Linear);
612 this._isUpdatingSplineInternally =
true;
615 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
616 for (
int i = splines.Count - 1; i >= 0; i--)
618 this._splineContainer.RemoveSpline(splines[i]);
621 this._splineContainer.AddSpline(newSpline);
625 this._isUpdatingSplineInternally =
false;
630 internal List<double2> GetCartographicPoints(Matrix4x4 worldToTileset)
633 CesiumGeoreference georeference = this._globeAnchor.GetComponentInParent<CesiumGeoreference>();
634 if (georeference ==
null)
639 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
640 if (splines.Count == 0)
645 if (splines.Count > 1)
647 Debug.LogWarning(
"CesiumCartographicPolygon has multiple splines in its Spline component, " +
648 "but can only support one at a time. Only the first spline will be rasterized.");
651 Spline spline = splines[0];
654 Debug.LogError(
"Spline must be closed to be used as a cartographic polygon.");
658 BezierKnot[] knots = spline.ToArray();
659 List<double2> cartographicPoints =
new List<double2>(knots.Length);
661 float4x4 localToWorld = this.transform.localToWorldMatrix;
663 for (
int i = 0; i < knots.Length; i++)
665 if (spline.GetTangentMode(i) != TangentMode.Linear)
667 Debug.LogError(
"CesiumCartographicPolygon only supports linear splines.");
671 BezierKnot knot = knots[i];
679 float3 worldPosition = knot.Transform(localToWorld).Position;
680 float3 unityPosition = worldToTileset.MultiplyPoint3x4(worldPosition);
681 double3 ecefPosition = georeference.TransformUnityPositionToEarthCenteredEarthFixed(unityPosition);
682 double3 cartographicPosition = georeference.ellipsoid.CenteredFixedToLongitudeLatitudeHeight(ecefPosition);
684 cartographicPoints.Add(cartographicPosition.xy);
687 return cartographicPoints;