Cesium for Unity 1.15.2
Loading...
Searching...
No Matches
CesiumCartographicPolygon.cs
Go to the documentation of this file.
1using System.Collections.Generic;
2using Unity.Mathematics;
3using UnityEngine;
4
5#if SUPPORTS_SPLINES
6using UnityEngine.Splines;
7#endif
8
9namespace CesiumForUnity
10{
15 [ExecuteInEditMode]
16#if SUPPORTS_SPLINES
17 [RequireComponent(typeof(SplineContainer))]
18 [RequireComponent(typeof(CesiumGlobeAnchor))]
19 [AddComponentMenu("Cesium/Cesium Cartographic Polygon")]
20#else
21 [AddComponentMenu("")]
22#endif
23 [IconAttribute("Packages/com.cesium.unity/Editor/Resources/Cesium-24x24.png")]
24 public partial class CesiumCartographicPolygon : MonoBehaviour
25 {
26#if SUPPORTS_SPLINES
27 private SplineContainer _splineContainer;
28 private CesiumGlobeAnchor _globeAnchor;
29#endif
30
31 void OnEnable()
32 {
33#if SUPPORTS_SPLINES
34 this._splineContainer = this.GetComponent<SplineContainer>();
35 this._globeAnchor = this.GetComponent<CesiumGlobeAnchor>();
36
37 // If this component is created before the Splines package is added, the
38 // "RequireComponent" attributes won't automatically apply. This extra check
39 // should ensure the required components exist.
40 if (this._splineContainer == null)
41 {
42 this._splineContainer = this.gameObject.AddComponent<SplineContainer>();
43#if UNITY_EDITOR
44 this.Reset();
45#endif
46 }
47 if (this._globeAnchor == null)
48 {
49 this._globeAnchor = this.gameObject.AddComponent<CesiumGlobeAnchor>();
50 }
51
52#elif UNITY_2022_2_OR_NEWER
53 Debug.LogError("CesiumCartographicPolygon requires the Splines package, which is currently not installed " +
54 "in the project. Install the Splines package using the Package Manager.");
55#else
56 Debug.LogError("CesiumCartographicPolygon requires the Splines package, which is not available " +
57 "in this version of Unity.");
58#endif
59 }
60
61#if SUPPORTS_SPLINES && UNITY_EDITOR
62 void Reset()
63 {
64 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
65 for (int i = splines.Count - 1; i >= 0; i--)
66 {
67 this._splineContainer.RemoveSpline(splines[i]);
68 }
69
70 Spline defaultSpline = new Spline();
71
72 BezierKnot[] knots = new BezierKnot[] {
73 new BezierKnot(new float3(-100.0f, 0f, -100.0f)),
74 new BezierKnot(new float3(100.0f, 0f, -100.0f)),
75 new BezierKnot(new float3(100.0f, 0f, 100.0f)),
76 new BezierKnot(new float3(-100.0f, 0f, 100.0f)),
77 };
78
79 defaultSpline.Knots = knots;
80 defaultSpline.Closed = true;
81 defaultSpline.SetTangentMode(TangentMode.Linear);
82
83 this._splineContainer.AddSpline(defaultSpline);
84 }
85#endif
86
87 static List<double2> emptyList = new List<double2>();
88
89 internal List<double2> GetCartographicPoints(Matrix4x4 worldToTileset)
90 {
91#if SUPPORTS_SPLINES
92 CesiumGeoreference georeference = this._globeAnchor.GetComponentInParent<CesiumGeoreference>();
93 if (georeference == null)
94 {
95 return emptyList;
96 }
97
98 IReadOnlyList<Spline> splines = this._splineContainer.Splines;
99 if (splines.Count == 0)
100 {
101 return emptyList;
102 }
103
104 if (splines.Count > 1)
105 {
106 Debug.LogWarning("CesiumCartographicPolygon has multiple splines in its Spline component, " +
107 "but can only support one at a time. Only the first spline will be rasterized.");
108 }
109
110 Spline spline = splines[0];
111 if (!spline.Closed)
112 {
113 Debug.LogError("Spline must be closed to be used as a cartographic polygon.");
114 return emptyList;
115 }
116
117 BezierKnot[] knots = spline.ToArray();
118 List<double2> cartographicPoints = new List<double2>(knots.Length);
119
120 float4x4 localToWorld = this.transform.localToWorldMatrix;
121
122 for (int i = 0; i < knots.Length; i++)
123 {
124 if (spline.GetTangentMode(i) != TangentMode.Linear)
125 {
126 Debug.LogError("CesiumCartographicPolygon only supports linear splines.");
127 return emptyList;
128 }
129
130 BezierKnot knot = knots[i];
131
132 // The spline points should be located in the tileset *exactly where they
133 // appear to be*. The way we do that is by getting their world position, and
134 // then transforming that world position to a Cesium3DTileset local position.
135 // That way if the tileset is transformed relative to the globe, the polygon
136 // will still affect the tileset where the user thinks it should.
137
138 float3 worldPosition = knot.Transform(localToWorld).Position;
139 float3 unityPosition = worldToTileset.MultiplyPoint3x4(worldPosition);
140 double3 ecefPosition = georeference.TransformUnityPositionToEarthCenteredEarthFixed(unityPosition);
141 double3 cartographicPosition = georeference.ellipsoid.CenteredFixedToLongitudeLatitudeHeight(ecefPosition);
142
143 cartographicPoints.Add(cartographicPosition.xy);
144 }
145
146 return cartographicPoints;
147#else
148 return emptyList;
149#endif
150 }
151 }
152}
A spline-based polygon used to rasterize 2D polygons on top of Cesium3DTilesets.
partial double3 CenteredFixedToLongitudeLatitudeHeight(double3 ellipsoidCenteredEllipsoidFixed)
Convert Ellipsoid-Centered, Ellipsoid-Fixed (ECEF) coordinates to longitude, latitude,...
Controls how global geospatial coordinates are mapped to coordinates in the Unity scene.
CesiumEllipsoid ellipsoid
The CesiumEllipsoid that is referenced.
double3 TransformUnityPositionToEarthCenteredEarthFixed(double3 unityPosition)
Transform a Unity position to Earth-Centered, Earth-Fixed (ECEF) coordinates.
Anchors this game object to the globe.