protected async Task InitializeAsync(RecordingLocation location, double angle, double hFov, Color color)
        {
            _angle         = angle;
            _hFov          = hFov;
            Color          = color;
            _isInitialized = true;

            double             x        = location.X;
            double             y        = location.Y;
            Settings           settings = Settings.Instance;
            MySpatialReference spatRel  = settings.CycloramaViewerCoordinateSystem;

            await QueuedTask.Run(() =>
            {
                Map map = MapView.Active?.Map;
                SpatialReference mapSpatialReference = map?.SpatialReference;
                SpatialReference spatialReference    = spatRel?.ArcGisSpatialReference ?? mapSpatialReference;
                MapPoint point = MapPointBuilder.CreateMapPoint(x, y, spatialReference);

                if ((mapSpatialReference != null) && (spatialReference.Wkid != mapSpatialReference.Wkid))
                {
                    ProjectionTransformation projection = ProjectionTransformation.Create(spatialReference, mapSpatialReference);
                    _mapPoint = GeometryEngine.Instance.ProjectEx(point, projection) as MapPoint;
                }
                else
                {
                    _mapPoint = (MapPoint)point.Clone();
                }
            });

            MapViewCameraChangedEvent.Subscribe(OnMapViewCameraChanged);
            await RedrawConeAsync();
        }
        // =========================================================================
        // Constructor
        // =========================================================================
        private Arrow(RecordingLocation location, double angle, double hFov, Color color)
        {
            _angle         = angle;
            _hFov          = hFov;
            _color         = color;
            _blinking      = false;
            _toUpdateArrow = false;
            _active        = true;

            double            x                = location.X;
            double            y                = location.Y;
            Config            config           = Config.Instance;
            SpatialReference  spatRel          = config.SpatialReference;
            ISpatialReference spatialReference = (spatRel == null) ? ArcUtils.SpatialReference : spatRel.SpatialRef;

            _point = new Point
            {
                X = x,
                Y = y,
                SpatialReference = spatialReference
            };

            _point.Project(ArcUtils.SpatialReference);
            var avEvents = ArcUtils.ActiveViewEvents;

            if (avEvents != null)
            {
                avEvents.AfterDraw += AvEventsAfterDraw;
            }

            VectorLayer.StartMeasurementEvent += OnMeasurementCreated;
            Redraw();
        }
        public void Set(RecordingLocation location, double angle, double hFov, Color color)
        {
            if (_arrow != null)
            {
                _arrow.Dispose();
            }

            Location = location;
            _arrow   = Arrow.Create(location, angle, hFov, color);

            foreach (var viewer in Viewers.Values)
            {
                if (viewer != this)
                {
                    viewer._arrow.SetActive(false);
                }
            }
        }
        private async Task MoveToLocationAsync(uint viewerId)
        {
            RecordingLocation location = _api?.GetRecordingLocation(viewerId);

            if (location != null)
            {
                MapPoint point = await CoordSystemUtils.CycloramaToMapPointAsync(location.X, location.Y, location.Z);

                MapView  thisView = MapView.Active;
                Envelope envelope = thisView?.Extent;

                if (point != null && envelope != null)
                {
                    const double percent = 10.0;
                    double       xBorder = (envelope.XMax - envelope.XMin) * percent / 100;
                    double       yBorder = (envelope.YMax - envelope.YMin) * percent / 100;
                    bool         inside  = point.X > envelope.XMin + xBorder && point.X <envelope.XMax - xBorder &&
                                                                                         point.Y> envelope.YMin + yBorder && point.Y < envelope.YMax - yBorder;

                    if (!inside)
                    {
                        Camera camera = new Camera
                        {
                            X = point.X,
                            Y = point.Y,
                            Z = point.Z,
                            SpatialReference = point.SpatialReference
                        };

                        await QueuedTask.Run(() =>
                        {
                            thisView.PanTo(camera);
                        });
                    }
                }
            }
        }
        public async void OnImagePreviewCompleted(uint viewerId)
        {
            Viewer viewer = _viewerList.Get(viewerId);

            if (viewer != null && _api != null)
            {
                CurrentCult cult       = CurrentCult.Get();
                string      dateFormat = cult.DateFormat;
                _api.SetDateFormat(dateFormat);
                string timeFormat = cult.TimeFormat;
                _api.SetTimeFormat(timeFormat);

                RecordingLocation location = _api.GetRecordingLocation(viewerId);
                double            angle    = _api.GetYaw(viewerId);
                double            hFov     = _api.GetHFov(viewerId);
                Color             color    = _api.GetViewerBorderColor(viewerId);
                await viewer.SetAsync(location, angle, hFov, color);

                string imageId = viewer.ImageId;

                if (GlobeSpotterConfiguration.AddLayerWfs)
                {
                    await UpdateVectorLayerAsync();

                    MapView          mapView             = MapView.Active;
                    Map              map                 = mapView?.Map;
                    SpatialReference spatRef             = map?.SpatialReference;
                    Unit             unit                = spatRef?.Unit;
                    double           factor              = unit?.ConversionFactor ?? 1;
                    double           overlayDrawDistance = _constants.OverlayDrawDistance / factor;
                    _api.SetOverlayDrawDistance(viewerId, overlayDrawDistance);
                }

                if (_openNearest.Contains(imageId))
                {
                    double pitch = _api.GetPitch(viewerId);
                    double v     = 90 - pitch;
                    _api.SetDrawingLayerVisible(true);
                    _api.SetDrawingMode(DrawingMode.CROSS_HAIR);
                    double size = _constants.CrossCheckSize;

                    _api.SetMarkerSize(size + 1);
                    _api.SetMarkerColor(Color.Bisque);
                    _api.DrawMarkerAtHV(viewerId, angle, v);

                    _api.SetMarkerSize(size - 1);
                    _api.SetMarkerColor(Color.Black);
                    _api.DrawMarkerAtHV(viewerId, angle, v);

                    viewer.HasMarker = true;
                    _openNearest.Remove(imageId);
                }

                DockPaneGlobeSpotter globeSpotter = ((dynamic)DataContext);
                Point3D point3D = globeSpotter?.LookAt;

                if (point3D != null)
                {
                    _api.LookAtCoordinate(viewerId, point3D.x, point3D.y, point3D.z);
                    globeSpotter.LookAt = null;
                }
            }

            await MoveToLocationAsync(viewerId);
        }
        public async Task <string> GenerateGmlAsync()
        {
            MapView            mapView       = MapView.Active;
            Map                map           = mapView?.Map;
            SpatialReference   mapSpatRef    = map?.SpatialReference;
            MySpatialReference myCyclSpatRef = _settings.CycloramaViewerCoordinateSystem;

            SpatialReference cyclSpatRef = (myCyclSpatRef == null)
        ? mapSpatRef
        : (myCyclSpatRef.ArcGisSpatialReference ?? (await myCyclSpatRef.CreateArcGisSpatialReferenceAsync()));

            Unit   unit   = cyclSpatRef?.Unit;
            double factor = unit?.ConversionFactor ?? 1;
            Color  color  = Color.White;
            string result =
                "<wfs:FeatureCollection xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:gml=\"http://www.opengis.net/gml\">";

            await QueuedTask.Run(async() =>
            {
                SpatialReference layerSpatRef       = Layer.GetSpatialReference();
                IList <IList <Segment> > geometries = new List <IList <Segment> >();
                ICollection <Viewer> viewers        = _viewerList.Viewers;

                foreach (var viewer in viewers)
                {
                    double distance = viewer.OverlayDrawDistance;
                    RecordingLocation recordingLocation = viewer.Location;

                    if (recordingLocation != null)
                    {
                        if (cyclSpatRef?.IsGeographic ?? true)
                        {
                            distance = distance * factor;
                        }
                        else
                        {
                            distance = distance / factor;
                        }

                        double x    = recordingLocation.X;
                        double y    = recordingLocation.Y;
                        double xMin = x - distance;
                        double xMax = x + distance;
                        double yMin = y - distance;
                        double yMax = y + distance;

                        Envelope envelope     = EnvelopeBuilder.CreateEnvelope(xMin, yMin, xMax, yMax, cyclSpatRef);
                        Envelope copyEnvelope = envelope;

                        if (layerSpatRef.Wkid != 0)
                        {
                            ProjectionTransformation projection = ProjectionTransformation.Create(cyclSpatRef, layerSpatRef);
                            copyEnvelope = GeometryEngine.Instance.ProjectEx(envelope, projection) as Envelope;
                        }

                        Polygon copyPolygon = PolygonBuilder.CreatePolygon(copyEnvelope, layerSpatRef);
                        ReadOnlyPartCollection polygonParts = copyPolygon.Parts;
                        IEnumerator <ReadOnlySegmentCollection> polygonSegments = polygonParts.GetEnumerator();
                        IList <Segment> segments = new List <Segment>();

                        while (polygonSegments.MoveNext())
                        {
                            ReadOnlySegmentCollection polygonSegment = polygonSegments.Current;

                            foreach (Segment segment in polygonSegment)
                            {
                                segments.Add(segment);
                            }
                        }

                        geometries.Add(segments);
                    }
                }

                GC.Collect();
                Polygon polygon = PolygonBuilder.CreatePolygon(geometries, layerSpatRef);

                using (FeatureClass featureClass = Layer?.GetFeatureClass())
                {
                    string uri = Layer?.URI;

                    SpatialQueryFilter spatialFilter = new SpatialQueryFilter
                    {
                        FilterGeometry      = polygon,
                        SpatialRelationship = SpatialRelationship.Intersects,
                        SubFields           = "*"
                    };

                    using (RowCursor existsResult = featureClass?.Search(spatialFilter, false))
                    {
                        while (existsResult?.MoveNext() ?? false)
                        {
                            Row row       = existsResult.Current;
                            long objectId = row.GetObjectID();

                            if ((_selection == null) || (!_selection.Contains(objectId)))
                            {
                                Feature feature = row as Feature;
                                var fieldvalues = new Dictionary <string, string> {
                                    { FieldUri, uri }, { FieldObjectId, objectId.ToString() }
                                };

                                Geometry geometry         = feature?.GetShape();
                                GeometryType geometryType = geometry?.GeometryType ?? GeometryType.Unknown;
                                Geometry copyGeometry     = geometry;

                                if ((geometry != null) && (layerSpatRef.Wkid != 0))
                                {
                                    ProjectionTransformation projection = ProjectionTransformation.Create(layerSpatRef, cyclSpatRef);
                                    copyGeometry = GeometryEngine.Instance.ProjectEx(geometry, projection);
                                }

                                if (copyGeometry != null)
                                {
                                    string gml = string.Empty;

                                    switch (geometryType)
                                    {
                                    case GeometryType.Envelope:
                                        break;

                                    case GeometryType.Multipatch:
                                        break;

                                    case GeometryType.Multipoint:
                                        break;

                                    case GeometryType.Point:
                                        MapPoint point = copyGeometry as MapPoint;

                                        if (point != null)
                                        {
                                            gml =
                                                $"<gml:Point {GmlDimension(copyGeometry)}><gml:coordinates>{await GmlPointAsync(point)}</gml:coordinates></gml:Point>";
                                        }

                                        break;

                                    case GeometryType.Polygon:
                                        Polygon polygonGml = copyGeometry as Polygon;

                                        if (polygonGml != null)
                                        {
                                            ReadOnlyPartCollection polygonParts = polygonGml.Parts;
                                            IEnumerator <ReadOnlySegmentCollection> polygonSegments = polygonParts.GetEnumerator();

                                            while (polygonSegments.MoveNext())
                                            {
                                                ReadOnlySegmentCollection segments = polygonSegments.Current;

                                                gml =
                                                    $"{gml}<gml:MultiPolygon><gml:PolygonMember><gml:Polygon {GmlDimension(copyGeometry)}><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>";

                                                for (int i = 0; i < segments.Count; i++)
                                                {
                                                    if (segments[i].SegmentType == SegmentType.Line)
                                                    {
                                                        MapPoint polygonPoint = segments[i].StartPoint;
                                                        gml = $"{gml}{((i == 0) ? string.Empty : " ")}{await GmlPointAsync(polygonPoint)}";

                                                        if (i == (segments.Count - 1))
                                                        {
                                                            polygonPoint = segments[i].EndPoint;
                                                            gml          = $"{gml} {await GmlPointAsync(polygonPoint)}";
                                                        }
                                                    }
                                                }

                                                gml =
                                                    $"{gml}</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:PolygonMember></gml:MultiPolygon>";
                                            }
                                        }
                                        break;

                                    case GeometryType.Polyline:
                                        Polyline polylineGml = copyGeometry as Polyline;

                                        if (polylineGml != null)
                                        {
                                            ReadOnlyPartCollection polylineParts = polylineGml.Parts;
                                            IEnumerator <ReadOnlySegmentCollection> polylineSegments = polylineParts.GetEnumerator();

                                            while (polylineSegments.MoveNext())
                                            {
                                                ReadOnlySegmentCollection segments = polylineSegments.Current;
                                                gml =
                                                    $"{gml}<gml:MultiLineString><gml:LineStringMember><gml:LineString {GmlDimension(copyGeometry)}><gml:coordinates>";

                                                for (int i = 0; i < segments.Count; i++)
                                                {
                                                    if (segments[i].SegmentType == SegmentType.Line)
                                                    {
                                                        MapPoint linePoint = segments[i].StartPoint;
                                                        gml = $"{gml}{((i == 0) ? string.Empty : " ")}{await GmlPointAsync(linePoint)}";

                                                        if (i == (segments.Count - 1))
                                                        {
                                                            linePoint = segments[i].EndPoint;
                                                            gml       = $"{gml} {await GmlPointAsync(linePoint)}";
                                                        }
                                                    }
                                                }

                                                gml = $"{gml}</gml:coordinates></gml:LineString></gml:LineStringMember></gml:MultiLineString>";
                                            }
                                        }

                                        break;

                                    case GeometryType.Unknown:
                                        break;
                                    }

                                    string fieldValueStr = fieldvalues.Aggregate(string.Empty,
                                                                                 (current, fieldvalue) =>
                                                                                 string.Format("{0}<{1}>{2}</{1}>", current, fieldvalue.Key, fieldvalue.Value));
                                    result =
                                        $"{result}<gml:featureMember><xs:Geometry>{fieldValueStr}{gml}</xs:Geometry></gml:featureMember>";
                                }
                            }
                        }
                    }
                }

                CIMRenderer renderer             = Layer.GetRenderer();
                CIMSimpleRenderer simpleRenderer = renderer as CIMSimpleRenderer;
                CIMUniqueValueRenderer uniqueValueRendererRenderer = renderer as CIMUniqueValueRenderer;
                CIMSymbolReference symbolRef = simpleRenderer?.Symbol ?? uniqueValueRendererRenderer?.DefaultSymbol;
                CIMSymbol symbol             = symbolRef?.Symbol;
                CIMColor cimColor            = symbol?.GetColor();
                double[] colorValues         = cimColor?.Values;

                int red   = ((colorValues != null) && (colorValues.Length >= 1)) ? ((int)colorValues[0]) : 255;
                int green = ((colorValues != null) && (colorValues.Length >= 2)) ? ((int)colorValues[1]) : 255;
                int blue  = ((colorValues != null) && (colorValues.Length >= 3)) ? ((int)colorValues[2]) : 255;
                int alpha = ((colorValues != null) && (colorValues.Length >= 4)) ? ((int)colorValues[3]) : 255;
                color     = Color.FromArgb(alpha, red, green, blue);
            });

            GmlChanged = (Color != color);
            Color      = color;
            string newGml = $"{result}</wfs:FeatureCollection>";

            GmlChanged = ((newGml != Gml) || GmlChanged);
            return(Gml = newGml);
        }
 // =========================================================================
 // Functions (Static)
 // =========================================================================
 public static Arrow Create(RecordingLocation location, double angle, double hFov, Color color)
 {
     return(new Arrow(location, angle, hFov, color));
 }