Example #1
0
        /// <summary>
        /// Takes the symbol code and matches one of the stencils in the resource dictionary.
        /// </summary>
        /// <param name="symbolCode">
        /// The symbol code for which to look up the stencil.
        /// </param>
        /// <returns>
        /// The string that should be used to get the ResourceDictionary entry for this symbol.
        /// </returns>
        public static string CodeToStencil(string symbolCode)
        {
            if (!SymbolData.Check(ref symbolCode))
            {
                return(null);
            }

            int schemeKey = CodingScheme.GetCode(symbolCode);

            // Weather short circuits most considerations, at least for now
            if (schemeKey == CodingScheme.Weather)
            {
                return(symbolCode);
            }

            string stencil = symbolCode.Substring(0, 10).ToUpperInvariant();

            int dash = stencil.IndexOf('-', 4);

            if (dash > 0)
            {
                stencil = stencil.Substring(0, dash);
            }

            // Replace remaining '-'s with '_'s
            stencil = stencil.Replace('-', '_');

            // Return one of the four (approximately) that we know about
            int identityKey = StandardIdentity.GetNormalizedStandardIdentity(symbolCode);

            // Need the battle dimension
            int dimensionKey = CategoryBattleDimension.GetCode(symbolCode);

            // If we have a Z battle dimension cut right to the chase.
            // Get a blank stencil so we can add a question mark.
            if (dimensionKey == CategoryBattleDimension.BdUnknown)
            {
                return("I" + StandardIdentity.ToChar(identityKey) + "ZP");
            }

            string tail = stencil.Substring(2, 1) + "P" + stencil.Substring(4);

            // If we have EmergenctManagement and a NaturalEvent, get rid of the standard identity
            // or if we have a tactical graphic, get rid of the standard identity
            if ((schemeKey == CodingScheme.EmergencyManagement &&
                 dimensionKey == CategoryBattleDimension.EmNaturalEvents) ||
                schemeKey == CodingScheme.TacticalGraphics)
            {
                return(stencil.Substring(0, 1) + "_" + tail);
            }

            // If framed, we'll include the base affiliation
            if (dimensionKey != CategoryBattleDimension.BdOther)
            {
                return(stencil.Substring(0, 1) + StandardIdentity.ToChar(identityKey) + tail);
            }

            // Otherwise, we're looking for an unframed element
            return(stencil.Substring(0, 1) + "." + tail);
        }
Example #2
0
        /// <summary>
        /// Normalize here strictly means "what will the templates understand?" which is mostly air, land, and water.
        /// </summary>
        /// <param name="symbolCode">
        /// The symbol code.
        /// </param>
        /// <returns>
        /// The enumerated battle dimension value.
        /// </returns>
        private static int NormalizeBattleDimension(string symbolCode)
        {
            if (!Check(ref symbolCode))
            {
                return(0);
            }

            int bd = CategoryBattleDimension.GetCode(symbolCode);

            if (bd == CategoryBattleDimension.BdUnknown)
            {
                return(CategoryBattleDimension.BdSeaSurface);
            }

            return(bd);
        }
Example #3
0
        /// <summary>
        /// Returns the arrow representing a direction of travel for a mil symbol
        /// </summary>
        /// <param name="symbolCode">Code for the mil symbol</param>
        /// <param name="labels">The labels for the symbol, we're looking for "Q"</param>
        /// <param name="extraOffset">An extra offset for tactical graphics</param>
        /// <returns>The arrow shape representing the direction of travel</returns>
        internal static Shape GenerateQ(
            string symbolCode,
            IDictionary <string, string> labels,
            double extraOffset)
        {
            if (!SymbolData.Check(ref symbolCode))
            {
                return(null);
            }

            string q;

            if (!labels.TryGetValue("Q", out q))
            {
                return(null);
            }

            double angle;

            if (!double.TryParse(q, out angle))
            {
                return(null);
            }

            double off = 0.0;

            if (CategoryBattleDimension.GetCode(symbolCode) == CategoryBattleDimension.BdGround)
            {
                off = SymbolData.GetBounds(symbolCode).Bottom;
            }

            off += extraOffset;
            return(new Path
            {
                Style = SymbolData.GetStyle("BS10"),
                Data = new PathGeometry
                {
                    Figures = new PathFigureCollection
                    {
                        GenerateArrowPoints(off, angle)
                    }
                }
            });
        }
Example #4
0
        public void BattleDimensionTest()
        {
            int gc = CategoryBattleDimension.GetCode(string.Empty);

            Assert.AreEqual(gc, 0);
            gc = CategoryBattleDimension.GetCode(null);
            Assert.AreEqual(gc, 0);
            gc = CategoryBattleDimension.GetCode("qqqqqqqqqqqqqqq");
            Assert.AreEqual(gc, 0);
            string str = CategoryBattleDimension.GetName(string.Empty);

            Assert.AreEqual(str, string.Empty);
            str = CategoryBattleDimension.GetName(null);
            Assert.AreEqual(str, string.Empty);
            str = CategoryBattleDimension.GetName("qqqqqqqqqqqqqqq");
            Assert.AreEqual(str, string.Empty);
            str = CategoryBattleDimension.GetName("iqpqqqqqqqqqqqq");
            Assert.AreEqual(str, "Space");
        }
Example #5
0
        /// <summary>
        /// Determine once and for all if a symbol code is for a piece of equipment.
        /// </summary>
        /// <param name="symbolCode">
        /// The symbol code.
        /// </param>
        /// <returns>
        /// A boolean indicating if the symbol code represents equipment.
        /// </returns>
        internal static bool IsEquipment(string symbolCode)
        {
            if (!Check(ref symbolCode))
            {
                return(false);
            }

            var schemeKey = CodingScheme.GetCode(symbolCode);

            if (schemeKey == CodingScheme.Intelligence)
            {
                return(true);
            }

            var func = symbolCode.Substring(4, 6).Trim(new[] { '-' });

            if (schemeKey == CodingScheme.Warfighting &&
                !string.IsNullOrEmpty(func) &&
                func[0] == 'E')
            {
                return(true);
            }

            if (schemeKey == CodingScheme.EmergencyManagement)
            {
                var catKey = CategoryBattleDimension.GetCode(symbolCode);
                if (catKey == CategoryBattleDimension.EmOperations &&
                    EmOperationsEquipment.Contains(func))
                {
                    return(true);
                }

                if (catKey == CategoryBattleDimension.EmInfrastructure &&
                    EmInfrastructureEquipment.Contains(func))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #6
0
        /// <summary>
        /// When is the top of the symbol flat?
        /// Answer:
        /// 1. normalize StandardIdentity to 'F', 'H', 'N' or 'U'
        /// 2. return true when it is Subsurface
        /// 3. return true when it is Neutral
        /// 4. return true when it is Friendly Units, Installations, or SOF
        /// 5. return true when it is Friendly Emergency Operations
        ///   a. technically, friendly emergency equipment is not flat
        /// </summary>
        /// <param name="symbolCode">
        /// The symbol code to check for a flat top to the symbol.
        /// </param>
        /// <returns>
        /// Returns a boolean to indicate whether the top of the symbol is flat.
        /// </returns>
        internal static bool IsTopFlat(string symbolCode)
        {
            if (!Check(ref symbolCode))
            {
                return(false);
            }

            int dimensionKey = CategoryBattleDimension.GetCode(symbolCode);

            if (dimensionKey == CategoryBattleDimension.BdSubsurface)
            {
                return(true);
            }

            int identityKey = StandardIdentity.GetNormalizedStandardIdentity(symbolCode);

            if (identityKey == StandardIdentity.Neutral)
            {
                return(true);
            }

            if (identityKey == StandardIdentity.Friend)
            {
                if (dimensionKey == CategoryBattleDimension.BdSpace || dimensionKey == CategoryBattleDimension.BdAir ||
                    dimensionKey == CategoryBattleDimension.BdSeaSurface ||
                    dimensionKey == CategoryBattleDimension.BdUnknown)
                {
                    return(false);
                }

                if (IsEquipment(symbolCode))
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Example #7
0
        /// <summary>
        /// Writes out the CXML file.
        /// </summary>
        /// <param name="ms">
        /// The symbol for which to generate the CXML.
        /// </param>
        /// <param name="rootName">
        /// The name to use for the symbol.
        /// </param>
        private void WriteCxml(MilSymbol ms, string rootName)
        {
            var symbolCode = (CodingScheme.GetCode(ms.SymbolCode) != CodingScheme.Weather) ? rootName + "*****" : ms.SymbolCode;

            var description = MilAppendix.Description(symbolCode);
            var lines       = description.Split(new[] { '\n' });
            var lineCount   = lines.Length - 1; // the last line is empty

            var sb = new StringBuilder();

            sb.AppendFormat(@"<Item Id=""{0}"" Name=""{1}"" Img=""Symbols\{1}.png"" Href="""">", this.index++, rootName);
            sb.AppendLine();
            if (lineCount > 0)
            {
                sb.AppendFormat(@" <Description>""{0}""</Description>", lines[lineCount - 1].Trim(new[] { ' ', '\n', '\r' }));
                sb.AppendLine();
            }
            else
            {
                sb.AppendFormat(@" <Description>""""</Description>");
                sb.AppendLine();
            }

            sb.AppendLine(@" <Facets>");
            sb.AppendLine(@"  <Facet Name=""Affiliation"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", StandardIdentity.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            sb.AppendLine(@"  <Facet Name=""Battle Dimension"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", CategoryBattleDimension.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            if (lineCount > 2)
            {
                sb.AppendLine(@"  <Facet Name=""Type"">");
                sb.AppendFormat(@"   <String Value=""{0}"" />", lines[2].Trim(new[] { ' ', '\n', '\r' }));
                sb.AppendLine();
                sb.AppendLine(@"  </Facet>");
            }

            sb.AppendLine(@"  <Facet Name=""Coding Scheme"">");
            sb.AppendFormat(@"   <String Value=""{0}"" />", CodingScheme.GetName(symbolCode));
            sb.AppendLine();
            sb.AppendLine(@"  </Facet>");
            if (lineCount - 1 > 3)
            {
                sb.AppendLine(@"  <Facet Name=""Key Phrases"">");
                for (var i = 3; i < lineCount - 1; i++)
                {
                    sb.AppendFormat(@"   <String Value=""{0}"" />", lines[i].Trim(new[] { ' ', '\n', '\r' }));
                    sb.AppendLine();
                }

                sb.AppendLine(@"  </Facet>");
            }

            sb.AppendLine(@" </Facets>");
            sb.AppendLine(@"</Item>");

#if DO_WRITES
            this.cxmlStream.Write(sb.ToString());
#endif
        }
Example #8
0
        /// <summary>
        /// Adds the black ribbon at the top of the symbol for the standard identity "Space".
        /// </summary>
        /// <param name="symbolCode">The symbol code for the space entity.</param>
        /// <returns>The shape representing the black ribbon overlay for a space entity.</returns>
        internal static Shape GenerateSpace(string symbolCode)
        {
            if (!SymbolData.Check(ref symbolCode))
            {
                return(null);
            }

            if (CategoryBattleDimension.GetCode(symbolCode) != CategoryBattleDimension.BdSpace)
            {
                return(null);
            }

            // Handy points for future reference
            // Inside for unknown ground
            // <Path Data="F0 M-61,-140 C-30,-175 30,-175 61,-140" />
            // Inside for hostile ground
            // <Polygon Points="-61,-105 0,-166 61,-105" />
            switch (StandardIdentity.GetNormalizedStandardIdentity(symbolCode))
            {
            case StandardIdentity.Friend:
            {
                return(GenerateBlackSpline(
                           new Point(-61, -107), new Point(-23, -148), new Point(23, -148), new Point(61, -107)));
            }

            case StandardIdentity.Unknown:
            {
                return(GenerateBlackSpline(
                           new Point(-61, -117), new Point(-30, -160), new Point(30, -160), new Point(61, -117)));
            }

            case StandardIdentity.Hostile:
            {
                return(new Path
                    {
                        Fill = new SolidColorBrush(Colors.Black),
                        Data = new PathGeometry
                        {
                            Figures = new PathFigureCollection
                            {
                                new PathFigure
                                {
                                    StartPoint = new Point(-61, -93),
                                    Segments = new PathSegmentCollection
                                    {
                                        new LineSegment {
                                            Point = new Point(0, -149)
                                        },
                                        new LineSegment {
                                            Point = new Point(61, -93)
                                        }
                                    }
                                }
                            }
                        }
                    });
            }

            case StandardIdentity.Neutral:
            {
                return(new Path
                    {
                        Fill = new SolidColorBrush(Colors.Black),
                        Data = new PathGeometry
                        {
                            Figures = new PathFigureCollection
                            {
                                new PathFigure
                                {
                                    StartPoint = new Point(-127, -104),
                                    Segments = new PathSegmentCollection
                                    {
                                        new LineSegment {
                                            Point = new Point(127, -104)
                                        },
                                        new LineSegment {
                                            Point = new Point(127, -139)
                                        },
                                        new LineSegment {
                                            Point = new Point(-127, -139)
                                        }
                                    }
                                }
                            }
                        }
                    });
            }
            }

            return(null);
        }
Example #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MilSymbolBase"/> class.
        /// </summary>
        /// <param name="symbolCode">
        /// The symbol code for this symbol.
        /// </param>
        /// <param name="lineBrush">
        /// An optional line brush for outlining the symbol.
        /// </param>
        /// <param name="fillBrush">
        /// An optional fill brush for filling the symbol's background.
        /// </param>
        public MilSymbolBase(string symbolCode, Brush lineBrush, Brush fillBrush)
        {
            if (symbolCode == null)
            {
                this.empty = true;
                return;
            }

            string stencil = CodeToStencil(symbolCode);

            if (MilAppendix.NoTemplate(stencil))
            {
                this.empty = true;
                return;
            }

            this.DataContext = this;

            // Will need to treat weather and tactical graphics carefully
            int schemeKey = CodingScheme.GetCode(symbolCode);

            if (schemeKey == CodingScheme.Weather)
            {
                // These symbols can change color - so we bind to Line and Fill
                if (symbolCode.StartsWith("WAS-WSTS"))
                {
                    if (lineBrush == null)
                    {
                        lineBrush = MilBrush.Rust;
                    }

                    if (fillBrush == null)
                    {
                        fillBrush = MilBrush.Rust;
                    }

                    this.SetLines(lineBrush);
                    this.SetLineFills(lineBrush, fillBrush);
                }

                this.Template = SymbolData.GetControlTemplate(stencil); // gets the template - the main thing
                this.empty    = this.Template == null;
                if (!this.empty)
                {
                    this.SetLimits(symbolCode);
                }

                return;
            }

            // If the standard identity (StandardIdentity) is some type of pending, we'll need the
            // anticipated (dashhed) outline for the frame.
            this.needDashed = SymbolData.IsDashed(symbolCode);

            // There are occasions when we need a line style that matches affiliation and present
            int  dimensionKey = CategoryBattleDimension.GetCode(symbolCode);
            bool needUnframed =
                schemeKey == CodingScheme.TacticalGraphics ||
                dimensionKey == CategoryBattleDimension.BdOther ||
                (schemeKey == CodingScheme.Warfighting &&
                 dimensionKey == CategoryBattleDimension.BdSubsurface);

            if (needUnframed)
            {
                this.unframedLine = MilBrush.GetLinePresent(MilBrush.FindColorScheme(symbolCode));
                this.SetUnframedLines(lineBrush);
            }

            this.SetLines(lineBrush);

            // Get a brush style if user didn't specify
            if (fillBrush == null)
            {
                fillBrush = MilBrush.FindColorScheme(symbolCode);
            }

            if (needUnframed)
            {
                this.SetUnframedLineFills(fillBrush);
            }

            this.SetLineFills(lineBrush, fillBrush);

            this.Template = SymbolData.GetControlTemplate(stencil); // gets the template - the main thing
            this.empty    = this.Template == null;
            if (!this.empty)
            {
                this.SetLimits(symbolCode);
            }
        }
Example #10
0
        /// <summary>
        /// Generate the installation rendering for the passed in symbol.
        /// </summary>
        /// <param name="ms">
        /// The military symbol for which to provide the installation rendering.
        /// </param>
        /// <param name="height">
        /// The height at which to provide the installation rendering.
        /// </param>
        /// <returns>
        /// The graphics Shape object that represents the installation rendering.
        /// </returns>
        private static Shape GenerateInstallation(MilSymbol ms, out double height)
        {
            ////    U&PGW   ZSGF      full unknown (flat)
            ////            AP        full air (not flat)
            ////            U         subsurface (flat)
            ////    N&L     ZSGF      full neutral (flat)
            ////            AP        full air (flat)
            ////            U         subsurface (flat)
            ////    H&S     ZSGF      full hostile (not flat)
            ////            AP        full air (not flat)
            ////            U         subsurface (flat)
            ////    F&ADMJK Z(IG)S    full friendly (not flat)
            ////            F(~IG)    full friendly (flat)
            ////            AP        full air (not flat)
            ////            U         subsurface  (flat)

            height = -185;
            Brush br = new SolidColorBrush(Colors.Black);
            int   si = StandardIdentity.GetNormalizedStandardIdentity(ms.SymbolCode);

            if (SymbolData.IsTopFlat(ms.SymbolCode))
            {
                double t = ms.BaseRect.Top;
                if (si == StandardIdentity.Unknown)
                {
                    t += SymbolData.HalfWidth;
                }

                height = t - 30;
                return(GenericInstallation(br, height, t));
            }

            int  bd = CategoryBattleDimension.GetCode(ms.SymbolCode);
            bool ap = bd == CategoryBattleDimension.BdSpace || bd == CategoryBattleDimension.BdAir;

            // The cases cover those surfaces which are flat on top versus those that are not
            switch (si)
            {
            case StandardIdentity.Unknown:
                // Outside for unknown space
                if (ap)
                {
                    return(UnknownSpaceInstallation(br, height));
                }

                return(UnknownGroundInstallation(br, height));

            case StandardIdentity.Hostile:
                // Outside for hostile space
                if (ap)
                {
                    height = -165;
                    return(HostileSpaceInstallation(br, height));
                }

                return(HostileGroundInstallation(br, height));

            case StandardIdentity.Friend:
                height = -175;

                // Outside for friendly space
                if (ap)
                {
                    return(FriendSpaceInstallation(br, height));
                }

                return(FriendCircleInstallation(br, height));
            }

            return(null);
        }
Example #11
0
        /// <summary>
        /// Generate the task force rendering for the passed in symbol.
        /// </summary>
        /// <param name="ms">
        /// The military symbol for which to provide the task force rendering.
        /// </param>
        /// <param name="height">
        /// The height at which to provide the task force rendering.
        /// </param>
        /// <returns>
        /// The graphics Path object that represents the task force rendering.
        /// </returns>
        private static Path GenerateTaskForce(MilSymbol ms, out double height)
        {
            height = -185;
            double       bottom = 0;
            const double Wide   = 54;
            int          si     = StandardIdentity.GetNormalizedStandardIdentity(ms.SymbolCode);

            if (SymbolData.IsTopFlat(ms.SymbolCode))
            {
                bottom = ms.BaseRect.Top;
                if (si == StandardIdentity.Unknown)
                {
                    bottom += SymbolData.HalfWidth;
                }

                height = bottom - 75;
            }
            else
            {
                int  bd = CategoryBattleDimension.GetCode(ms.SymbolCode);
                bool ap = bd == CategoryBattleDimension.BdSpace || bd == CategoryBattleDimension.BdAir;

                // The cases cover those surfaces which are flat on top versus those that are not
                switch (si)
                {
                case StandardIdentity.Unknown:
                    if (ap)
                    {
                        height = -230;      // space
                        bottom = -133;
                    }
                    else
                    {
                        height = -250;      // ground
                        bottom = -154;
                    }

                    break;

                case StandardIdentity.Hostile:
                    if (ap)
                    {
                        height = -230;      // space
                        bottom = -107;
                    }
                    else
                    {
                        height = -253;      // ground
                        bottom = -119;
                    }

                    break;

                case StandardIdentity.Friend:
                    height = -222;
                    if (ap)
                    {
                        bottom = -121;      // space
                    }
                    else
                    {
                        bottom = -137;      // ground circles
                    }

                    break;
                }
            }

            return(new Path
            {
                Style = SymbolData.GetStyle("BS10"),
                Data = new PathGeometry
                {
                    Figures = new PathFigureCollection
                    {
                        new PathFigure
                        {
                            StartPoint = new Point(Wide, bottom),
                            Segments = new PathSegmentCollection
                            {
                                new LineSegment {
                                    Point = new Point(Wide, height)
                                },
                                new LineSegment {
                                    Point = new Point(-Wide, height)
                                },
                                new LineSegment {
                                    Point = new Point(-Wide, bottom)
                                }
                            }
                        }
                    }
                }
            });
        }