Visualizing Platforms |
While Insight3D® provides the ability to visualize almost anything, most users will want to create applications that visualize the definitional objects and analysis results used with other DME Component Libraries. The Platform Graphics library provides an abstraction on top of Insight3D to make this process easier. While Platform Graphics does not replace the need to learn at least the basics of Insight3D, it simplifies the process of creating robust visualization when working with Platforms, ObjectExtensions, and other definitional objects. This topic assumes basic familiarity with Insight3D and DME Component Libraries.
Platform Graphics is built upon the same patterns used throughout DME Component Libraries, specifically, evaluatorsService Providers. It provides ObjectExtensions that describe graphical properties over time. These extensions are then added to individual Platforms and other ExtensibleObjects, which are then added to a ServiceProviderDisplay, which then handles representing the objects in Insight3D, and maintaining the underlying primitives necessary for visualization.
The following code sample is a simple example that draws a satellite marker and label at the location of the International Space Station.
var earth = CentralBodiesFacet.GetFromContext().Earth; var issTle = new TwoLineElementSet(@"1 25544U 98067A 10172.34241898 .00007451 00000-0 60420-4 0 3627 2 25544 51.6459 209.3399 0009135 352.3227 186.5240 15.71934500664129"); var iss = new Platform("ISS") { LocationPoint = new Sgp4Propagator(issTle).CreatePoint(), OrientationAxes = Axes.Root }; var issText = new TextGraphicsExtension { TextGraphics = { Font = new ConstantGraphicsParameter<Font>(new Font("Times New Roman", 10)), Text = new ConstantGraphicsParameter<string>(iss.Name), Color = new ConstantGraphicsParameter<Color>(Color.Red) } }; iss.Extensions.Add(issText); iss.Extensions.Add(new MarkerGraphicsExtension { MarkerGraphics = { Texture = new ConstantGraphicsParameter<Texture2D>(satelliteTexture) } }); var display = new ServiceProviderDisplay(); display.ServiceProviders.Add(iss); display.ApplyChanges(); EventHandler<TimeChangedEventArgs> timeChanged = (sender, e) => display.Update(e.Time); SceneManager.TimeChanged += timeChanged; SceneManager.Animation.PlayForward();
First, we create a Platform representing the ISS, using a TLE to determine its position. We then create a TextGraphicsExtension and a MarkerGraphicsExtension and assign their properties to configure how the text and marker should be drawn. Next, we create a ServiceProviderDisplay and add the Platform to the display. Since this is the only Platform we are adding, we immediately call ApplyChanges. Finally, we add an event handler to the TimeChanged event which will call Update which will update the visualization when the animation time changes, ensuring that the marker and label are always located at the current ISS location.
ServiceProviderDisplay handles the necessary work behind the scenes to update the Insight3D primitives to show the correct visualization. Next, we will dig deeper into the individual objects being used in this example.
In the above example, instead of simply assigning values to the various graphical properties, we are using instances of ConstantGraphicsParameter<T>. For example, instead of assigning the color yellow directly to the Color property, we created an instance of ConstantGraphicsParameter<Color>. The reason for this difference is that we are not just defining the color to be yellow, rather, we are defining what the color of the object will be over time. In this case, using ConstantGraphicsParameter<Color> means that the color itself will remain constant as time changes.
The Color property is actually defined as a GraphicsParameter<Color>, which is an abstract base class that is a definitional object which provides an evaluator for the property over time. In addition to ConstantGraphicsParameter<T>, there are two other types of parameters provided: TimeIntervalGraphicsParameter<T>, which defines the value using the data inside of a TimeIntervalCollection<T>, and AccessQueryGraphicsParameter<T>, which defines the value depending on the results of an AccessQuery.
For example, suppose we wanted the text of the ISS to be green before January 1st, 2009, and red anytime after that. The following code sample shows how to accomplish this:
var intervals = new TimeIntervalCollection<Color> { new TimeInterval<Color>(JulianDate.MinValue, new GregorianDate(2009, 1, 1).ToJulianDate(), Color.Green, true, false), new TimeInterval<Color>(new GregorianDate(2009, 1, 1).ToJulianDate(), JulianDate.MaxValue, Color.Red, false, true), }; issText.TextGraphics.Color = new TimeIntervalGraphicsParameter<Color>(intervals);
So far, the examples have used color, but properties of other types work the same way. Suppose we wanted to know when the ISS had line of sight to a point on the ground, for example, AGI headquarters. In DME Component Libraries, we model this using LinkInstantaneous and a CentralBodyObstructionConstraint, as seen in the code sample below:
var facilityPoint = new PointCartographic(earth, new Cartographic(-1.3191780323141054, 0.69871349190638687, 0.0)); var facility = new Platform("AGI HQ") { LocationPoint = facilityPoint, OrientationAxes = new AxesEastNorthUp(earth, facilityPoint) }; var link = new LinkInstantaneous(iss, facility); var constraint = new CentralBodyObstructionConstraint(link, earth);
Given the link and an access constraint that tells us when the link is valid, we can visualize the valid link by drawing a line connecting our two platforms in the following code sample:
var linkGraphics = new LinkGraphicsExtension { LinkGraphics = { Color = new ConstantGraphicsParameter<Color>(Color.Yellow) } }; linkGraphics.LinkGraphics.DisplayParameters.Display = new AccessQueryGraphicsParameter<bool> { Query = constraint, AccessExists = true, AccessUnknown = false, NoAccess = false }; link.Extensions.Add(linkGraphics);
First, we create a LinkGraphicsExtension which describes the graphical properties of the link, and assign the color of the link to be yellow. We only want the link to be shown when the constraint is satisfied. Since CentralBodyObstructionConstraint is an AccessQuery, we can use an AccessQueryGraphicsParameter<T> to specify the values to associate with access results. In this case, we configure the Display property to be true when access exists, and false otherwise.
The following code sample presents a complete example of the above visualization:
var earth = CentralBodiesFacet.GetFromContext().Earth; var satelliteTexture = SceneManager.Textures.FromUri(satelliteTexturePath); var facilityTexture = SceneManager.Textures.FromUri(facilityTexturePath); var issTle = new TwoLineElementSet(@"1 25544U 98067A 10172.34241898 .00007451 00000-0 60420-4 0 3627 2 25544 51.6459 209.3399 0009135 352.3227 186.5240 15.71934500664129"); var iss = new Platform("ISS") { LocationPoint = new Sgp4Propagator(issTle).CreatePoint(), OrientationAxes = Axes.Root }; iss.Extensions.Add(new TextGraphicsExtension { TextGraphics = { Font = new ConstantGraphicsParameter<Font>(new Font("Courier New", 8)), Outline = new ConstantGraphicsParameter<bool>(true), OutlineColor = new ConstantGraphicsParameter<Color>(Color.Black), Text = new ConstantGraphicsParameter<string>(iss.Name), Origin = new ConstantGraphicsParameter<Origin>(Origin.TopCenter), PixelOffset = new ConstantGraphicsParameter<PointF>(new PointF(0.0f, satelliteTexture.Template.Height / -2.0f)), Color = new ConstantGraphicsParameter<Color>(Color.White) } }); iss.Extensions.Add(new MarkerGraphicsExtension { MarkerGraphics = { Texture = new ConstantGraphicsParameter<Texture2D>(satelliteTexture) } }); var facilityPoint = new PointCartographic(earth, new Cartographic(-1.3191780323141054, 0.69871349190638687, 0.0)); var facility = new Platform("AGI HQ") { LocationPoint = facilityPoint, OrientationAxes = new AxesEastNorthUp(earth, facilityPoint) }; facility.Extensions.Add(new MarkerGraphicsExtension { MarkerGraphics = { Texture = new ConstantGraphicsParameter<Texture2D>(facilityTexture) } }); facility.Extensions.Add(new TextGraphicsExtension { TextGraphics = { Font = new ConstantGraphicsParameter<Font>(new Font("Courier New", 8)), Outline = new ConstantGraphicsParameter<bool>(true), OutlineColor = new ConstantGraphicsParameter<Color>(Color.Black), Text = new ConstantGraphicsParameter<string>(facility.Name), Origin = new ConstantGraphicsParameter<Origin>(Origin.TopCenter), PixelOffset = new ConstantGraphicsParameter<PointF>(new PointF(0.0f, facilityTexture.Template.Height / -2.0f)), Color = new ConstantGraphicsParameter<Color>(Color.White) } }); var link = new LinkInstantaneous(iss, facility); var constraint = new CentralBodyObstructionConstraint(link, earth); var linkGraphics = new LinkGraphicsExtension { LinkGraphics = { Color = new ConstantGraphicsParameter<Color>(Color.Yellow) } }; linkGraphics.LinkGraphics.DisplayParameters.Display = new AccessQueryGraphicsParameter<bool>(constraint, true, false, false); link.Extensions.Add(linkGraphics); var display = new ServiceProviderDisplay(); display.ServiceProviders.Add(iss); display.ServiceProviders.Add(link); display.ServiceProviders.Add(facility); display.ApplyChanges(); EventHandler<TimeChangedEventArgs> timeChanged = (sender, e) => display.Update(e.Time); SceneManager.TimeChanged += timeChanged; SceneManager.Animation.PlayForward();
GraphicsParameter<T> provide a mechanism to define the visual state of a scene declaratively, as it changes over time, which is useful to connect analysis results with a visualization.
In the previous section, we described ServiceProviderDisplay as the object responsible for managing the Insight3D primitives that make up the visualization. However, ServiceProviderDisplay actually just delegates the work to a set of ServiceProviderVisualizers, each of which handle visualization of a specific type of IServiceProvider. The full set of visualizers together create a complete picture. For example, a MarkerVisualizer uses the IMarkerGraphicsService and ILocationPointService to draw a marker at the current location of the service provider.
ServiceProviderVisualizers can be used to provide custom visualization for services you define yourself, however, this is advanced functionality. In practice, the standard set of visualizers, which are provided by the Visualizers property, are available by default and serve most visualization needs. The following table lists the available ObjectExtensions and the associated ServiceProviderVisualizers.
Object Extension | Visualizer | Description |
---|---|---|
The outline, interior and boundary wall of a surface region on an central body. | ||
The outline and boundary wall of a surface curve on an central body. | ||
A line drawn between the two end points of a link. | ||
A marker at the location of the object. | ||
A model at the location of the object. | ||
A point at the location of the object. | ||
Text at the location of the object. | ||
Ellipsoidal uncertainty in the position of an object. | ||
Sensor volumes and footprints projected onto a CentralBody. | ||
Renders an AzimuthElevationMask. | ||
Renders a ReferenceFrame. | ||
Renders a Vector. |
Picking allows users to select and interact with objects in the 3D scene. The Pick method takes a normal Insight3D PickResult and returns the collection of service providers associated with the result.
Collection<PickResult> pickResults = Scene.Pick(x, y); foreach (var pickResult in pickResults) { IEnumerable<IServiceProvider> pickedEntities = display.Pick(pickResult); }
Further examples showcasing various features of Platform Graphics can be found in the Insight3D HowTo application.