コード例 #1
0
ファイル: AnnotationOverlay.cs プロジェクト: abordt/Viking
        public void Draw(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphicsDevice,
                         VikingXNA.Scene scene, 
                         Microsoft.Xna.Framework.Graphics.Texture BackgroundLuma,
                         Microsoft.Xna.Framework.Graphics.Texture BackgroundColors,
                        ref int nextStencilValue)
        {
            /// <summary>
            /// Steps:
            ///     Find all the locations for a section.  This could be optimized to return only visible sections immediately with a better data structure
            ///     Filter out invisible locations
            ///     Draw the backgrounds
            ///     Draw the overlapping linked locations over the backgrounds
            ///     Draw the structure links
            ///     Draw the labels
            /// </summary>
            /// <param name="graphicsDevice"></param>
            /// <param name="scene"></param>
            /// <param name="BackgroundLuma"></param>
            /// <param name="BackgroundColors"></param>
            /// <param name="nextStencilValue"></param>

            if(_Parent.Section == null)
                return;

            if (_Parent.spriteBatch.GraphicsDevice.IsDisposed)
                return;

            Matrix ViewProjMatrix = scene.Camera.View * scene.Projection;

            GridRectangle Bounds = scene.VisibleWorldBounds;

            nextStencilValue++;

            if (basicEffect == null)
                basicEffect = new BasicEffect(graphicsDevice);
            else if(basicEffect.IsDisposed)
                basicEffect = new BasicEffect(graphicsDevice);

            VikingXNA.AnnotationOverBackgroundLumaEffect overlayEffect = Parent.annotationOverlayEffect;

            overlayEffect.LumaTexture = BackgroundLuma;

            overlayEffect.RenderTargetSize = graphicsDevice.Viewport;

            basicEffect.Alpha = 1;

            RasterizerState OriginalRasterState = graphicsDevice.RasterizerState;
            SectionLocationsViewModel currentSectionAnnotations = CurrentSectionAnnotations;
            Debug.Assert(currentSectionAnnotations != null);

            int SectionNumber = _Parent.Section.Number;

            float Time = (float)TimeSpan.FromTicks(DateTime.Now.Ticks - DateTime.Today.Ticks).TotalSeconds;
            //            Debug.WriteLine("Time: " + Time.ToString());

            IncrementDepthStencilValue(graphicsDevice, ref nextStencilValue);

            //Get all the lines to draw first so the text and geometric shapes are over top of them
            LocationLink[] VisibleLinks = linksView.VisibleLocationLinks(_Parent.Section.Number, Bounds);
            foreach (LocationLink link in VisibleLinks)
            {
                DrawLocationLink(link, ViewProjMatrix);
            }
            graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, float.MaxValue, 0);

            IncrementDepthStencilValue(graphicsDevice, ref nextStencilValue);

            //graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, float.MaxValue, 0);
            //IncrementDepthStencilValue(graphicsDevice, ref nextStencilValue);

            ICollection<Location_CanvasViewModel> Locations = currentSectionAnnotations.GetLocations();
            List<Location_CanvasViewModel> listLocationsToDraw = FindVisibleLocations(Locations, Bounds);

            //Find a circle that encloses the visible bounds
            GridCircle VisibleCircle = new GridCircle(Bounds.Center, GridVector2.Distance(Bounds.Center, new GridVector2(Bounds.Left, Bounds.Top)));

            List<Location_CanvasViewModel> RefLocations = new List<Location_CanvasViewModel>();
            if(_Parent.Section.ReferenceSectionBelow != null)
            {
                SectionLocationsViewModel sectionLocations = GetAnnotationsForSection(_Parent.Section.ReferenceSectionBelow.Number);
                if (sectionLocations != null)
                    RefLocations.AddRange(sectionLocations.GetLocations());//(Bounds));
            }

            if(_Parent.Section.ReferenceSectionAbove != null)
            {
                SectionLocationsViewModel sectionLocations = GetAnnotationsForSection(_Parent.Section.ReferenceSectionAbove.Number);
                if (sectionLocations != null)
                {
                    RefLocations.AddRange(sectionLocations.GetLocations());
                }
            }

            //Draw text for locations on the reference sections
            List<Location_CanvasViewModel> listVisibleNonOverlappingLocationsOnAdjacentSections = FindVisibleLocations(RefLocations, Bounds);
            List<Location_CanvasViewModel> listVisibleOverlappingLocationsOnAdjacentSections = RemoveOverlappingLocations(listVisibleNonOverlappingLocationsOnAdjacentSections, _Parent.Section.Number);

            //Draw all of the locations on the current section
            WebAnnotation.LocationObjRenderer.DrawBackgrounds(listLocationsToDraw, graphicsDevice, basicEffect, overlayEffect, scene, SectionNumber);

            IncrementDepthStencilValue(graphicsDevice, ref nextStencilValue);
            graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, float.MaxValue, 0);

            WebAnnotation.LocationObjRenderer.DrawBackgrounds(listVisibleNonOverlappingLocationsOnAdjacentSections, graphicsDevice, basicEffect, overlayEffect, scene, SectionNumber);

            IncrementDepthStencilValue(graphicsDevice, ref nextStencilValue);
            graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, float.MaxValue, 0);

            WebAnnotation.LocationObjRenderer.DrawOverlappedAdjacentLinkedLocations(listLocationsToDraw, scene, graphicsDevice, basicEffect, overlayEffect, SectionNumber);

            TryDrawLineFromOverlappingLocation(AnnotationOverlay.LastMouseOverObject as OverlappedLocation, _Parent.LineManager, _Parent.Section.Number, Time);

            if (defaultBlendState == null || defaultBlendState.IsDisposed)
            {
                defaultBlendState = new BlendState();
                defaultBlendState.AlphaBlendFunction = BlendFunction.Add;
                defaultBlendState.AlphaSourceBlend = Blend.SourceAlpha;
                defaultBlendState.AlphaDestinationBlend = Blend.DestinationAlpha;
                defaultBlendState.ColorSourceBlend = Blend.SourceColor;
                defaultBlendState.ColorDestinationBlend = Blend.DestinationColor;
                defaultBlendState.ColorBlendFunction = BlendFunction.Add;
            }

            graphicsDevice.BlendState = defaultBlendState;

            //Get all the lines to draw
            StructureLink[] VisibleStructureLinks = currentSectionAnnotations.VisibleStructureLinks(Bounds);
            foreach (StructureLink link in VisibleStructureLinks)
            {
                DrawStructureLink(link, ViewProjMatrix, Time);
            }

            graphicsDevice.BlendState = defaultBlendState;

            //Draw text
            DrawLocationLabels(listLocationsToDraw);

            DrawLocationLabels(listVisibleNonOverlappingLocationsOnAdjacentSections);

            graphicsDevice.RasterizerState = OriginalRasterState;
        }
コード例 #2
0
ファイル: AnnotationOverlay.cs プロジェクト: abordt/Viking
        private static List<Location_CanvasViewModel> FindVisibleLocations(ICollection<Location_CanvasViewModel> locations,  GridRectangle VisibleBounds)
        {
            GridCircle VisibleCircle = new GridCircle(VisibleBounds.Center, GridVector2.Distance(VisibleBounds.Center, new GridVector2(VisibleBounds.Left, VisibleBounds.Top)));
            List<Location_CanvasViewModel> listLocationsToDraw = new List<Location_CanvasViewModel>(locations.Count);

            foreach (Location_CanvasViewModel loc in locations)
            {
                if (loc == null)
                    continue;

                if (!loc.VolumePositionHasBeenCalculated)
                    continue;

                //Find out if we should draw the location
                if (loc.TypeCode == LocationType.CIRCLE)
                {
                    if (VisibleCircle.Intersects(loc.VolumePosition, loc.Radius) == false)
                        continue;
                }
                else if (loc.TypeCode == LocationType.POINT)
                {
                    if (VisibleBounds.Contains(loc.VolumePosition) == false)
                        continue;
                }
                else
                {
                    Debug.Fail("Unknown location type");
                }

                Structure ParentStructure = loc.Parent;
                if (ParentStructure == null)
                    continue;

                if (ParentStructure.Type == null)
                    continue;

                listLocationsToDraw.Add(loc);
            }

            return listLocationsToDraw;
        }
コード例 #3
0
ファイル: AnnotationOverlay.cs プロジェクト: abordt/Viking
        /// <summary>
        /// Remove all locations from the collection which overlap locations on the specified section
        /// </summary>
        /// <param name="locations">The collection to remove overlapping locations from</param>
        /// <returns>The removed locations which overlap</returns>
        private static List<Location_CanvasViewModel> RemoveOverlappingLocations(List<Location_CanvasViewModel> locations, int section_number)
        {
            List<Location_CanvasViewModel> listOverlappingLocations = new List<Location_CanvasViewModel>(locations.Count);
            for (int i = locations.Count - 1; i >= 0; i--)
            {
                Location_CanvasViewModel loc = locations.ElementAt(i);
                if (loc.TypeCode == LocationType.CIRCLE)
                {
                    GridCircle locCircle = new GridCircle(loc.VolumePosition, loc.OffSectionRadius);
                    foreach (long linked in loc.Links)
                    {
                        LocationObj LinkedObj = Store.Locations.GetObjectByID(linked, false);
                        if (LinkedObj == null)
                            continue;

                        if (LinkedObj.Section == section_number)
                        {
                            if (locCircle.Intersects(LinkedObj.VolumePosition, LinkedObj.Radius))
                            {
                                listOverlappingLocations.Add(loc);
                                locations.RemoveAt(i);
                                break;
                            }
                        }
                    }
                }
            }

            return listOverlappingLocations;
        }
コード例 #4
0
ファイル: GridCircle.cs プロジェクト: abordt/Viking
        public bool Intersects(GridCircle c)
        {
            double XDist = c.Center.X - this.Center.X;
            double YDist = c.Center.Y - this.Center.Y;
            double CombinedRadiusSquared = this.Radius + c.Radius;
            CombinedRadiusSquared *= CombinedRadiusSquared;

            return (XDist * XDist) + (YDist * YDist) <= CombinedRadiusSquared;
        }
コード例 #5
0
ファイル: GridCircle.cs プロジェクト: abordt/Viking
        /// <summary>
        /// This exists because the Delaunay algorithm creates a ton of circles.  Allocating memory for them
        /// means taking the allocation lock twice instead of one (Circle is created by triangle object)
        /// </summary>
        /// <param name="One"></param>
        /// <param name="Two"></param>
        /// <param name="Three"></param>
        /// <returns></returns>
        public static void CircleFromThreePoints(GridVector2 One, GridVector2 Two, GridVector2 Three, ref GridCircle circle)
        {
            if (One.X == Two.X && Two.X == Three.X)
            {
                throw new ArgumentException("Circle from three points with three points on a vertical line");
            }

            double A = Two.X - One.X;
            double B = Two.Y - One.Y;
            double C = Three.X - One.X;
            double D = Three.Y - One.Y;
            double E = A * (One.X + Two.X) + B * (One.Y + Two.Y);
            double F = C * (One.X + Three.X) + D * (One.Y + Three.Y);
            double G = 2 * (A * (Three.Y - Two.Y) - B * (Three.X - Two.X));

            //Check for colinear
            //         Debug.Assert(false == (G <= double.Epsilon && G >= -double.Epsilon));
            if (G <= double.Epsilon && G >= -double.Epsilon)
            {
                throw new ArgumentException("Circle from three points with three points on a line");
            }

            GridVector2 Center = new GridVector2();
            Center.X = (D * E - B * F) / G;
            Center.Y = (A * F - C * E) / G;

            circle.Center = Center;
            circle.Radius = GridVector2.Distance(Center, One);
            circle.RadiusSquared = circle.Radius * circle.Radius;
            //return new GridCircle(Center, GridVector2.Distance(Center, One));
        }
コード例 #6
0
ファイル: GridCircle.cs プロジェクト: abordt/Viking
        /// <summary>
        /// This exists because the Delaunay algorithm creates a ton of circles.  Allocating memory for them
        /// means taking the allocation lock twice instead of one (Circle is created by triangle object)
        /// </summary>
        /// <param name="One"></param>
        /// <param name="Two"></param>
        /// <param name="Three"></param>
        /// <returns></returns>
        public static void CircleFromThreePoints(GridVector2[] points, ref GridCircle circle)
        {
            if (points == null)
            {
                throw new ArgumentNullException("points");

            }

            Debug.Assert(points.Length == 3);
            if (points.Length != 3)
                throw new ArgumentException("GridCircle: Expected an array with three elements");

            GridCircle.CircleFromThreePoints(points[0],points[1], points[2], ref circle);
        }
コード例 #7
0
        private ConcurrentDictionary<Location_CanvasCircleAnnotationViewModel, GridCircle> CalculateOverlappedLocationCircles()
        {
            ConcurrentDictionary<Location_CanvasCircleAnnotationViewModel, GridCircle> listCircles = null;
            if (_OverlappingLinkedLocationCircles == null)
            {
                listCircles = new ConcurrentDictionary<Location_CanvasCircleAnnotationViewModel, GridCircle>();
            }
            else
            {
                listCircles = _OverlappingLinkedLocationCircles;
                listCircles.Clear();
            }
            List<Location_CanvasCircleAnnotationViewModel> listLinksAbove = new List<Location_CanvasCircleAnnotationViewModel>(this.Links.Count);
            List<Location_CanvasCircleAnnotationViewModel> listLinksBelow = new List<Location_CanvasCircleAnnotationViewModel>(this.Links.Count);

            foreach (long linkID in Links)
            {
                LocationObj locObj = Store.Locations.GetObjectByID(linkID, false);
                if (locObj == null)
                {
                    continue;
                }

                if (locObj.Z == this.Z)
                    continue;

                Location_CanvasCircleAnnotationViewModel loc = new Location_CanvasCircleAnnotationViewModel(locObj);
                if (loc == null)
                    continue;

                if (loc.OffSectionRadius + this.Radius < GridVector2.Distance(loc.VolumePosition, this.VolumePosition))
                    continue;

                else if (loc.Section < this.Section)
                {
                    listLinksBelow.Add(loc);
                }
                else
                {
                    listLinksAbove.Add(loc);
                }
            }

            listLinksAbove = listLinksAbove.OrderBy(L => -L.X).ThenBy(L => L.Y).ToList();
            listLinksBelow = listLinksBelow.OrderBy(L => L.X).ThenBy(L => L.Y).ToList();

            //Figure out how large link images would be
            double linkRadius = this.Radius / 6;

            double linkArcNormalizedDistanceFromCenter = 0.75;
            double linkArcDistanceFromCenter = linkArcNormalizedDistanceFromCenter * this.Radius;
            double circumferenceOfLinkArc = linkArcDistanceFromCenter * Math.PI; //Don't multiply by two since we only use top half of circle

            double UpperArcLinkRadius = linkRadius;
            double LowerArcLinkRadius = linkRadius;

            //See if we will run out of room for links
            if (linkRadius * listLinksAbove.Count > circumferenceOfLinkArc)
            {
                UpperArcLinkRadius = circumferenceOfLinkArc / listLinksAbove.Count;
            }

            if (linkRadius * listLinksBelow.Count > circumferenceOfLinkArc)
            {
                LowerArcLinkRadius = circumferenceOfLinkArc / listLinksBelow.Count;
            }

            double UpperArcStepSize = UpperArcLinkRadius / (circumferenceOfLinkArc / 2);
            double LowerArcStepSize = LowerArcLinkRadius / (circumferenceOfLinkArc / 2);

            //double angleOffset =((listLinksAbove.Count / 2) / (double)listLinksAbove.Count) * Math.PI;
            double halfNumLinksAbove = listLinksAbove.Count / 2;
            double angleOffset = ((double)(1 - listLinksAbove.Count) % 2) * (UpperArcStepSize / 2);
            for (int iLocAbove = 0; iLocAbove < listLinksAbove.Count; iLocAbove++)
            {
                Location_CanvasCircleAnnotationViewModel linkLoc = listLinksAbove[iLocAbove];

                //Figure out where the link should be drawn.
                //Allocate the top 180 degree arc for links above, the bottom 180 for links below

                double angle = (((((double)iLocAbove - halfNumLinksAbove) * UpperArcStepSize) - angleOffset) * Math.PI); //- angleOffset;

                Vector3 positionOffset = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle), (float)0);
                positionOffset *= (float)linkArcDistanceFromCenter;

                GridCircle circle = new GridCircle(this.VolumePosition + new GridVector2(positionOffset.X, positionOffset.Y), UpperArcLinkRadius);

                OverlappedLocation overlapLocation = new OverlappedLocation(new LocationLink(this, linkLoc), linkLoc.modelObj, circle);
                bool added = listCircles.TryAdd(overlapLocation, circle);
                if (!added)
                {
                    overlapLocation = null;
                    linkLoc = null;
                }
            }

            double halfNumLinksBelow = listLinksBelow.Count / 2;
            angleOffset = ((double)(1 - listLinksBelow.Count) % 2) * (LowerArcStepSize / 2);
            for (int iLocBelow = 0; iLocBelow < listLinksBelow.Count; iLocBelow++)
            {
                Location_CanvasCircleAnnotationViewModel linkLoc = listLinksBelow[iLocBelow];

                //Figure out where the link should be drawn.
                //Allocate the top 180 degree arc for links above, the bottom 180 for links below

                double angle = (((((double)iLocBelow - halfNumLinksBelow) * LowerArcStepSize) - angleOffset) * Math.PI) + Math.PI;

                Vector3 positionOffset = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle), (float)0);
                positionOffset *= (float)linkArcDistanceFromCenter;

                GridCircle circle = new GridCircle(this.VolumePosition + new GridVector2(positionOffset.X, positionOffset.Y), LowerArcLinkRadius);

                OverlappedLocation overlapLocation = new OverlappedLocation(new LocationLink(this, linkLoc), linkLoc.modelObj, circle);
                bool added = listCircles.TryAdd(overlapLocation, circle);
                if (!added)
                {
                    overlapLocation = null;
                    linkLoc = null;
                }
            }

            return listCircles;
        }
コード例 #8
0
ファイル: OverlappedLocation.cs プロジェクト: abordt/Viking
 public OverlappedLocation(LocationLink linkObj, LocationObj location, GridCircle circle)
     : base(location)
 {
     link = linkObj;
     gridCircle = circle;
 }