├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── dist └── milgraphics.js ├── docs ├── README.md ├── milsymbol-2525c-tactical-points-svg.html └── milsymbol-APP6b-tactical-points-svg.html ├── example-data └── tacticaljson │ ├── airspace-coordination-area.json │ ├── ambush.json │ ├── ambush_wrong_order.json │ ├── artillery-target-intelligence-zone.json │ ├── block.json │ ├── breach.json │ ├── bypass.json │ ├── call-for-fire-zone.json │ ├── canalize.json │ ├── censor-zone.json │ ├── clear.json │ ├── critical-friendly-zone.json │ ├── dead-space-area.json │ ├── delay.json │ ├── fire-support-areas.json │ ├── free-fire-area.json │ ├── named-area-of-interest.json │ ├── restrictive-fire-area.json │ ├── sensor-zone.json │ ├── target-build-up-area.json │ ├── target-value-area.json │ ├── targeted-area-of-interest.json │ ├── terminally-guided-munition-footprint.json │ └── zone-of-responsibility.json ├── examples ├── armyxml-openlayers │ ├── index.html │ ├── preview.png │ └── readme.md ├── geojson-openlayers │ ├── index.html │ ├── preview.png │ └── readme.md ├── nvg-openlayers │ ├── index.html │ ├── preview.png │ └── readme.md ├── slf-cesium │ ├── index.html │ ├── preview.png │ └── readme.md └── slf-openlayers │ ├── index.html │ ├── preview.png │ ├── readme.md │ └── sample.slf ├── license.txt ├── package.json ├── src ├── format.js ├── format │ ├── armyxml.js │ ├── geojson.js │ ├── nvg.js │ └── slf.js ├── geometry.js ├── geometry │ ├── bearingbetween.js │ ├── circle.js │ ├── circlecorridorpolygon.js │ ├── corridor.js │ ├── distancebetween.js │ ├── pointbetween.js │ ├── rectangle.js │ └── todistancebearing.js ├── geometryconverter.js ├── geometryconverter │ ├── airspace-coordination-area.js │ ├── ambush.js │ ├── artillery-target-intelligence-zone.js │ ├── block.js │ ├── breach.js │ ├── bypass.js │ ├── call-for-fire-zone.js │ ├── canalize.js │ ├── censor-zone.js │ ├── circle.js │ ├── clear.js │ ├── corridor.js │ ├── cover.js │ ├── critical-friendly-zone.js │ ├── dead-space-area.js │ ├── delay.js │ ├── fire-support-area.js │ ├── fix.js │ ├── free-fire-area.js │ ├── guard.js │ ├── isolate.js │ ├── main-attack.js │ ├── named-area-of-interest.js │ ├── occupy.js │ ├── restrictive-fire-area.js │ ├── search-area.js │ ├── sensor-zone.js │ ├── supporting-attack.js │ ├── target-build-up-area.js │ ├── target-value-area.js │ ├── targeted-area-of-interest.js │ ├── terminally-guided-munition-footprint.js │ └── zone-of-responsibility.js ├── graphic.js ├── graphic │ └── getproperties.js ├── graphicslayer.js ├── graphicslayer │ ├── ascesium.js │ └── asopenlayers.js ├── index.js ├── letter-sidc │ ├── getgraphic.js │ ├── properties.js │ ├── tactical-2525.js │ └── tactical-app6.js ├── ms │ └── addsidcgraphics.js └── number-sidc │ └── properties.js └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | "browser": true, 4 | //"node": true, 5 | "commonjs": true 6 | }, 7 | extends: "eslint:recommended", 8 | rules: { 9 | "linebreak-style": ["error", "unix"], 10 | "no-console": ["error", { allow: ["info","warn", "error"] }], 11 | //quotes: ["error", "double"], 12 | "no-unused-vars": ["error", { "vars": "all", "args": "none"}], 13 | semi: ["error", "always"] 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | 4 | dev/ 5 | 6 | examples/slf-cesium/cesium/ 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | I welcome contributions from anyone and everyone. If you want to make any major changes please open an issue first, but for small changes you can simply create a pull. 4 | 5 | Before you make an contribution, please read GitHub Terms of Service: (Everything works as you think it works, but just make sure that you have the right to contribute the code you want to hand over.) 6 | https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license 7 | 8 | ## Priorities 9 | 10 | The big part of this library is the geometry converter functions that takes the input geometries and converts them to military symbology. These can be developed individualy, so if you plan to implement some of them, please add issues for the ones you have in mind making, so that noone else starts implementing the same converters. 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Milgraphics 2 | 3 | Military Tactical Graphics 4 | 5 | This is a work in progress with the goal of being able to render tactical graphics in the web browser. 6 | 7 | The library is still in initial development and should not be used in production environments. The goal is to release an initial version during the summer of 2017. What this initial version will include will be decided at a later stage. 8 | 9 | ## Main idea 10 | 11 | The main idea is to initially being able to convert input definition geometries to simple GeoJSON geometries. 12 | 13 | ### Input 14 | 15 | First data will be input in GeoJSON, at the moment the data will be defined with the same geometries as in 2525D, the data specification will be published as [TacticalJSON](https://github.com/spatialillusions/TacticalJSON). 16 | 17 | The library includes a parser for SitaWare SLF/SPF files just to be able to get some test data from an external source. 18 | 19 | ### Output 20 | 21 | Points will be points with style information for different libraries (Cesium/OpenLayers etc.) 22 | 23 | Lines will be lines, might have style information about simple label placement. 24 | 25 | Polygons will be polygons, might have style information about simple label placement. 26 | 27 | Other geometries (arrows and other complex geometries) will be converted to lines or polygons so that they can be displayed on a map and make sense. 28 | 29 | The over all main idea is to keep it simple from the beginning and then move forward where it is needed. 30 | 31 | ## Feedback 32 | 33 | Please add issues for feedback and ideas 34 | 35 | ## Technology 36 | 37 | Milgraphics is built on top of [milsymbol](https://github.com/spatialillusions/milsymbol) and adds functionality for reading tactical data in GeoJSON and outputting it in different ways that makes it easy to use in webmaps. 38 | 39 | ## Contact 40 | 41 | Milsymbol is created and maintained by Måns Beckman 42 | - http://www.spatialillusions.com to see more examples of what milsymbol can be used for 43 | - https://twitter.com/spatialillusion for milsymbol and mapping/military related information 44 | 45 | ## Licensing 46 | 47 | MIT, See [license.txt](license.txt) for details -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Milgraphics Documentation 2 | 3 | 4 | # Creating military graphics layers 5 | 6 | ## ms.GraphicsLayer(GeoJSON) 7 | 8 | Creates a new Graphics Layer from the provided GeoJSON. Properties in the GeoJSON should be mapped with the same names as in milsymbol. GeoJSON in other formats can be cloned and remapped using ms.format.GeoJSON. 9 | 10 | 11 | ----- 12 | ### asCesium() 13 | 14 | Takes the current Graphics Layer and returns it as a Cesium Entity Collection with suitable styles applied. 15 | 16 | **Returns** 17 | 18 | ```javascript 19 | Cesium.EntityCollection 20 | ``` 21 | 22 | 23 | ### asOpenLayers(*crs*) 24 | 25 | Takes the current Graphics Layer and returns it as Open Layers Feature Collection with suitable styles applied. 26 | 27 | **Returns** 28 | 29 | ```javascript 30 | Array. 31 | ``` 32 | 33 | ----- 34 | 35 | # Reading Files 36 | 37 | 38 | ## ms.format.GeoJSON(GeoJSON, mapping) 39 | 40 | Reads GeoJSON, clones it and maps properties according to the mapping object. 41 | 42 | ## ms.format.SLF( file ) 43 | 44 | Reads a SitaWare SLF file and parses it to GeoJSON with attributes mapped to the values milgraphics expects. 45 | 46 | ### Known limitations 47 | 48 | The following location types are not supported at the moment: 49 | 50 | - Ellipse 51 | - FreehandDrawing 52 | - Sector 53 | 54 | -------------------------------------------------------------------------------- /example-data/tacticaljson/airspace-coordination-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACAI------X", 8 | "uniqueDesignation": "53ID (M)", 9 | "altitudeDepth": "500 FT AGL", 10 | "altitudeDepth1": "300 FT AGL", 11 | "additionalInformation1": "NK2313 to NK3013", 12 | "dtg": "281400ZAPR", 13 | "dtg1": "281530ZAPR" 14 | }, 15 | "geometry": { 16 | "type": "Polygon", 17 | "coordinates": [ 18 | [ 19 | [ 20 | 8.725204467773438, 21 | 50.118706959423314 22 | ], 23 | [ 24 | 8.699626922607422, 25 | 50.109680440473284 26 | ], 27 | [ 28 | 8.700828552246094, 29 | 50.099440987634985 30 | ], 31 | [ 32 | 8.719367980957031, 33 | 50.100982550598395 34 | ], 35 | [ 36 | 8.741683959960938, 37 | 50.10912998793372 38 | ], 39 | [ 40 | 8.732757568359375, 41 | 50.12101835522268 42 | ], 43 | [ 44 | 8.725204467773438, 45 | 50.118706959423314 46 | ] 47 | ] 48 | ] 49 | } 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/ambush.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "GFGPSLA-------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 6.609306335449219, 14 | 52.51517622886228 15 | ], 16 | [ 17 | 6.5979766845703125, 18 | 52.52269704703948 19 | ], 20 | [ 21 | 6.597633361816406, 22 | 52.50974372615093 23 | ] 24 | ] 25 | } 26 | }, 27 | { 28 | "type": "Feature", 29 | "properties": {"sidc":"GFGPSLA-------X"}, 30 | "geometry": { 31 | "type": "LineString", 32 | "coordinates": [ 33 | [ 34 | 6.588706970214844, 35 | 52.51663871100423 36 | ], 37 | [ 38 | 6.573944091796875, 39 | 52.5197724373965 40 | ], 41 | [ 42 | 6.5856170654296875, 43 | 52.5081765332574 44 | ] 45 | ] 46 | } 47 | }, 48 | { 49 | "type": "Feature", 50 | "properties": {"sidc":"GFGPSLA-------X"}, 51 | "geometry": { 52 | "type": "LineString", 53 | "coordinates": [ 54 | [ 55 | 6.576347351074219, 56 | 52.50734067419732 57 | ], 58 | [ 59 | 6.560382843017577, 60 | 52.50253417611727 61 | ], 62 | [ 63 | 6.586818695068359, 64 | 52.500339730516956 65 | ] 66 | ] 67 | } 68 | }, 69 | { 70 | "type": "Feature", 71 | "properties": {"sidc":"GFGPSLA-------X"}, 72 | "geometry": { 73 | "type": "LineString", 74 | "coordinates": [ 75 | [ 76 | 6.575145721435547, 77 | 52.49741363265356 78 | ], 79 | [ 80 | 6.574115753173828, 81 | 52.48664809680302 82 | ], 83 | [ 84 | 6.593341827392578, 85 | 52.49762264610208 86 | ] 87 | ] 88 | } 89 | }, 90 | { 91 | "type": "Feature", 92 | "properties": {"sidc":"GFGPSLA-------X"}, 93 | "geometry": { 94 | "type": "LineString", 95 | "coordinates": [ 96 | [ 97 | 6.5938568115234375, 98 | 52.49176989396086 99 | ], 100 | [ 101 | 6.603641510009766, 102 | 52.48434832038955 103 | ], 104 | [ 105 | 6.60552978515625, 106 | 52.49563697822492 107 | ] 108 | ] 109 | } 110 | }, 111 | { 112 | "type": "Feature", 113 | "properties": {"sidc":"GFGPSLA-------X"}, 114 | "geometry": { 115 | "type": "LineString", 116 | "coordinates": [ 117 | [ 118 | 6.613254547119141, 119 | 52.49145633168364 120 | ], 121 | [ 122 | 6.629905700683594, 123 | 52.48800699907657 124 | ], 125 | [ 126 | 6.620979309082031, 127 | 52.49971272594018 128 | ] 129 | ] 130 | } 131 | }, 132 | { 133 | "type": "Feature", 134 | "properties": {"sidc":"GFGPSLA-------X"}, 135 | "geometry": { 136 | "type": "LineString", 137 | "coordinates": [ 138 | [ 139 | 6.6302490234375, 140 | 52.49783165855699 141 | ], 142 | [ 143 | 6.6474151611328125, 144 | 52.50535544522142 145 | ], 146 | [ 147 | 6.618747711181641, 148 | 52.506191342034576 149 | ] 150 | ] 151 | } 152 | }, 153 | { 154 | "type": "Feature", 155 | "properties": {"sidc":"GFGPSLA-------X"}, 156 | "geometry": { 157 | "type": "LineString", 158 | "coordinates": [ 159 | [ 160 | 6.633853912353516, 161 | 52.51016163481784 162 | ], 163 | [ 164 | 6.632823944091797, 165 | 52.5199813445422 166 | ], 167 | [ 168 | 6.614799499511719, 169 | 52.51026611136366 170 | ] 171 | ] 172 | } 173 | }, 174 | { 175 | "type": "Feature", 176 | "properties": {"sidc":"GFGPSLA-------X"}, 177 | "geometry": { 178 | "type": "LineString", 179 | "coordinates": [ 180 | [ 181 | 6.695137023925781, 182 | 52.50859445682651 183 | ], 184 | [ 185 | 6.680545806884766, 186 | 52.5022206905951 187 | ], 188 | [ 189 | 6.706981658935547, 190 | 52.50054873005541 191 | ] 192 | ] 193 | } 194 | }, 195 | { 196 | "type": "Feature", 197 | "properties": {"sidc":"GFGPSLA-------X"}, 198 | "geometry": { 199 | "type": "LineString", 200 | "coordinates": [ 201 | [ 202 | 6.6886138916015625, 203 | 52.489993011495585 204 | ], 205 | [ 206 | 6.705093383789062, 207 | 52.496159531097106 208 | ], 209 | [ 210 | 6.679172515869141, 211 | 52.49845868996027 212 | ] 213 | ] 214 | } 215 | } 216 | ] 217 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/ambush_wrong_order.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": {"sidc":"GFGPSLA-------X"}, 7 | "geometry": { 8 | "type": "LineString", 9 | "coordinates": [ 10 | [ 11 | 15.851211547851562, 12 | 58.23853710414432 13 | ], 14 | [ 15 | 15.839881896972656, 16 | 58.23329584804805 17 | ], 18 | [ 19 | 15.840911865234373, 20 | 58.24359689253174 21 | ] 22 | ] 23 | } 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/artillery-target-intelligence-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-AZII------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-AZIR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/block.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-B---------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 8.730182647705078, 14 | 50.19767137199048 15 | ], 16 | [ 17 | 8.726921081542969, 18 | 50.190967765585604 19 | ], 20 | [ 21 | 8.711814880371094, 22 | 50.19778125933641 23 | ] 24 | ] 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/breach.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-H---------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 8.730182647705078, 14 | 50.19767137199048 15 | ], 16 | [ 17 | 8.726921081542969, 18 | 50.190967765585604 19 | ], 20 | [ 21 | 8.711814880371094, 22 | 50.19778125933641 23 | ] 24 | ] 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/bypass.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-Y---------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 8.730182647705078, 14 | 50.19767137199048 15 | ], 16 | [ 17 | 8.726921081542969, 18 | 50.190967765585604 19 | ], 20 | [ 21 | 8.711814880371094, 22 | 50.19778125933641 23 | ] 24 | ] 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/call-for-fire-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-AZXI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-AZXR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/canalize.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-C---------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 8.730182647705078, 14 | 50.19767137199048 15 | ], 16 | [ 17 | 8.726921081542969, 18 | 50.190967765585604 19 | ], 20 | [ 21 | 8.711814880371094, 22 | 50.19778125933641 23 | ] 24 | ] 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/censor-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-AZCI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-AZCR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/clear.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-X---------X" 8 | }, 9 | "geometry": { 10 | "type": "LineString", 11 | "coordinates": [ 12 | [ 13 | 8.730182647705078, 14 | 50.19767137199048 15 | ], 16 | [ 17 | 8.726921081542969, 18 | 50.190967765585604 19 | ], 20 | [ 21 | 8.711814880371094, 22 | 50.19778125933641 23 | ] 24 | ] 25 | } 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/critical-friendly-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-AZFI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-AZFR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/dead-space-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACDI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACDR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACDC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "Q37" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/delay.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-T-L---------X", 8 | "dtg": "272100Z SEP" 9 | }, 10 | "geometry": { 11 | "type": "LineString", 12 | "coordinates": [ 13 | [ 14 | 8.66769790649414, 15 | 50.195253786387475 16 | ], 17 | [ 18 | 8.680744171142576, 19 | 50.201297520859185 20 | ], 21 | [ 22 | 8.676109313964844, 23 | 50.204593780814676 24 | ] 25 | ] 26 | } 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/fire-support-areas.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACSI------X", 8 | "uniqueDesignation": "I" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACSR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "II" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACSC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "III" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/free-fire-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACFI------X", 8 | "uniqueDesignation": "I" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACFR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "II" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACFC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "III" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/named-area-of-interest.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-G-SAN-------X", 8 | "uniqueDesignation": "DOCKS" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 8.725204467773438, 16 | 50.118706959423314 17 | ], 18 | [ 19 | 8.699626922607422, 20 | 50.109680440473284 21 | ], 22 | [ 23 | 8.700828552246094, 24 | 50.099440987634985 25 | ], 26 | [ 27 | 8.719367980957031, 28 | 50.100982550598395 29 | ], 30 | [ 31 | 8.741683959960938, 32 | 50.10912998793372 33 | ], 34 | [ 35 | 8.732757568359375, 36 | 50.12101835522268 37 | ], 38 | [ 39 | 8.725204467773438, 40 | 50.118706959423314 41 | ] 42 | ] 43 | ] 44 | } 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/restrictive-fire-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACRI------X", 8 | "uniqueDesignation": "I" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACRR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "II" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACRC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "III" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/sensor-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACEI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACER------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACEC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "Q37" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/target-build-up-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACBI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACBR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACBC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "Q37" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/target-value-area.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACVI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACVR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACVC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "Q37" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/targeted-area-of-interest.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-G-SAT-------X", 8 | "uniqueDesignation": "DOCKS" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 8.725204467773438, 16 | 50.118706959423314 17 | ], 18 | [ 19 | 8.699626922607422, 20 | 50.109680440473284 21 | ], 22 | [ 23 | 8.700828552246094, 24 | 50.099440987634985 25 | ], 26 | [ 27 | 8.719367980957031, 28 | 50.100982550598395 29 | ], 30 | [ 31 | 8.741683959960938, 32 | 50.10912998793372 33 | ], 34 | [ 35 | 8.732757568359375, 36 | 50.12101835522268 37 | ], 38 | [ 39 | 8.725204467773438, 40 | 50.118706959423314 41 | ] 42 | ] 43 | ] 44 | } 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/terminally-guided-munition-footprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACT-------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | } 58 | ] 59 | } -------------------------------------------------------------------------------- /example-data/tacticaljson/zone-of-responsibility.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "sidc": "G-F-ACZI------X", 8 | "uniqueDesignation": "Q35" 9 | }, 10 | "geometry": { 11 | "type": "Polygon", 12 | "coordinates": [ 13 | [ 14 | [ 15 | 0.514984130859375, 16 | 47.42065432071318 17 | ], 18 | [ 19 | 0.45799255371093744, 20 | 47.39695481668995 21 | ], 22 | [ 23 | 0.454559326171875, 24 | 47.37184960049907 25 | ], 26 | [ 27 | 0.46623229980468756, 28 | 47.33789206010502 29 | ], 30 | [ 31 | 0.5101776123046875, 32 | 47.33789206010502 33 | ], 34 | [ 35 | 0.5417633056640625, 36 | 47.35836223484991 37 | ], 38 | [ 39 | 0.5108642578125, 40 | 47.37138457633079 41 | ], 42 | [ 43 | 0.5417633056640625, 44 | 47.38812286319825 45 | ], 46 | [ 47 | 0.538330078125, 48 | 47.41833131141311 49 | ], 50 | [ 51 | 0.514984130859375, 52 | 47.42065432071318 53 | ] 54 | ] 55 | ] 56 | } 57 | }, 58 | { 59 | "type": "Feature", 60 | "properties": { 61 | "sidc": "G-F-ACZR------X", 62 | "distance": 5000, 63 | "uniqueDesignation": "Q36" 64 | }, 65 | "geometry": { 66 | "type": "LineString", 67 | "coordinates": [ 68 | [ 69 | 0.6008148193359375, 70 | 47.38672820892124 71 | ], 72 | [ 73 | 0.6488800048828125, 74 | 47.40810885284093 75 | ] 76 | ] 77 | } 78 | }, 79 | { 80 | "type": "Feature", 81 | "properties": { 82 | "sidc": "G-F-ACZC------X", 83 | "distance": 5000, 84 | "dtg": "10095900ZJAN92", 85 | "dtg1": "11095900ZJAN92", 86 | "uniqueDesignation": "Q37" 87 | }, 88 | "geometry": { 89 | "type": "Point", 90 | "coordinates": [ 91 | 0.7532501220703125, 92 | 47.3895174805737 93 | ] 94 | } 95 | } 96 | ] 97 | } -------------------------------------------------------------------------------- /examples/armyxml-openlayers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Army XML:
24 | 25 |
26 | 27 | 53 | 54 | 56 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /examples/armyxml-openlayers/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialillusions/milgraphics/9cc4e608b577e61b0aacf22ba322c2b2ca4feae1/examples/armyxml-openlayers/preview.png -------------------------------------------------------------------------------- /examples/armyxml-openlayers/readme.md: -------------------------------------------------------------------------------- 1 | ## Army XML to GeoJSON 2 | 3 | This is a demo of reading Army XML and converting them to GeoJSON. Not all location types are supported yet, but the plan is to support all of them. 4 | -------------------------------------------------------------------------------- /examples/geojson-openlayers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | TacticalJSON:
26 | 27 |
28 | 29 | 55 | 56 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /examples/geojson-openlayers/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialillusions/milgraphics/9cc4e608b577e61b0aacf22ba322c2b2ca4feae1/examples/geojson-openlayers/preview.png -------------------------------------------------------------------------------- /examples/geojson-openlayers/readme.md: -------------------------------------------------------------------------------- 1 | ## TacticalJSON 2 | 3 | This is a demo of reading GeoJON following the TacticalJSON specification. 4 | -------------------------------------------------------------------------------- /examples/nvg-openlayers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Nato Vector Graphics:
24 | 25 |
26 | 27 | 53 | 54 | 56 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /examples/nvg-openlayers/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialillusions/milgraphics/9cc4e608b577e61b0aacf22ba322c2b2ca4feae1/examples/nvg-openlayers/preview.png -------------------------------------------------------------------------------- /examples/nvg-openlayers/readme.md: -------------------------------------------------------------------------------- 1 | ## Nato Vector Graphics 2 | 3 | This is a demo of reading Nato Vector Graphics (NVG). The reader supports NVG in both JSON format and XML format, and should support most version of NVG. 4 | -------------------------------------------------------------------------------- /examples/slf-cesium/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | SitaWare Layer File (SLF) or SitaWare Plan File (SPF):
27 | 28 |
29 | 30 | 40 | 41 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /examples/slf-cesium/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialillusions/milgraphics/9cc4e608b577e61b0aacf22ba322c2b2ca4feae1/examples/slf-cesium/preview.png -------------------------------------------------------------------------------- /examples/slf-cesium/readme.md: -------------------------------------------------------------------------------- 1 | ## SLF to GeoJSON 2 | 3 | This is a demo of reading SitaWare SLF fils and converting them to GeoJSON. Not all location types are supported yet, but the plan is to support all of them. 4 | -------------------------------------------------------------------------------- /examples/slf-openlayers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | SitaWare Layer File (SLF) or SitaWare Plan File (SPF):
24 | 25 |
26 | 27 | 53 | 54 | 56 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /examples/slf-openlayers/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialillusions/milgraphics/9cc4e608b577e61b0aacf22ba322c2b2ca4feae1/examples/slf-openlayers/preview.png -------------------------------------------------------------------------------- /examples/slf-openlayers/readme.md: -------------------------------------------------------------------------------- 1 | ## SLF to GeoJSON 2 | 3 | This is a demo of reading SitaWare SLF fils and converting them to GeoJSON. Not all location types are supported yet, but the plan is to support all of them. 4 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Måns Beckman - www.spatialillusions.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "milgraphics", 3 | "version": "0.0.1", 4 | "description": "MilGraphics is a library for drawing military graphics", 5 | "main": "dist/milgraphics.js", 6 | "directories": { 7 | "doc": "docs", 8 | "example": "examples" 9 | }, 10 | "scripts": { 11 | "build": "webpack -p", 12 | "build-dev": "webpack", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/spatialillusions/milgraphics" 18 | }, 19 | "author": "Måns Beckman (http://www.spatialillusions.com)", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/spatialillusions/milgraphics/issues" 23 | }, 24 | "homepage": "https://github.com/spatialillusions/milgraphics", 25 | "devDependencies": { 26 | "eslint": "^3.19.0", 27 | "milsymbol": "^1.0.0", 28 | "webpack": "^2.2.0", 29 | "webpack-custom-var-library-name-plugin": "^1.0.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/format.js: -------------------------------------------------------------------------------- 1 | var format = {}; 2 | 3 | format.ArmyXML = require("./format/armyxml.js"); 4 | format.GeoJSON = require("./format/geojson.js"); 5 | format.NVG = require("./format/nvg.js"); 6 | format.SLF = require("./format/slf.js"); 7 | 8 | module.exports = format; 9 | -------------------------------------------------------------------------------- /src/format/armyxml.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function ArmyXML(xml) { 4 | var features = []; 5 | /* 6 | function parseSIDC(sidc) { 7 | for (var i in sidc.childNodes){ 8 | if (sidc.childNodes[i].nodeName == 'SymbolCodeString'){ 9 | return sidc.childNodes[i].textContent; 10 | } 11 | } 12 | } 13 | */ 14 | function parseArea(area) { 15 | var coordinates = []; 16 | area = area.getElementsByTagName(ns + "Point"); 17 | for (var i in area) { 18 | if (area[i].nodeName == ns + "Point") { 19 | var point = area[i]; 20 | var coord = []; 21 | coord[0] = parseFloat(point.getAttribute("Longitude")); 22 | coord[1] = parseFloat(point.getAttribute("Latitude")); 23 | if (point.getAttribute("Elevation")) { 24 | coord[2] = parseFloat(point.getAttribute("Elevation")); 25 | } 26 | coordinates.push(coord); 27 | } 28 | } 29 | coordinates.push(coordinates[0]); //close ring 30 | return coordinates; 31 | } 32 | 33 | /* 34 | function parseArrow(arrow) { 35 | var coordinates = []; 36 | var arrowHead = []; 37 | for (var i in arrow.childNodes){ 38 | if (arrow.childNodes[i].nodeName == 'Arrowhead'){ 39 | arrowHead = parsePoint(arrow.childNodes[i]); 40 | } 41 | if (arrow.childNodes[i].nodeName == 'Points'){ 42 | for (var j in arrow.childNodes[i].childNodes){ 43 | if (arrow.childNodes[i].childNodes[j].nodeName == 'Point'){ 44 | coordinates.unshift( parsePoint(arrow.childNodes[i].childNodes[j]) ); 45 | } 46 | } 47 | } 48 | } 49 | coordinates.push(arrowHead);//Add arrow head last in multipoint 50 | return coordinates; 51 | } 52 | */ 53 | /* 54 | function parseCircle(line) { 55 | var coordinates = [0,0]; 56 | for (var i in line.childNodes){ 57 | if (line.childNodes[i].nodeName == 'CenterPoint'){ 58 | coordinates[0] = parsePoint(line.childNodes[i]); 59 | } 60 | if (line.childNodes[i].nodeName == 'PerimeterPoint'){ 61 | coordinates[1] = parsePoint(line.childNodes[i]); 62 | } 63 | } 64 | return coordinates; 65 | } 66 | */ 67 | /* 68 | function parseCorridor(corridor) { 69 | var coordinates = []; 70 | var width = 0; 71 | for (var i in corridor.childNodes){ 72 | if (corridor.childNodes[i].nodeName == 'Width'){ 73 | width = corridor.childNodes[i].textContent; 74 | } 75 | if (corridor.childNodes[i].nodeName == 'Points'){ 76 | for (var j in corridor.childNodes[i].childNodes){ 77 | if (corridor.childNodes[i].childNodes[j].nodeName == 'Point'){ 78 | coordinates.push( parsePoint(corridor.childNodes[i].childNodes[j]) ); 79 | } 80 | } 81 | } 82 | } 83 | coordinates.push(width);//Add width last in array, we fix this later 84 | return coordinates; 85 | } 86 | */ 87 | 88 | function parseLine(line) { 89 | var coordinates = []; 90 | line = line.getElementsByTagName(ns + "Point"); 91 | for (var i in line) { 92 | if (line[i].nodeName == ns + "Point") { 93 | var point = line[i]; 94 | var coord = []; 95 | coord[0] = parseFloat(point.getAttribute("Longitude")); 96 | coord[1] = parseFloat(point.getAttribute("Latitude")); 97 | if (point.getAttribute("Elevation")) { 98 | coord[2] = parseFloat(point.getAttribute("Elevation")); 99 | } 100 | coordinates.push(coord); 101 | } 102 | } 103 | return coordinates; 104 | } 105 | 106 | /* 107 | function parseTwoPointArrow(arrow) { 108 | var coordinates = [0,0,0]; 109 | for (var i in arrow.childNodes){ 110 | if (arrow.childNodes[i].nodeName == 'StartPoint'){ 111 | coordinates[1] = parsePoint(arrow.childNodes[i]); 112 | } 113 | if (arrow.childNodes[i].nodeName == 'EndPoint' || arrow.childNodes[i].nodeName == 'Endpoint'){ 114 | coordinates[0] = parsePoint(arrow.childNodes[i]); 115 | } 116 | if (arrow.childNodes[i].nodeName == 'Arrowhead' || arrow.childNodes[i].nodeName == 'ArrowHead'){ 117 | coordinates[2] = parsePoint(arrow.childNodes[i]); 118 | } 119 | } 120 | console.log(coordinates) 121 | return coordinates; 122 | } 123 | */ 124 | /* 125 | function parseTwoPointCorridor(line) { 126 | var coordinates = [0,0,0]; 127 | for (var i in line.childNodes){ 128 | if (line.childNodes[i].nodeName == 'StartPoint'){ 129 | coordinates[0] = parsePoint(line.childNodes[i]); 130 | } 131 | if (line.childNodes[i].nodeName == 'EndPoint' || line.childNodes[i].nodeName == 'Endpoint'){ 132 | coordinates[1] = parsePoint(line.childNodes[i]); 133 | } 134 | if (line.childNodes[i].nodeName == 'Width'){ 135 | coordinates[2] = line.childNodes[i].textContent; 136 | } 137 | } 138 | return coordinates; 139 | } 140 | */ 141 | /* 142 | function parseTwoPointLine(line) { 143 | var coordinates = [0,0]; 144 | for (var i in line.childNodes){ 145 | if (line.childNodes[i].nodeName == 'StartPoint'){ 146 | //we reverse them because MIR vs 2525 147 | coordinates[1] = parsePoint(line.childNodes[i]); 148 | } 149 | if (line.childNodes[i].nodeName == 'EndPoint' || line.childNodes[i].nodeName == 'Endpoint'){ 150 | coordinates[0] = parsePoint(line.childNodes[i]); 151 | } 152 | } 153 | return coordinates; 154 | } 155 | */ 156 | 157 | function parsePoint(point) { 158 | var coordinates = [0, 0]; 159 | point = point.getElementsByTagName(ns + "Point")[0]; 160 | coordinates[0] = parseFloat(point.getAttribute("Longitude")); 161 | coordinates[1] = parseFloat(point.getAttribute("Latitude")); 162 | if (point.getAttribute("Elevation")) { 163 | coordinates[2] = parseFloat(point.getAttribute("Elevation")); 164 | } 165 | return coordinates; 166 | } 167 | 168 | function parseSymbol(symbol) { 169 | var feature = { type: "Feature", properties: {} }; 170 | 171 | var symbolNodes = {}; 172 | for (var i in symbol.childNodes) { 173 | symbolNodes[symbol.childNodes[i].nodeName] = symbol.childNodes[i]; 174 | } 175 | 176 | var symbolDefinition = symbolNodes[ns + "Symbol_Definition"]; 177 | for (i in symbolDefinition.childNodes) { 178 | var nodeName = symbolDefinition.childNodes[i].nodeName; 179 | if (nodeName == "#text" || typeof nodeName === "undefined") continue; 180 | if (nodeName.indexOf(":") != -1) nodeName = nodeName.split(":")[1]; 181 | feature.properties[nodeName] = symbolDefinition.childNodes[i].textContent; 182 | } 183 | 184 | var operationalAttributes = symbolNodes[ns + "Operational_Attributes"]; 185 | for (i in operationalAttributes.childNodes) { 186 | nodeName = operationalAttributes.childNodes[i].nodeName; 187 | if (nodeName == "#text" || typeof nodeName === "undefined") continue; 188 | if (nodeName.indexOf(":") != -1) nodeName = nodeName.split(":")[1]; 189 | feature.properties[nodeName] = 190 | operationalAttributes.childNodes[i].textContent; 191 | } 192 | 193 | var displayAttributes = symbolNodes[ns + "Display_Attributes"]; 194 | for (i in displayAttributes.childNodes) { 195 | nodeName = displayAttributes.childNodes[i].nodeName; 196 | if (nodeName == "#text" || typeof nodeName === "undefined") continue; 197 | if (nodeName.indexOf(":") != -1) nodeName = nodeName.split(":")[1]; 198 | feature.properties[nodeName] = 199 | displayAttributes.childNodes[i].textContent; 200 | } 201 | 202 | switch (feature.properties["Symbol_Category"]) { 203 | case "AREA": 204 | feature.geometry = { 205 | type: "Polygon", 206 | coordinates: [parseArea(symbolNodes[ns + "Symbol_Points"])] 207 | }; 208 | break; 209 | case "BIOCHEM": 210 | if ( 211 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 212 | .length == 1 213 | ) { 214 | feature.geometry = { 215 | type: "Point", 216 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 217 | }; 218 | } else { 219 | feature.geometry = { 220 | type: "Polygon", 221 | coordinates: [parseArea(symbolNodes[ns + "Symbol_Points"])] 222 | }; 223 | } 224 | break; 225 | //BOUNDARY, 226 | case "EQUIPMENT": 227 | feature.geometry = { 228 | type: "Point", 229 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 230 | }; 231 | break; 232 | //GROUP , 233 | case "INSTALLATION": 234 | feature.geometry = { 235 | type: "Point", 236 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 237 | }; 238 | break; 239 | case "LINE": 240 | feature.geometry = { 241 | type: "LineString", 242 | coordinates: parseLine(symbolNodes[ns + "Symbol_Points"]) 243 | }; 244 | break; 245 | case "MINE": 246 | if ( 247 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 248 | .length == 1 249 | ) { 250 | feature.geometry = { 251 | type: "Point", 252 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 253 | }; 254 | } else { 255 | feature.geometry = { 256 | type: "Polygon", 257 | coordinates: [parseArea(symbolNodes[ns + "Symbol_Points"])] 258 | }; 259 | } 260 | break; 261 | case "MOOTW": 262 | feature.geometry = { 263 | type: "Point", 264 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 265 | }; 266 | break; 267 | case "NOT_SPECIFIED": 268 | if ( 269 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 270 | .length == 1 271 | ) { 272 | feature.geometry = { 273 | type: "Point", 274 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 275 | }; 276 | } else { 277 | console.warn( 278 | "cannot handle Symbol_Category: " + 279 | feature.properties["Symbol_Category"] 280 | ); 281 | console.warn(feature.properties["Symbol_Name"]); 282 | console.warn(symbol); 283 | } 284 | break; 285 | case "NUCLEAR": 286 | if ( 287 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 288 | .length == 1 289 | ) { 290 | feature.geometry = { 291 | type: "Point", 292 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 293 | }; 294 | } else { 295 | feature.geometry = { 296 | type: "Polygon", 297 | coordinates: [parseArea(symbolNodes[ns + "Symbol_Points"])] 298 | }; 299 | } 300 | break; 301 | case "OBSTACLE": 302 | if ( 303 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 304 | .length == 1 305 | ) { 306 | feature.geometry = { 307 | type: "Point", 308 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 309 | }; 310 | } else { 311 | console.warn( 312 | "cannot handle Symbol_Category: " + 313 | feature.properties["Symbol_Category"] 314 | ); 315 | console.warn(symbol); 316 | } 317 | break; 318 | case "POINT": 319 | if ( 320 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 321 | .length == 1 322 | ) { 323 | feature.geometry = { 324 | type: "Point", 325 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 326 | }; 327 | } else { 328 | // OK this is bonkers, but i found some errors in some of my sample files... 329 | feature.geometry = { 330 | type: "LineString", 331 | coordinates: parseLine(symbolNodes[ns + "Symbol_Points"]) 332 | }; 333 | } 334 | break; 335 | case "SIG_INT": 336 | if ( 337 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 338 | .length == 1 339 | ) { 340 | feature.geometry = { 341 | type: "Point", 342 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 343 | }; 344 | } else { 345 | console.warn( 346 | "cannot handle Symbol_Category: " + 347 | feature.properties["Symbol_Category"] 348 | ); 349 | console.warn(symbol); 350 | } 351 | break; 352 | case "TARGET": 353 | if ( 354 | symbolNodes[ns + "Symbol_Points"].getElementsByTagName(ns + "Point") 355 | .length == 1 356 | ) { 357 | feature.geometry = { 358 | type: "Point", 359 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 360 | }; 361 | } else { 362 | feature.geometry = { 363 | type: "Polygon", 364 | coordinates: [parseArea(symbolNodes[ns + "Symbol_Points"])] 365 | }; 366 | } 367 | break; 368 | case "UNIT": 369 | feature.geometry = { 370 | type: "Point", 371 | coordinates: parsePoint(symbolNodes[ns + "Symbol_Points"]) 372 | }; 373 | break; 374 | default: 375 | console.warn( 376 | "cannot handle Symbol_Category: " + 377 | feature.properties["Symbol_Category"] 378 | ); 379 | console.warn(symbol); 380 | } 381 | return feature; 382 | } 383 | 384 | if (typeof xml == "string") { 385 | xml = new DOMParser().parseFromString(xml, "text/xml"); 386 | } 387 | var ns = ""; 388 | if (xml.firstChild.nodeName.indexOf(":") != -1) { 389 | ns = xml.firstChild.nodeName.split(":")[0] + ":"; 390 | } 391 | 392 | var symbols = xml.getElementsByTagName(ns + "Symbol"); 393 | for (var sym in symbols) { 394 | if (symbols[sym].nodeName) { 395 | features = features.concat(parseSymbol(symbols[sym])); 396 | } 397 | } 398 | 399 | var rawGeoJSON = { type: "FeatureCollection", features: features }; 400 | return ms.format.GeoJSON(rawGeoJSON, { 401 | Additional_Info1: "additionalInformation", 402 | Additional_Info2: "additionalInformation1", 403 | Additional_Info3: "additionalInformation1", 404 | Common_Identifier: "commonIdentifier", 405 | Higher_Formation: "higherFormation", 406 | Unique_Designator1: "uniqueDesignation", 407 | Unique_Designator2: "uniqueDesignation1", 408 | Staff_Comments: "staffComments", 409 | Symbol_Code: "sidc", 410 | DTG_1: "dtg", 411 | DTG_2: "dtg1", 412 | //Speed: 'speed', 413 | //Direction: 'direction', 414 | //Altitude_Depth: 'altitudeDepth', 415 | Reinforced_or_Reduced: "reinforcedReduced", 416 | Quantity: "quantity", 417 | //Combat_Effectiveness: 'combatEffectiveness', 418 | Signature_Equipment: "signatureEquipment", 419 | IFF_SIF: "iffSif", 420 | Special_C2HQ: "specialHeadquarters" 421 | }); 422 | } 423 | 424 | if (typeof module !== "undefined") { 425 | module.exports = ArmyXML; 426 | } 427 | -------------------------------------------------------------------------------- /src/format/geojson.js: -------------------------------------------------------------------------------- 1 | function GeoJSON(data, mapping) { 2 | if (typeof mapping == "undefined") { 3 | mapping = {}; 4 | } 5 | // If input is a string, parse it to JSON 6 | if (typeof data == "string") { 7 | data = JSON.parse(data); 8 | for (var key in data) { 9 | this[key] = data[key]; 10 | } 11 | } 12 | 13 | // Parse and clone the JSON 14 | var feature_copy = []; 15 | for (var i = 0; i < data.features.length; i++) { 16 | var feature = data.features[i]; 17 | var f = { type: "Feature", properties: {} }; 18 | if (feature.geometry) { 19 | f.geometry = { 20 | type: feature.geometry.type, 21 | coordinates: feature.geometry.coordinates 22 | }; 23 | } 24 | for (key in feature.properties) { 25 | if (mapping.hasOwnProperty(key)) { 26 | f.properties[mapping[key]] = feature.properties[key]; 27 | } else { 28 | f.properties[key] = feature.properties[key]; 29 | } 30 | } 31 | feature_copy.push(f); 32 | } 33 | return { type: "FeatureCollection", features: feature_copy }; 34 | } 35 | 36 | module.exports = GeoJSON; 37 | -------------------------------------------------------------------------------- /src/format/slf.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function SLF(xml) { 4 | var features = []; 5 | 6 | function parseSIDC(sidc) { 7 | for (var i in sidc.childNodes) { 8 | if (sidc.childNodes[i].nodeName == "SymbolCodeString") { 9 | return sidc.childNodes[i].textContent; 10 | } 11 | } 12 | } 13 | 14 | function parseArea(area) { 15 | var coordinates = []; 16 | for (var i in area.childNodes) { 17 | if (area.childNodes[i].nodeName == "Points") { 18 | for (var j in area.childNodes[i].childNodes) { 19 | if (area.childNodes[i].childNodes[j].nodeName == "Point") { 20 | coordinates.push(parsePoint(area.childNodes[i].childNodes[j])); 21 | } 22 | } 23 | } 24 | } 25 | coordinates.push(coordinates[0]); //close ring 26 | return coordinates; 27 | } 28 | 29 | function parseArrow(arrow) { 30 | var coordinates = []; 31 | var arrowHead = []; 32 | for (var i in arrow.childNodes) { 33 | if (arrow.childNodes[i].nodeName == "Arrowhead") { 34 | arrowHead = parsePoint(arrow.childNodes[i]); 35 | } 36 | if (arrow.childNodes[i].nodeName == "Points") { 37 | for (var j in arrow.childNodes[i].childNodes) { 38 | if (arrow.childNodes[i].childNodes[j].nodeName == "Point") { 39 | coordinates.unshift(parsePoint(arrow.childNodes[i].childNodes[j])); 40 | } 41 | } 42 | } 43 | } 44 | coordinates.push(arrowHead); //Add arrow head last in multipoint 45 | return coordinates; 46 | } 47 | 48 | function parseCircle(line) { 49 | var coordinates = [0, 0]; 50 | for (var i in line.childNodes) { 51 | if (line.childNodes[i].nodeName == "CenterPoint") { 52 | coordinates[0] = parsePoint(line.childNodes[i]); 53 | } 54 | if (line.childNodes[i].nodeName == "PerimeterPoint") { 55 | coordinates[1] = parsePoint(line.childNodes[i]); 56 | } 57 | } 58 | return coordinates; 59 | } 60 | 61 | function parseCorridor(corridor) { 62 | var coordinates = []; 63 | var width = 0; 64 | for (var i in corridor.childNodes) { 65 | if (corridor.childNodes[i].nodeName == "Width") { 66 | width = corridor.childNodes[i].textContent; 67 | } 68 | if (corridor.childNodes[i].nodeName == "Points") { 69 | for (var j in corridor.childNodes[i].childNodes) { 70 | if (corridor.childNodes[i].childNodes[j].nodeName == "Point") { 71 | coordinates.push(parsePoint(corridor.childNodes[i].childNodes[j])); 72 | } 73 | } 74 | } 75 | } 76 | coordinates.push(width); //Add width last in array, we fix this later 77 | return coordinates; 78 | } 79 | 80 | function parseLine(line) { 81 | var coordinates = []; 82 | for (var i in line.childNodes) { 83 | if (line.childNodes[i].nodeName == "Points") { 84 | for (var j in line.childNodes[i].childNodes) { 85 | if (line.childNodes[i].childNodes[j].nodeName == "Point") { 86 | coordinates.push(parsePoint(line.childNodes[i].childNodes[j])); 87 | } 88 | } 89 | } 90 | } 91 | return coordinates; 92 | } 93 | 94 | function parseTwoPointArrow(arrow) { 95 | var coordinates = [0, 0, 0]; 96 | for (var i in arrow.childNodes) { 97 | if (arrow.childNodes[i].nodeName == "StartPoint") { 98 | coordinates[1] = parsePoint(arrow.childNodes[i]); 99 | } 100 | if ( 101 | arrow.childNodes[i].nodeName == "EndPoint" || 102 | arrow.childNodes[i].nodeName == "Endpoint" 103 | ) { 104 | coordinates[0] = parsePoint(arrow.childNodes[i]); 105 | } 106 | if ( 107 | arrow.childNodes[i].nodeName == "Arrowhead" || 108 | arrow.childNodes[i].nodeName == "ArrowHead" 109 | ) { 110 | coordinates[2] = parsePoint(arrow.childNodes[i]); 111 | } 112 | } 113 | console.warn(coordinates); 114 | return coordinates; 115 | } 116 | 117 | function parseTwoPointCorridor(line) { 118 | var coordinates = [0, 0, 0]; 119 | for (var i in line.childNodes) { 120 | if (line.childNodes[i].nodeName == "StartPoint") { 121 | coordinates[0] = parsePoint(line.childNodes[i]); 122 | } 123 | if ( 124 | line.childNodes[i].nodeName == "EndPoint" || 125 | line.childNodes[i].nodeName == "Endpoint" 126 | ) { 127 | coordinates[1] = parsePoint(line.childNodes[i]); 128 | } 129 | if (line.childNodes[i].nodeName == "Width") { 130 | coordinates[2] = line.childNodes[i].textContent; 131 | } 132 | } 133 | return coordinates; 134 | } 135 | 136 | function parseTwoPointLine(line) { 137 | var coordinates = [0, 0]; 138 | for (var i in line.childNodes) { 139 | if (line.childNodes[i].nodeName == "StartPoint") { 140 | //we reverse them because MIR vs 2525 141 | coordinates[1] = parsePoint(line.childNodes[i]); 142 | } 143 | if ( 144 | line.childNodes[i].nodeName == "EndPoint" || 145 | line.childNodes[i].nodeName == "Endpoint" 146 | ) { 147 | coordinates[0] = parsePoint(line.childNodes[i]); 148 | } 149 | } 150 | return coordinates; 151 | } 152 | 153 | function parsePoint(point) { 154 | var coordinates = [0, 0]; 155 | for (var i in point.childNodes) { 156 | if (point.childNodes[i].nodeName == "Longitude") { 157 | coordinates[0] = parseFloat(point.childNodes[i].textContent); 158 | } 159 | if (point.childNodes[i].nodeName == "Latitude") { 160 | coordinates[1] = parseFloat(point.childNodes[i].textContent); 161 | } 162 | } 163 | return coordinates; 164 | } 165 | 166 | function parseLocation(location) { 167 | var locationType = location.getAttribute("xsi:type"); 168 | switch (locationType) { 169 | case "Area": 170 | return { type: "Polygon", coordinates: [parseArea(location)] }; 171 | //break; 172 | case "Arrow": 173 | return { type: "LineString", coordinates: parseArrow(location) }; 174 | //break; 175 | case "Circle": 176 | return { type: "LineString", coordinates: parseCircle(location) }; 177 | //break; 178 | case "Corridor": 179 | return { type: "Corridor", coordinates: parseCorridor(location) }; // We fix Corridors later 180 | //break; 181 | case "Line": 182 | return { type: "LineString", coordinates: parseLine(location) }; 183 | //break; 184 | case "Point": 185 | return { type: "Point", coordinates: parsePoint(location) }; 186 | //break; 187 | case "PolyPoint": 188 | return { type: "LineString", coordinates: parseLine(location) }; //I know this isn't a line but they are stored in the same way. 189 | //break; 190 | case "Rectangle": 191 | return { 192 | type: "Rectangle", 193 | coordinates: parseTwoPointCorridor(location) 194 | }; // We will fix TwoPointCorridor later 195 | //break; 196 | case "TwoPointArrow": 197 | return { 198 | type: "LineString", 199 | coordinates: parseTwoPointArrow(location) 200 | }; 201 | //break; 202 | case "TwoPointCorridor": 203 | return { 204 | type: "TwoPointCorridor", 205 | coordinates: parseTwoPointCorridor(location) 206 | }; // We will fix TwoPointCorridor later 207 | //break; 208 | case "TwoPointLine": 209 | return { type: "LineString", coordinates: parseTwoPointLine(location) }; 210 | //break; 211 | default: 212 | console.warn( 213 | "SitaWare Layer File: TODO parse location type " + locationType 214 | ); 215 | } 216 | } 217 | 218 | function parseSymbols(symbols) { 219 | var features = []; 220 | for (var i in symbols.childNodes) { 221 | if (symbols.childNodes[i].nodeName == "Symbol") { 222 | var symbol = symbols.childNodes[i]; 223 | var symbolType = symbol.getAttribute("xsi:type"); 224 | var feature = { type: "Feature", properties: {} }; 225 | 226 | if ( 227 | [ 228 | "Aviation", 229 | "BattlePosition", 230 | "BoundaryLine", 231 | "Equipment", 232 | "GenericShape", 233 | "Incident", 234 | "Installation", 235 | "Minefield", 236 | "TacticalGraphic", 237 | "TextArea", 238 | "Unit" 239 | ].indexOf(symbolType) != -1 240 | ) { 241 | for (var j in symbol.childNodes) { 242 | var nodeName = symbol.childNodes[j].nodeName; 243 | if (typeof nodeName === "undefined") continue; 244 | switch (nodeName) { 245 | case "Location": 246 | feature.geometry = parseLocation(symbol.childNodes[j]); 247 | if (feature.geometry && feature.geometry.type == "Corridor") { 248 | var points = feature.geometry.coordinates; 249 | feature.properties.distance = points[points.length - 1]; 250 | points.pop(); 251 | feature.geometry = { 252 | type: "LineString", 253 | coordinates: points 254 | }; 255 | } 256 | if (feature.geometry && feature.geometry.type == "Rectangle") { 257 | points = feature.geometry.coordinates; 258 | feature.properties.distance = points[points.length - 1]; 259 | points.pop(); 260 | feature.geometry = { 261 | type: "LineString", 262 | coordinates: points 263 | }; 264 | } 265 | if ( 266 | feature.geometry && 267 | feature.geometry.type == "TwoPointCorridor" 268 | ) { 269 | //TODO make sure that we are drawing this in the right direction 270 | points = feature.geometry.coordinates; 271 | var coordinates = [points[0], points[1]]; 272 | var width = points[2]; 273 | var bearing = ms.geometry.bearingBetween( 274 | points[1], 275 | points[0] 276 | ); 277 | coordinates.push( 278 | ms.geometry.toDistanceBearing( 279 | ms.geometry.pointBetween(points[0], points[1], 0.5), 280 | width / 2, 281 | bearing - 90 282 | ) 283 | ); 284 | //coordinates.push( ms.geometry.toDistanceBearing(points[1],width/2,bearing-90)); 285 | //coordinates.push(points[0]); 286 | 287 | feature.geometry = { 288 | type: "LineString", 289 | coordinates: coordinates 290 | }; 291 | } 292 | break; 293 | case "SymbolCode": 294 | feature.properties.SymbolCode = parseSIDC(symbol.childNodes[j]); 295 | break; 296 | case "#text": 297 | break; 298 | default: 299 | feature.properties[nodeName] = symbol.childNodes[j].textContent; 300 | } 301 | } 302 | if (typeof feature.geometry !== "undefined") { 303 | features.push(feature); 304 | } 305 | } else { 306 | console.warn( 307 | "SitaWare Layer File: TODO parse symbol type " + symbolType 308 | ); 309 | } 310 | } 311 | } 312 | return features; 313 | } 314 | 315 | function parseLayer(layer) { 316 | var features = []; 317 | for (var i in layer.childNodes) { 318 | if (layer.childNodes[i].nodeName == "Name") { 319 | //console.log('LAYER: ' + layer.childNodes[i].textContent); 320 | } 321 | if (layer.childNodes[i].nodeName == "Symbols") { 322 | //console.log(parseSymbols( layer.childNodes[i] )) 323 | features = features.concat(parseSymbols(layer.childNodes[i])); 324 | } 325 | } 326 | return features; 327 | } 328 | 329 | if (typeof xml == "string") { 330 | xml = new DOMParser().parseFromString(xml, "text/xml"); 331 | } 332 | 333 | var layers = xml.getElementsByTagName("Layer"); // For SLF files 334 | for (var lyr in layers) { 335 | features = features.concat(parseLayer(layers[lyr])); 336 | } 337 | layers = xml.getElementsByTagName("Overlay"); // For SPF files 338 | for (lyr in layers) { 339 | features = features.concat(parseLayer(layers[lyr])); 340 | } 341 | 342 | // Fix circles 343 | for (var f in features) { 344 | var sidc = features[f].properties.SymbolCode; 345 | var genericSIDC = 346 | sidc.substr(0, 1) + "-" + sidc.substr(2, 1) + "-" + sidc.substr(4, 6); 347 | if ( 348 | [ 349 | "G-F-ATC---", 350 | "G-F-ACSC--", 351 | "G-F-ACAC--", 352 | "G-F-ACFC--", 353 | "G-F-ACNC--", 354 | "G-F-ACRC--", 355 | "G-F-ACPC--", 356 | "G-F-AZIC--", 357 | "G-F-AZXC--", 358 | "G-F-AZSC--", 359 | "G-F-AZCC--", 360 | "G-F-AZDC--", 361 | "G-F-AZFC--", 362 | "G-F-AZZC--", 363 | "G-F-AZBC--", 364 | "G-F-AZVC--", 365 | "X---I-----" 366 | ].indexOf(genericSIDC) != -1 367 | ) { 368 | var points = features[f].geometry.coordinates; 369 | features[f].properties.distance = ms.geometry.distanceBetween( 370 | points[0], 371 | points[1] 372 | ); 373 | features[f].geometry = { type: "Point", coordinates: points[0] }; 374 | } 375 | } 376 | 377 | var rawGeoJSON = { type: "FeatureCollection", features: features }; 378 | return ms.format.GeoJSON(rawGeoJSON, { 379 | Aliases: "commonIdentifier", 380 | Name: "uniqueDesignation", 381 | StaffComments: "staffComments", 382 | SymbolCode: "sidc", 383 | Timestamp: "dtg" 384 | }); 385 | } 386 | 387 | if (typeof module !== "undefined") { 388 | module.exports = SLF; 389 | } 390 | -------------------------------------------------------------------------------- /src/geometry.js: -------------------------------------------------------------------------------- 1 | var geometry = {}; 2 | 3 | geometry.bearingBetween = require("./geometry/bearingbetween.js"); 4 | geometry.circle = require("./geometry/circle.js"); 5 | geometry.circleCorridorPolygon = require("./geometry/circlecorridorpolygon.js"); 6 | geometry.corridor = require("./geometry/corridor.js"); 7 | geometry.distanceBetween = require("./geometry/distancebetween.js"); 8 | geometry.pointBetween = require("./geometry/pointbetween.js"); 9 | geometry.rectangle = require("./geometry/rectangle.js"); 10 | geometry.toDistanceBearing = require("./geometry/todistancebearing.js"); 11 | 12 | module.exports = geometry; 13 | -------------------------------------------------------------------------------- /src/geometry/bearingbetween.js: -------------------------------------------------------------------------------- 1 | // Calculates the bearing between two points in meter 2 | function bearingBetween(p1, p2) { 3 | var l1 = p1[0] * (Math.PI / 180); 4 | var l2 = p2[0] * (Math.PI / 180); 5 | var f1 = p1[1] * (Math.PI / 180); 6 | var f2 = p2[1] * (Math.PI / 180); 7 | var y = Math.sin(l2 - l1) * Math.cos(f2); 8 | var x = 9 | Math.cos(f1) * Math.sin(f2) - 10 | Math.sin(f1) * Math.cos(f2) * Math.cos(l2 - l1); 11 | return Math.atan2(y, x) / (Math.PI / 180); 12 | } 13 | 14 | module.exports = bearingBetween; 15 | -------------------------------------------------------------------------------- /src/geometry/circle.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a circle withe a radius in meters 4 | module.exports = function(feature) { 5 | var p = feature.geometry.coordinates; 6 | var r = feature.properties.distance; 7 | var geometry = { type: "Polygon" }; 8 | geometry.coordinates = [[]]; 9 | for (var direction = 360; direction >= 0; direction -= 5) { 10 | geometry.coordinates[0].push( 11 | ms.geometry.toDistanceBearing(p, r, direction) 12 | ); 13 | } 14 | return { geometry: geometry }; 15 | }; 16 | -------------------------------------------------------------------------------- /src/geometry/circlecorridorpolygon.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | module.exports = function(feature) { 4 | var annotation = {}; 5 | var geometry; 6 | annotation.geometry = { type: "Point" }; 7 | 8 | switch (feature.geometry.type) { 9 | case "Point": 10 | geometry = ms.geometry.circle(feature).geometry; 11 | annotation.geometry.coordinates = feature.geometry.coordinates; 12 | break; 13 | case "LineString": 14 | geometry = ms.geometry.rectangle(feature).geometry; 15 | annotation.geometry.coordinates = ms.geometry.pointBetween( 16 | feature.geometry.coordinates[0], 17 | feature.geometry.coordinates[1], 18 | 0.5 19 | ); 20 | break; 21 | case "Polygon": 22 | geometry = { type: feature.geometry.type }; 23 | geometry.coordinates = feature.geometry.coordinates; 24 | // add annotation geometry 25 | break; 26 | default: 27 | console.warn("Invalid feature type in SIDC: " + feature.properties.sidc); 28 | } 29 | 30 | return { annotation: annotation, geometry: geometry }; 31 | }; 32 | -------------------------------------------------------------------------------- /src/geometry/corridor.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a corridor with a widht in meters 4 | function corridor(feature) { 5 | var direction; 6 | var points = feature.geometry.coordinates; 7 | var width = feature.properties.distance; 8 | var geometry = { type: "Polygon" }; 9 | geometry.coordinates = [[]]; 10 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 360) % 360; 11 | geometry.coordinates[0].push( 12 | ms.geometry.toDistanceBearing(points[0], width / 2, direction - 90) 13 | ); 14 | for (var j = 1; j < points.length - 1; j++) { 15 | var direction1 = 16 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 17 | var direction2 = 18 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 19 | var factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 20 | geometry.coordinates[0].push( 21 | ms.geometry.toDistanceBearing( 22 | points[j], 23 | width / 2 * factor, 24 | (direction1 + direction2) / 2 25 | ) 26 | ); 27 | } 28 | 29 | direction = 30 | (ms.geometry.bearingBetween( 31 | points[points.length - 1], 32 | points[points.length - 2] 33 | ) + 34 | 180) % 35 | 360; 36 | geometry.coordinates[0].push( 37 | ms.geometry.toDistanceBearing( 38 | points[points.length - 1], 39 | width / 2, 40 | direction - 90 41 | ) 42 | ); 43 | geometry.coordinates[0].push( 44 | ms.geometry.toDistanceBearing( 45 | points[points.length - 1], 46 | width / 2, 47 | direction + 90 48 | ) 49 | ); 50 | 51 | for (j = points.length - 2; j > 0; j--) { 52 | direction1 = 53 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 54 | direction2 = 55 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 56 | factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 57 | geometry.coordinates[0].push( 58 | ms.geometry.toDistanceBearing( 59 | points[j], 60 | -(width / 2) * factor, 61 | (direction1 + direction2) / 2 62 | ) 63 | ); 64 | } 65 | 66 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 360) % 360; 67 | geometry.coordinates[0].push( 68 | ms.geometry.toDistanceBearing(points[0], width / 2, direction + 90) 69 | ); 70 | geometry.coordinates[0].push( 71 | ms.geometry.toDistanceBearing(points[0], width / 2, direction - 90) 72 | ); //Close line 73 | return { geometry: geometry }; 74 | } 75 | 76 | module.exports = corridor; 77 | -------------------------------------------------------------------------------- /src/geometry/distancebetween.js: -------------------------------------------------------------------------------- 1 | // Calculates the great circle distance between two points in meter 2 | function distanceBetween(p1, p2) { 3 | var lng1 = p1[0]; 4 | var lng2 = p2[0]; 5 | var lat1 = p1[1]; 6 | var lat2 = p2[1]; 7 | 8 | var latRad1 = lat1 * (Math.PI / 180); 9 | var latRad2 = lat2 * (Math.PI / 180); 10 | var deltaLat = (lat2 - lat1) * (Math.PI / 180); 11 | var delataLng = (lng2 - lng1) * (Math.PI / 180); 12 | 13 | var a = 14 | Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + 15 | Math.cos(latRad1) * 16 | Math.cos(latRad2) * 17 | Math.sin(delataLng / 2) * 18 | Math.sin(delataLng / 2); 19 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 20 | return (6371e3 * c).toFixed(1); // we don't expect more precision than this... 21 | } 22 | 23 | module.exports = distanceBetween; 24 | -------------------------------------------------------------------------------- /src/geometry/pointbetween.js: -------------------------------------------------------------------------------- 1 | // Calculates a point between two other points at any fractional distance f between them 2 | function pointBetween(p1, p2, f) { 3 | var lng1 = p1[0]; 4 | var lng2 = p2[0]; 5 | var lat1 = p1[1]; 6 | var lat2 = p2[1]; 7 | 8 | var lngRad1 = lng1 * (Math.PI / 180); 9 | var lngRad2 = lng2 * (Math.PI / 180); 10 | var latRad1 = lat1 * (Math.PI / 180); 11 | var latRad2 = lat2 * (Math.PI / 180); 12 | 13 | var deltaLat = (lat2 - lat1) * (Math.PI / 180); 14 | var delataLng = (lng2 - lng1) * (Math.PI / 180); 15 | var a = 16 | Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + 17 | Math.cos(latRad1) * 18 | Math.cos(latRad2) * 19 | Math.sin(delataLng / 2) * 20 | Math.sin(delataLng / 2); 21 | var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // Angular distance 22 | 23 | var A = Math.sin((1 - f) * c) / Math.sin(c); 24 | var B = Math.sin(f * c) / Math.sin(c); 25 | 26 | var x = 27 | A * Math.cos(latRad1) * Math.cos(lngRad1) + 28 | B * Math.cos(latRad2) * Math.cos(lngRad2); 29 | var y = 30 | A * Math.cos(latRad1) * Math.sin(lngRad1) + 31 | B * Math.cos(latRad2) * Math.sin(lngRad2); 32 | var z = A * Math.sin(latRad1) + B * Math.sin(latRad2); 33 | 34 | var lng3 = Math.atan2(y, x) / (Math.PI / 180); 35 | var lat3 = 36 | (Math.atan2(z, Math.sqrt(x * x + y * y)) / (Math.PI / 180) + 540) % 360 - 37 | 180; 38 | 39 | return [lng3, lat3]; 40 | } 41 | 42 | module.exports = pointBetween; 43 | -------------------------------------------------------------------------------- /src/geometry/rectangle.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws rectangle from input feature 4 | module.exports = function(feature) { 5 | // A rectangle is just a two point corridor 6 | return ms.geometry.corridor(feature); 7 | }; 8 | -------------------------------------------------------------------------------- /src/geometry/todistancebearing.js: -------------------------------------------------------------------------------- 1 | // Calculates the bearing between two points in meter 2 | function toDistanceBearing(point, dist, bearing) { 3 | var angularDist = dist / 6371e3; 4 | bearing = bearing * (Math.PI / 180); 5 | var lng = point[0] * (Math.PI / 180); 6 | var lat = point[1] * (Math.PI / 180); 7 | var lat2 = Math.asin( 8 | Math.sin(lat) * Math.cos(angularDist) + 9 | Math.cos(lat) * Math.sin(angularDist) * Math.cos(bearing) 10 | ); 11 | var lng2 = 12 | lng + 13 | Math.atan2( 14 | Math.sin(bearing) * Math.sin(angularDist) * Math.cos(lat), 15 | Math.cos(angularDist) - Math.sin(lat) * Math.sin(lat2) 16 | ); 17 | lat2 = lat2 / (Math.PI / 180); 18 | lng2 = (lng2 / (Math.PI / 180) + 540) % 360 - 180; 19 | return [lng2, lat2]; 20 | } 21 | 22 | module.exports = toDistanceBearing; 23 | -------------------------------------------------------------------------------- /src/geometryconverter.js: -------------------------------------------------------------------------------- 1 | var geometryConverter = {}; 2 | 3 | geometryConverter[ 4 | "AIRSPACE COORDINATION AREA" 5 | ] = require("./geometryconverter/airspace-coordination-area.js"); 6 | geometryConverter["AMBUSH"] = require("./geometryconverter/ambush.js"); 7 | geometryConverter[ 8 | "ARTILLERY TARGET INTELLIGENCE ZONE" 9 | ] = require("./geometryconverter/artillery-target-intelligence-zone.js"); 10 | geometryConverter["BLOCK"] = require("./geometryconverter/block.js"); 11 | geometryConverter["BREACH"] = require("./geometryconverter/breach.js"); 12 | geometryConverter["BYPASS"] = require("./geometryconverter/bypass.js"); 13 | geometryConverter[ 14 | "CALL FOR FIRE ZONE" 15 | ] = require("./geometryconverter/call-for-fire-zone.js"); 16 | geometryConverter["CANALIZE"] = require("./geometryconverter/canalize.js"); 17 | geometryConverter[ 18 | "CENSOR ZONE" 19 | ] = require("./geometryconverter/censor-zone.js"); 20 | //geometryConverter.circle = require("./geometryconverter/circle.js"); 21 | geometryConverter["CLEAR"] = require("./geometryconverter/clear.js"); 22 | geometryConverter.corridor = require("./geometryconverter/corridor.js"); 23 | geometryConverter.cover = require("./geometryconverter/cover.js"); 24 | geometryConverter[ 25 | "CRITICAL FRIENDLY ZONE" 26 | ] = require("./geometryconverter/critical-friendly-zone.js"); 27 | geometryConverter[ 28 | "DEAD SPACE AREA" 29 | ] = require("./geometryconverter/dead-space-area.js"); 30 | geometryConverter["DELAY"] = require("./geometryconverter/delay.js"); 31 | geometryConverter[ 32 | "FIRE SUPPORT AREA" 33 | ] = require("./geometryconverter/fire-support-area.js"); 34 | geometryConverter["FIX"] = require("./geometryconverter/fix.js"); 35 | geometryConverter[ 36 | "FREE FIRE AREA" 37 | ] = require("./geometryconverter/free-fire-area.js"); 38 | geometryConverter.guard = require("./geometryconverter/guard.js"); 39 | geometryConverter["ISOLATE"] = require("./geometryconverter/isolate.js"); 40 | geometryConverter[ 41 | "MAIN ATTACK" 42 | ] = require("./geometryconverter/main-attack.js"); 43 | geometryConverter[ 44 | "NAMED AREA OF INTEREST" 45 | ] = require("./geometryconverter/named-area-of-interest.js"); 46 | geometryConverter.occupy = require("./geometryconverter/occupy.js"); 47 | geometryConverter[ 48 | "RESTRICTIVE FIRE AREA" 49 | ] = require("./geometryconverter/restrictive-fire-area.js"); 50 | geometryConverter.searchArea = require("./geometryconverter/search-area.js"); 51 | geometryConverter[ 52 | "SENSOR ZONE" 53 | ] = require("./geometryconverter/sensor-zone.js"); 54 | geometryConverter[ 55 | "SUPPORTING ATTACK" 56 | ] = require("./geometryconverter/supporting-attack.js"); 57 | geometryConverter[ 58 | "TARGET BUILD-UP AREA" 59 | ] = require("./geometryconverter/target-build-up-area.js"); 60 | geometryConverter[ 61 | "TARGET VALUE AREA" 62 | ] = require("./geometryconverter/target-value-area.js"); 63 | geometryConverter[ 64 | "TARGETED AREA OF INTEREST" 65 | ] = require("./geometryconverter/targeted-area-of-interest.js"); 66 | geometryConverter[ 67 | "TERMINALLY GUIDED MUNITION FOOTPRINT" 68 | ] = require("./geometryconverter/terminally-guided-munition-footprint.js"); 69 | geometryConverter[ 70 | "ZONE OF RESPONSIBILITY" 71 | ] = require("./geometryconverter/zone-of-responsibility.js"); 72 | 73 | module.exports = geometryConverter; 74 | -------------------------------------------------------------------------------- /src/geometryconverter/airspace-coordination-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a NAI 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "ACA"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.altitudeDepth) 15 | annotations[0].properties.text += 16 | "\nMIN ALT: " + feature.properties.altitudeDepth; 17 | if (feature.properties.altitudeDepth1) 18 | annotations[0].properties.text += 19 | "\nMAX ALT: " + feature.properties.altitudeDepth1; 20 | if (feature.properties.additionalInformation1) 21 | annotations[0].properties.text += 22 | "\nGrids " + feature.properties.additionalInformation1; 23 | if (feature.properties.dtg) 24 | annotations[0].properties.text += "\nEFF: " + feature.properties.dtg; 25 | if (feature.properties.dtg1) 26 | annotations[0].properties.text += "\n- " + feature.properties.dtg1; 27 | 28 | var polygon = ms.geometry.circleCorridorPolygon(feature); 29 | geometry = polygon.geometry; 30 | if (polygon.annotation.hasOwnProperty("geometry")) { 31 | annotations[0].geometry = polygon.annotation.geometry; 32 | } 33 | 34 | return { geometry: geometry, annotations: annotations }; 35 | }; 36 | -------------------------------------------------------------------------------- /src/geometryconverter/ambush.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function block(feature) { 4 | var geom; 5 | var points = feature.geometry.coordinates; 6 | var geometry = { type: "MultiLineString" }; 7 | geometry.coordinates = []; 8 | 9 | var midpoint = ms.geometry.pointBetween(points[1], points[2], 0.5); 10 | var bearing1 = (ms.geometry.bearingBetween(points[1], points[2]) + 360) % 360; 11 | var bearing2 = (ms.geometry.bearingBetween(points[1], points[0]) + 360) % 360; 12 | 13 | var distance = 14 | Math.sin((bearing1 - bearing2) * (Math.PI / 180)) * 15 | ms.geometry.distanceBetween(points[0], points[1]); 16 | if (distance < 0) { 17 | // Wrong order in input 18 | points = [points[0], points[2], points[1]]; 19 | bearing1 = (ms.geometry.bearingBetween(points[1], points[2]) + 360) % 360; 20 | bearing2 = (ms.geometry.bearingBetween(points[1], points[0]) + 360) % 360; 21 | distance = -distance; 22 | } 23 | var rotationpoint = ms.geometry.toDistanceBearing( 24 | midpoint, 25 | distance, 26 | bearing1 + 90 27 | ); 28 | var radius = ms.geometry.distanceBetween(rotationpoint, points[1]); 29 | var b1 = (ms.geometry.bearingBetween(rotationpoint, points[1]) + 360) % 360; 30 | var b2 = (ms.geometry.bearingBetween(rotationpoint, points[2]) + 360) % 360; 31 | if (b1 > b2) { 32 | b2 = b2 + 360; 33 | } 34 | var midAngle = (b1 + b2) / 2; 35 | var tip = ms.geometry.toDistanceBearing( 36 | rotationpoint, 37 | distance * 2, 38 | midAngle 39 | ); 40 | var b3 = (ms.geometry.bearingBetween(tip, rotationpoint) + 360) % 360; 41 | 42 | // Arc 43 | geom = []; 44 | geom.push(points[1]); 45 | 46 | for (var i = b1; i <= b2; i += 5) { 47 | geom.push(ms.geometry.toDistanceBearing(rotationpoint, radius, i)); 48 | } 49 | geom.push(points[2]); 50 | geometry.coordinates.push(geom); 51 | 52 | // Lines 53 | var diff = (b2 - b1) / 7; 54 | var p1, p2; 55 | for (i = 1; i <= 6; i++) { 56 | geom = []; 57 | p1 = ms.geometry.toDistanceBearing(rotationpoint, radius, b1 + diff * i); 58 | p2 = ms.geometry.toDistanceBearing(p1, distance * 0.3, b3); 59 | geom.push(p1, p2); 60 | geometry.coordinates.push(geom); 61 | } 62 | 63 | // Arrow 64 | geom = []; 65 | geom.push(ms.geometry.toDistanceBearing(rotationpoint, radius, midAngle)); 66 | geom.push( 67 | ms.geometry.toDistanceBearing(rotationpoint, distance * 2, midAngle) 68 | ); 69 | geometry.coordinates.push(geom); 70 | 71 | // Arrow head 72 | geom = []; 73 | geom.push(ms.geometry.toDistanceBearing(tip, distance * 0.2, b3 + 45)); 74 | geom.push(tip); 75 | geom.push(ms.geometry.toDistanceBearing(tip, distance * 0.2, b3 - 45)); 76 | geometry.coordinates.push(geom); 77 | 78 | return { geometry: geometry }; 79 | } 80 | 81 | module.exports = block; 82 | -------------------------------------------------------------------------------- /src/geometryconverter/artillery-target-intelligence-zone.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "ATI ZONE"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | /*if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1;*/ 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/block.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function block(feature) { 4 | //var direction, width; 5 | var annotations = [{}]; 6 | var points = feature.geometry.coordinates; 7 | 8 | var geometry = { type: "MultiLineString" }; 9 | geometry.coordinates = []; 10 | 11 | var geometry1 = []; 12 | geometry1.push(points[0], points[1]); 13 | 14 | var geometry2 = []; 15 | var midpoint = ms.geometry.pointBetween(points[0], points[1], 0.5); 16 | geometry2.push(points[2], midpoint); 17 | 18 | geometry.coordinates = [geometry1, geometry2]; 19 | 20 | annotations[0].geometry = { type: "Point" }; 21 | annotations[0].properties = {}; 22 | annotations[0].properties.text = "B"; 23 | annotations[0].geometry.coordinates = ms.geometry.pointBetween( 24 | midpoint, 25 | points[2], 26 | 0.5 27 | ); 28 | 29 | return { geometry: geometry, annotations: annotations }; 30 | } 31 | 32 | module.exports = block; 33 | -------------------------------------------------------------------------------- /src/geometryconverter/breach.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function canalize(feature) { 4 | //var direction, width; 5 | var annotations = [{}]; 6 | 7 | var points = feature.geometry.coordinates; 8 | var geometry = { type: "MultiLineString" }; 9 | var scale = ms.geometry.distanceBetween(points[0], points[1]); 10 | var pMid = ms.geometry.pointBetween(points[0], points[1], 0.5); 11 | var length = ms.geometry.distanceBetween(pMid, points[2]); 12 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 13 | 14 | geometry.coordinates = []; 15 | 16 | var geom = [points[0]]; 17 | geom.push(ms.geometry.toDistanceBearing(points[0], length, bearing + 90)); 18 | geom.push(ms.geometry.toDistanceBearing(points[1], length, bearing + 90)); 19 | geom.push(points[1]); 20 | geometry.coordinates.push(geom); 21 | 22 | geom = []; 23 | geom.push( 24 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing - 45) 25 | ); 26 | geom.push( 27 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing - 45 + 180) 28 | ); 29 | geometry.coordinates.push(geom); 30 | 31 | geom = []; 32 | geom.push( 33 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing + 45) 34 | ); 35 | geom.push( 36 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing + 45 + 180) 37 | ); 38 | geometry.coordinates.push(geom); 39 | 40 | annotations[0].geometry = { type: "Point" }; 41 | annotations[0].properties = {}; 42 | annotations[0].properties.text = "B"; 43 | annotations[0].geometry.coordinates = points[2]; 44 | 45 | return { geometry: geometry, annotations: annotations }; 46 | } 47 | 48 | module.exports = canalize; 49 | -------------------------------------------------------------------------------- /src/geometryconverter/bypass.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function bypass(feature) { 4 | //var direction, width; 5 | var annotations = [{}]; 6 | 7 | var points = feature.geometry.coordinates; 8 | var geometry = { type: "MultiLineString" }; 9 | var scale = ms.geometry.distanceBetween(points[0], points[1]); 10 | var pMid = ms.geometry.pointBetween(points[0], points[1], 0.5); 11 | var length = ms.geometry.distanceBetween(pMid, points[2]); 12 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 13 | 14 | geometry.coordinates = []; 15 | 16 | var geom = [points[0]]; 17 | geom.push(ms.geometry.toDistanceBearing(points[0], length, bearing + 90)); 18 | geom.push(ms.geometry.toDistanceBearing(points[1], length, bearing + 90)); 19 | geom.push(points[1]); 20 | geometry.coordinates.push(geom); 21 | 22 | geom = []; 23 | geom.push( 24 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing + 90 - 30) 25 | ); 26 | geom.push(points[0]); 27 | geom.push( 28 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing + 90 + 30) 29 | ); 30 | geometry.coordinates.push(geom); 31 | 32 | geom = []; 33 | geom.push( 34 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing + 90 - 30) 35 | ); 36 | geom.push(points[1]); 37 | geom.push( 38 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing + 90 + 30) 39 | ); 40 | geometry.coordinates.push(geom); 41 | 42 | annotations[0].geometry = { type: "Point" }; 43 | annotations[0].properties = {}; 44 | annotations[0].properties.text = "B"; 45 | annotations[0].geometry.coordinates = points[2]; 46 | 47 | return { geometry: geometry, annotations: annotations }; 48 | } 49 | 50 | module.exports = bypass; 51 | -------------------------------------------------------------------------------- /src/geometryconverter/call-for-fire-zone.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "CFF ZONE"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | /*if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1;*/ 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/canalize.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function canalize(feature) { 4 | //var direction, width; 5 | var annotations = [{}]; 6 | 7 | var points = feature.geometry.coordinates; 8 | var geometry = { type: "MultiLineString" }; 9 | var scale = ms.geometry.distanceBetween(points[0], points[1]); 10 | var pMid = ms.geometry.pointBetween(points[0], points[1], 0.5); 11 | var length = ms.geometry.distanceBetween(pMid, points[2]); 12 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 13 | 14 | geometry.coordinates = []; 15 | 16 | var geom = [points[0]]; 17 | geom.push(ms.geometry.toDistanceBearing(points[0], length, bearing + 90)); 18 | geom.push(ms.geometry.toDistanceBearing(points[1], length, bearing + 90)); 19 | geom.push(points[1]); 20 | geometry.coordinates.push(geom); 21 | 22 | geom = []; 23 | geom.push( 24 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing + 45) 25 | ); 26 | geom.push( 27 | ms.geometry.toDistanceBearing(points[0], scale * 0.2, bearing + 45 + 180) 28 | ); 29 | geometry.coordinates.push(geom); 30 | 31 | geom = []; 32 | geom.push( 33 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing - 45) 34 | ); 35 | geom.push( 36 | ms.geometry.toDistanceBearing(points[1], scale * 0.2, bearing - 45 + 180) 37 | ); 38 | geometry.coordinates.push(geom); 39 | 40 | annotations[0].geometry = { type: "Point" }; 41 | annotations[0].properties = {}; 42 | annotations[0].properties.text = "C"; 43 | annotations[0].geometry.coordinates = points[2]; 44 | 45 | return { geometry: geometry, annotations: annotations }; 46 | } 47 | 48 | module.exports = canalize; 49 | -------------------------------------------------------------------------------- /src/geometryconverter/censor-zone.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "CENSOR ZONE"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/circle.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a circle withe a radius in meters 4 | module.exports = function(feature) { 5 | var p = feature.geometry.coordinates; 6 | var r = feature.properties.distance; 7 | var geometry = { type: "Polygon" }; 8 | geometry.coordinates = [[]]; 9 | for (var direction = 360; direction >= 0; direction -= 5) { 10 | geometry.coordinates[0].push( 11 | ms.geometry.toDistanceBearing(p, r, direction) 12 | ); 13 | } 14 | return { geometry: geometry }; 15 | }; 16 | -------------------------------------------------------------------------------- /src/geometryconverter/clear.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function clear(feature) { 4 | //var direction, width; 5 | var annotations = [{}]; 6 | 7 | var points = feature.geometry.coordinates; 8 | var geometry = { type: "MultiLineString" }; 9 | var scale = ms.geometry.distanceBetween(points[0], points[1]); 10 | 11 | geometry.coordinates = []; 12 | 13 | var geom = [points[0], points[1]]; 14 | geometry.coordinates.push(geom); 15 | 16 | var pMid = ms.geometry.pointBetween(points[0], points[1], 0.5); 17 | var length = ms.geometry.distanceBetween(pMid, points[2]); 18 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 19 | 20 | geom = [pMid, ms.geometry.toDistanceBearing(pMid, length, bearing + 90)]; 21 | geometry.coordinates.push(geom); 22 | 23 | annotations[0].geometry = { type: "Point" }; 24 | annotations[0].properties = {}; 25 | annotations[0].properties.text = "C"; 26 | annotations[0].geometry.coordinates = ms.geometry.pointBetween( 27 | pMid, 28 | geom[1], 29 | 0.5 30 | ); 31 | 32 | geom = []; 33 | geom.push(ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60)); 34 | geom.push(pMid); 35 | geom.push( 36 | ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60 + 60) 37 | ); 38 | geometry.coordinates.push(geom); 39 | 40 | pMid = ms.geometry.pointBetween(points[0], points[1], 0.2); 41 | geom = [pMid, ms.geometry.toDistanceBearing(pMid, length, bearing + 90)]; 42 | geometry.coordinates.push(geom); 43 | 44 | geom = []; 45 | geom.push(ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60)); 46 | geom.push(pMid); 47 | geom.push( 48 | ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60 + 60) 49 | ); 50 | geometry.coordinates.push(geom); 51 | 52 | pMid = ms.geometry.pointBetween(points[0], points[1], 0.8); 53 | geom = [pMid, ms.geometry.toDistanceBearing(pMid, length, bearing + 90)]; 54 | geometry.coordinates.push(geom); 55 | 56 | geom = []; 57 | geom.push(ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60)); 58 | geom.push(pMid); 59 | geom.push( 60 | ms.geometry.toDistanceBearing(pMid, scale * 0.15, bearing + 60 + 60) 61 | ); 62 | geometry.coordinates.push(geom); 63 | 64 | return { geometry: geometry, annotations: annotations }; 65 | } 66 | 67 | module.exports = clear; 68 | -------------------------------------------------------------------------------- /src/geometryconverter/corridor.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a corridor with a widht in meters 4 | function corridor(feature) { 5 | var direction; 6 | var points = feature.geometry.coordinates; 7 | var width = feature.properties.distance; 8 | var geometry = { type: "Polygon" }; 9 | geometry.coordinates = [[]]; 10 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 360) % 360; 11 | geometry.coordinates[0].push( 12 | ms.geometry.toDistanceBearing(points[0], width / 2, direction - 90) 13 | ); 14 | for (var j = 1; j < points.length - 1; j++) { 15 | var direction1 = 16 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 17 | var direction2 = 18 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 19 | var factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 20 | geometry.coordinates[0].push( 21 | ms.geometry.toDistanceBearing( 22 | points[j], 23 | width / 2 * factor, 24 | (direction1 + direction2) / 2 25 | ) 26 | ); 27 | } 28 | 29 | direction = 30 | (ms.geometry.bearingBetween( 31 | points[points.length - 1], 32 | points[points.length - 2] 33 | ) + 34 | 180) % 35 | 360; 36 | geometry.coordinates[0].push( 37 | ms.geometry.toDistanceBearing( 38 | points[points.length - 1], 39 | width / 2, 40 | direction - 90 41 | ) 42 | ); 43 | geometry.coordinates[0].push( 44 | ms.geometry.toDistanceBearing( 45 | points[points.length - 1], 46 | width / 2, 47 | direction + 90 48 | ) 49 | ); 50 | 51 | for (j = points.length - 2; j > 0; j--) { 52 | direction1 = 53 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 54 | direction2 = 55 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 56 | factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 57 | geometry.coordinates[0].push( 58 | ms.geometry.toDistanceBearing( 59 | points[j], 60 | -(width / 2) * factor, 61 | (direction1 + direction2) / 2 62 | ) 63 | ); 64 | } 65 | 66 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 360) % 360; 67 | geometry.coordinates[0].push( 68 | ms.geometry.toDistanceBearing(points[0], width / 2, direction + 90) 69 | ); 70 | geometry.coordinates[0].push( 71 | ms.geometry.toDistanceBearing(points[0], width / 2, direction - 90) 72 | ); //Close line 73 | return { geometry: geometry }; 74 | } 75 | 76 | module.exports = corridor; 77 | -------------------------------------------------------------------------------- /src/geometryconverter/cover.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a circle withe a radius in meters 4 | function cover(feature) { 5 | var p = feature.geometry.coordinates; 6 | var scale = Math.max( 7 | ms.geometry.distanceBetween(p[0], p[1]), 8 | ms.geometry.distanceBetween(p[0], p[2]) 9 | ); 10 | var geometry = { type: "MultiLineString" }; 11 | geometry.coordinates = [[]]; 12 | 13 | var geom = []; 14 | var pMid = ms.geometry.pointBetween(p[0], p[1], 0.5); 15 | var bearing = ms.geometry.bearingBetween(p[0], p[1]); 16 | geom.push(p[0]); 17 | geom.push( 18 | ms.geometry.toDistanceBearing(pMid, scale * 0.05, bearing + (120 - 180)) 19 | ); 20 | var pMid2 = ms.geometry.toDistanceBearing(pMid, scale * 0.05, bearing + 120); 21 | geom.push(pMid2); 22 | geom.push(p[1]); 23 | geometry.coordinates.push(geom); 24 | 25 | geom = []; 26 | bearing = ms.geometry.bearingBetween(p[1], pMid2); 27 | geom.push(ms.geometry.toDistanceBearing(p[1], scale * 0.08, bearing - 45)); 28 | geom.push(p[1]); 29 | geom.push(ms.geometry.toDistanceBearing(p[1], scale * 0.08, bearing + 45)); 30 | geometry.coordinates.push(geom); 31 | 32 | geom = []; 33 | pMid = ms.geometry.pointBetween(p[0], p[2], 0.5); 34 | bearing = ms.geometry.bearingBetween(p[0], p[2]); 35 | geom.push(p[0]); 36 | geom.push( 37 | ms.geometry.toDistanceBearing(pMid, scale * 0.05, bearing + (120 - 180)) 38 | ); 39 | pMid2 = ms.geometry.toDistanceBearing(pMid, scale * 0.05, bearing + 120); 40 | geom.push(pMid2); 41 | geom.push(p[2]); 42 | geometry.coordinates.push(geom); 43 | 44 | geom = []; 45 | bearing = ms.geometry.bearingBetween(p[2], pMid2); 46 | geom.push(ms.geometry.toDistanceBearing(p[2], scale * 0.08, bearing - 45)); 47 | geom.push(p[2]); 48 | geom.push(ms.geometry.toDistanceBearing(p[2], scale * 0.08, bearing + 45)); 49 | geometry.coordinates.push(geom); 50 | 51 | return { geometry: geometry }; 52 | } 53 | 54 | module.exports = cover; 55 | -------------------------------------------------------------------------------- /src/geometryconverter/critical-friendly-zone.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "CF ZONE"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/dead-space-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "DA"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/delay.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function delay(feature) { 4 | var annotations = [{}]; 5 | var directionFactor = -1; 6 | var points = feature.geometry.coordinates; 7 | 8 | var width = ms.geometry.distanceBetween(points[1], points[2]); 9 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 10 | 11 | var geometry = { type: "MultiLineString" }; 12 | 13 | geometry.coordinates = []; 14 | 15 | var geometry1 = []; 16 | geometry1.push(points[0]); 17 | geometry1.push(points[1]); 18 | //console.log('arrow bearing ' + bearing) 19 | //console.log('fjomp bearing ' + ms.geometry.bearingBetween(points[1],points[2])) 20 | 21 | var midpoint = ms.geometry.pointBetween(points[1], points[2], 0.5); 22 | var curveBearing = ms.geometry.bearingBetween(points[1], points[2]); 23 | if (curveBearing < 0 && bearing < 0) directionFactor = 1; // OK 24 | //if (curveBearing > 0 && bearing < 0)directionFactor = -1; // OK 25 | //if (curveBearing < 0 && bearing > 0)directionFactor = -1; // OK 26 | //if (curveBearing > 0 && bearing > 0)directionFactor = -1; // OK 27 | //var directionFactor = (Math.abs(curveBearing)/curveBearing)*(Math.abs(bearing)/bearing); 28 | 29 | for (var i = 10; i < 180; i += 10) { 30 | geometry1.push( 31 | ms.geometry.toDistanceBearing( 32 | midpoint, 33 | width / 2, 34 | curveBearing + i * directionFactor + 180 35 | ) 36 | ); 37 | } 38 | 39 | geometry1.push(points[2]); 40 | 41 | var geometry2 = []; 42 | geometry2.push( 43 | ms.geometry.toDistanceBearing(points[0], width * 0.4, bearing + 45) 44 | ); 45 | geometry2.push(points[0]); 46 | geometry2.push( 47 | ms.geometry.toDistanceBearing(points[0], width * 0.4, bearing - 45) 48 | ); 49 | 50 | geometry.coordinates = [geometry1, geometry2]; 51 | 52 | annotations[0].geometry = { type: "Point" }; 53 | annotations[0].properties = {}; 54 | annotations[0].properties.text = feature.properties.dtg 55 | ? feature.properties.dtg + "\n" 56 | : ""; 57 | annotations[0].properties.text += "D"; 58 | annotations[0].geometry.coordinates = ms.geometry.pointBetween( 59 | points[0], 60 | points[1], 61 | 0.5 62 | ); 63 | 64 | return { geometry: geometry, annotations: annotations }; 65 | } 66 | 67 | module.exports = delay; 68 | -------------------------------------------------------------------------------- /src/geometryconverter/fire-support-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = 11 | "FSA " + (feature.properties.uniqueDesignation || ""); 12 | if (feature.properties.dtg) 13 | annotations[0].properties.text += "\n" + feature.properties.dtg; 14 | if (feature.properties.dtg1) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 16 | 17 | var polygon = ms.geometry.circleCorridorPolygon(feature); 18 | geometry = polygon.geometry; 19 | if (polygon.annotation.hasOwnProperty("geometry")) { 20 | annotations[0].geometry = polygon.annotation.geometry; 21 | } 22 | 23 | return { geometry: geometry, annotations: annotations }; 24 | }; 25 | -------------------------------------------------------------------------------- /src/geometryconverter/fix.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function fix(feature) { 4 | //var direction, width; 5 | var points = feature.geometry.coordinates; 6 | 7 | var length = ms.geometry.distanceBetween(points[0], points[1]); 8 | var bearing = ms.geometry.bearingBetween(points[0], points[1]); 9 | var widht = length * 0.10; 10 | 11 | var geometry = { type: "MultiLineString" }; 12 | 13 | geometry.coordinates = []; 14 | 15 | var geometry1 = []; 16 | 17 | geometry1.push(points[0]); 18 | 19 | geometry1.push(ms.geometry.pointBetween(points[0], points[1], 0.2)); 20 | 21 | geometry1.push( 22 | ms.geometry.toDistanceBearing( 23 | ms.geometry.pointBetween(points[0], points[1], 0.25), 24 | widht, 25 | bearing + 90 26 | ) 27 | ); 28 | geometry1.push( 29 | ms.geometry.toDistanceBearing( 30 | ms.geometry.pointBetween(points[0], points[1], 0.3), 31 | widht, 32 | bearing - 90 33 | ) 34 | ); 35 | geometry1.push( 36 | ms.geometry.toDistanceBearing( 37 | ms.geometry.pointBetween(points[0], points[1], 0.35), 38 | widht, 39 | bearing + 90 40 | ) 41 | ); 42 | geometry1.push( 43 | ms.geometry.toDistanceBearing( 44 | ms.geometry.pointBetween(points[0], points[1], 0.4), 45 | widht, 46 | bearing - 90 47 | ) 48 | ); 49 | geometry1.push( 50 | ms.geometry.toDistanceBearing( 51 | ms.geometry.pointBetween(points[0], points[1], 0.45), 52 | widht, 53 | bearing + 90 54 | ) 55 | ); 56 | geometry1.push( 57 | ms.geometry.toDistanceBearing( 58 | ms.geometry.pointBetween(points[0], points[1], 0.5), 59 | widht, 60 | bearing - 90 61 | ) 62 | ); 63 | geometry1.push( 64 | ms.geometry.toDistanceBearing( 65 | ms.geometry.pointBetween(points[0], points[1], 0.55), 66 | widht, 67 | bearing + 90 68 | ) 69 | ); 70 | geometry1.push( 71 | ms.geometry.toDistanceBearing( 72 | ms.geometry.pointBetween(points[0], points[1], 0.6), 73 | widht, 74 | bearing - 90 75 | ) 76 | ); 77 | geometry1.push( 78 | ms.geometry.toDistanceBearing( 79 | ms.geometry.pointBetween(points[0], points[1], 0.65), 80 | widht, 81 | bearing + 90 82 | ) 83 | ); 84 | geometry1.push( 85 | ms.geometry.toDistanceBearing( 86 | ms.geometry.pointBetween(points[0], points[1], 0.7), 87 | widht, 88 | bearing - 90 89 | ) 90 | ); 91 | geometry1.push( 92 | ms.geometry.toDistanceBearing( 93 | ms.geometry.pointBetween(points[0], points[1], 0.75), 94 | widht, 95 | bearing + 90 96 | ) 97 | ); 98 | 99 | geometry1.push(ms.geometry.pointBetween(points[0], points[1], 0.8)); 100 | 101 | geometry1.push(points[1]); 102 | 103 | var geometry2 = []; 104 | geometry2.push( 105 | ms.geometry.toDistanceBearing(points[0], widht * 1.5, bearing + 45) 106 | ); 107 | geometry2.push(points[0]); 108 | geometry2.push( 109 | ms.geometry.toDistanceBearing(points[0], widht * 1.5, bearing - 45) 110 | ); 111 | 112 | geometry.coordinates = [geometry1, geometry2]; 113 | return { geometry: geometry }; 114 | } 115 | 116 | module.exports = fix; 117 | -------------------------------------------------------------------------------- /src/geometryconverter/free-fire-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "FFA"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/guard.js: -------------------------------------------------------------------------------- 1 | // Draws a circle withe a radius in meters 2 | function guard(feature) {} 3 | 4 | module.exports = guard; 5 | -------------------------------------------------------------------------------- /src/geometryconverter/isolate.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a circle withe a radius in meters 4 | function isolate(feature) { 5 | var p = feature.geometry.coordinates; 6 | var r = ms.geometry.distanceBetween(p[0], p[1]); 7 | var bearing = ms.geometry.bearingBetween(p[0], p[1]); 8 | 9 | var geometry = { type: "MultiLineString" }; 10 | geometry.coordinates = [[]]; 11 | for (var d = 0; d <= 340; d += 5) { 12 | geometry.coordinates[0].push( 13 | ms.geometry.toDistanceBearing(p[0], r, d + bearing) 14 | ); 15 | } 16 | 17 | for (d = 20; d <= 320; d += 40) { 18 | var geom = []; 19 | geom.push(ms.geometry.toDistanceBearing(p[0], r, d + bearing)); 20 | geom.push(ms.geometry.toDistanceBearing(p[0], r * 0.7, 10 + d + bearing)); 21 | geom.push(ms.geometry.toDistanceBearing(p[0], r, 20 + d + bearing)); 22 | geometry.coordinates.push(geom); 23 | } 24 | 25 | geom = []; 26 | var pEnd = ms.geometry.toDistanceBearing(p[0], r, 340 + bearing); 27 | geom.push( 28 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing - (90 - 15) + 45) 29 | ); 30 | geom.push(pEnd); 31 | geom.push( 32 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing - (90 - 15) - 45) 33 | ); 34 | geometry.coordinates.push(geom); 35 | 36 | return { geometry: geometry }; 37 | } 38 | 39 | module.exports = isolate; 40 | -------------------------------------------------------------------------------- /src/geometryconverter/main-attack.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a corridor with a widht in meters 4 | function mainAttack(feature) { 5 | var direction, width; 6 | var points = feature.geometry.coordinates; 7 | var arrowHead = points.pop(); 8 | var widthHeadRatio = 0.7; 9 | 10 | var geometry = { type: "MultiLineString" }; 11 | geometry.coordinates = []; 12 | 13 | var geometry1 = []; 14 | var geometry2 = []; 15 | 16 | // Width of the arrow 17 | direction = ms.geometry.bearingBetween(points[0], points[1]); 18 | var deltaDirection = 19 | direction - ms.geometry.bearingBetween(points[0], arrowHead); 20 | //console.log(deltaDirection) 21 | var distance = ms.geometry.distanceBetween(points[0], arrowHead); 22 | var arrowHead2 = ms.geometry.toDistanceBearing( 23 | points[0], 24 | distance, 25 | direction + deltaDirection 26 | ); 27 | width = ms.geometry.distanceBetween(arrowHead, arrowHead2) / 2; 28 | 29 | direction = 30 | (ms.geometry.bearingBetween( 31 | points[points.length - 1], 32 | points[points.length - 2] 33 | ) + 34 | 360) % 35 | 360; 36 | geometry1.push( 37 | ms.geometry.toDistanceBearing( 38 | points[points.length - 1], 39 | width * widthHeadRatio, 40 | direction - 90 41 | ) 42 | ); 43 | 44 | for (var j = points.length - 2; j > 0; j--) { 45 | var direction1 = 46 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 47 | var direction2 = 48 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 49 | var factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 50 | geometry1.push( 51 | ms.geometry.toDistanceBearing( 52 | points[j], 53 | width * widthHeadRatio * factor, 54 | (direction1 + direction2) / 2 55 | ) 56 | ); 57 | } 58 | 59 | // Arrowhead 60 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 180) % 360; 61 | geometry1.push( 62 | ms.geometry.toDistanceBearing( 63 | arrowHead, 64 | width * (1 - widthHeadRatio), 65 | direction + 90 66 | ) 67 | ); 68 | geometry1.push(arrowHead); 69 | geometry1.push(points[0]); 70 | geometry1.push(arrowHead2); 71 | geometry1.push( 72 | ms.geometry.toDistanceBearing( 73 | arrowHead2, 74 | width * (1 - widthHeadRatio), 75 | direction - 90 76 | ) 77 | ); 78 | 79 | geometry2.push( 80 | ms.geometry.toDistanceBearing( 81 | arrowHead, 82 | width * (1 - widthHeadRatio), 83 | direction + 90 84 | ) 85 | ); 86 | geometry2.push( 87 | ms.geometry.toDistanceBearing( 88 | points[0], 89 | width * 90 | (1 - widthHeadRatio) * 91 | Math.abs(1 / Math.tan(deltaDirection * (Math.PI / 180))), 92 | direction - 180 93 | ) 94 | ); 95 | geometry2.push( 96 | ms.geometry.toDistanceBearing( 97 | arrowHead2, 98 | width * (1 - widthHeadRatio), 99 | direction - 90 100 | ) 101 | ); 102 | 103 | for (j = 1; j < points.length - 1; j++) { 104 | direction1 = 105 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 106 | direction2 = 107 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 108 | factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 109 | geometry1.push( 110 | ms.geometry.toDistanceBearing( 111 | points[j], 112 | -(width * widthHeadRatio) * factor, 113 | (direction1 + direction2) / 2 114 | ) 115 | ); 116 | } 117 | 118 | direction = 119 | (ms.geometry.bearingBetween( 120 | points[points.length - 1], 121 | points[points.length - 2] 122 | ) + 123 | 360) % 124 | 360; 125 | geometry1.push( 126 | ms.geometry.toDistanceBearing( 127 | points[points.length - 1], 128 | width * widthHeadRatio, 129 | direction + 90 130 | ) 131 | ); 132 | 133 | geometry.coordinates = [geometry1, geometry2]; 134 | return { geometry: geometry }; 135 | } 136 | 137 | module.exports = mainAttack; 138 | -------------------------------------------------------------------------------- /src/geometryconverter/named-area-of-interest.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a NAI 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "NAI"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | 15 | var polygon = ms.geometry.circleCorridorPolygon(feature); 16 | geometry = polygon.geometry; 17 | if (polygon.annotation.hasOwnProperty("geometry")) { 18 | annotations[0].geometry = polygon.annotation.geometry; 19 | } 20 | 21 | return { geometry: geometry, annotations: annotations }; 22 | }; 23 | -------------------------------------------------------------------------------- /src/geometryconverter/occupy.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a circle withe a radius in meters 4 | function occupy(feature) { 5 | var p = feature.geometry.coordinates; 6 | var r = ms.geometry.distanceBetween(p[0], p[1]); 7 | var bearing = ms.geometry.bearingBetween(p[0], p[1]); 8 | 9 | var geometry = { type: "MultiLineString" }; 10 | geometry.coordinates = [[]]; 11 | for (var d = 0; d <= 340; d += 5) { 12 | geometry.coordinates[0].push( 13 | ms.geometry.toDistanceBearing(p[0], r, d + bearing) 14 | ); 15 | } 16 | 17 | var geom = []; 18 | var pEnd = ms.geometry.toDistanceBearing(p[0], r, 340 + bearing); 19 | geom.push( 20 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing - (90 - 15) + 45) 21 | ); 22 | geom.push(pEnd); 23 | geom.push( 24 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing - (90 - 15) - 45) 25 | ); 26 | geometry.coordinates.push(geom); 27 | 28 | geom = []; 29 | pEnd = ms.geometry.toDistanceBearing(p[0], r, 340 + bearing); 30 | geom.push( 31 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing + (90 + 15) + 45) 32 | ); 33 | geom.push(pEnd); 34 | geom.push( 35 | ms.geometry.toDistanceBearing(pEnd, r * 0.2, 320 + bearing + (90 + 15) - 45) 36 | ); 37 | geometry.coordinates.push(geom); 38 | 39 | return { geometry: geometry }; 40 | } 41 | 42 | module.exports = occupy; 43 | -------------------------------------------------------------------------------- /src/geometryconverter/restrictive-fire-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "RFA"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/search-area.js: -------------------------------------------------------------------------------- 1 | // Draws a circle withe a radius in meters 2 | function searchArea(feature) {} 3 | 4 | module.exports = searchArea; 5 | -------------------------------------------------------------------------------- /src/geometryconverter/sensor-zone.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "SENSOR ZONE"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/supporting-attack.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | // Draws a corridor with a widht in meters 3 | function supportingAttack(feature) { 4 | var direction, width; 5 | var points = feature.geometry.coordinates; 6 | var arrowHead = points.pop(); 7 | var widthHeadRatio = 0.7; 8 | 9 | var geometry = { type: "LineString" }; 10 | geometry.coordinates = []; 11 | 12 | var geometry1 = []; 13 | 14 | // Width of the arrow 15 | direction = ms.geometry.bearingBetween(points[0], points[1]); 16 | var deltaDirection = 17 | direction - ms.geometry.bearingBetween(points[0], arrowHead); 18 | //console.log(deltaDirection) 19 | var distance = ms.geometry.distanceBetween(points[0], arrowHead); 20 | var arrowHead2 = ms.geometry.toDistanceBearing( 21 | points[0], 22 | distance, 23 | direction + deltaDirection 24 | ); 25 | width = ms.geometry.distanceBetween(arrowHead, arrowHead2) / 2; 26 | 27 | direction = 28 | (ms.geometry.bearingBetween( 29 | points[points.length - 1], 30 | points[points.length - 2] 31 | ) + 32 | 360) % 33 | 360; 34 | geometry1.push( 35 | ms.geometry.toDistanceBearing( 36 | points[points.length - 1], 37 | width * widthHeadRatio, 38 | direction - 90 39 | ) 40 | ); 41 | 42 | for (var j = points.length - 2; j > 0; j--) { 43 | var direction1 = 44 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 45 | var direction2 = 46 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 47 | var factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 48 | geometry1.push( 49 | ms.geometry.toDistanceBearing( 50 | points[j], 51 | width * widthHeadRatio * factor, 52 | (direction1 + direction2) / 2 53 | ) 54 | ); 55 | } 56 | 57 | // Arrowhead 58 | direction = (ms.geometry.bearingBetween(points[0], points[1]) + 180) % 360; 59 | geometry1.push( 60 | ms.geometry.toDistanceBearing( 61 | arrowHead, 62 | width * (1 - widthHeadRatio), 63 | direction + 90 64 | ) 65 | ); 66 | geometry1.push(arrowHead); 67 | geometry1.push(points[0]); 68 | geometry1.push(arrowHead2); 69 | geometry1.push( 70 | ms.geometry.toDistanceBearing( 71 | arrowHead2, 72 | width * (1 - widthHeadRatio), 73 | direction - 90 74 | ) 75 | ); 76 | 77 | for (j = 1; j < points.length - 1; j++) { 78 | direction1 = 79 | (ms.geometry.bearingBetween(points[j], points[j + 1]) + 360) % 360; 80 | direction2 = 81 | (ms.geometry.bearingBetween(points[j], points[j - 1]) + 360) % 360; 82 | factor = 1 / Math.sin((direction2 - direction1) / 2 * (Math.PI / 180)); 83 | geometry1.push( 84 | ms.geometry.toDistanceBearing( 85 | points[j], 86 | -(width * widthHeadRatio) * factor, 87 | (direction1 + direction2) / 2 88 | ) 89 | ); 90 | } 91 | 92 | direction = 93 | (ms.geometry.bearingBetween( 94 | points[points.length - 1], 95 | points[points.length - 2] 96 | ) + 97 | 360) % 98 | 360; 99 | geometry1.push( 100 | ms.geometry.toDistanceBearing( 101 | points[points.length - 1], 102 | width * widthHeadRatio, 103 | direction + 90 104 | ) 105 | ); 106 | 107 | geometry.coordinates = geometry1; 108 | return { geometry: geometry }; 109 | } 110 | 111 | module.exports = supportingAttack; 112 | -------------------------------------------------------------------------------- /src/geometryconverter/target-build-up-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "TBA"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/target-value-area.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "TVAR"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/targeted-area-of-interest.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a NAI 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "TAI"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | 15 | var polygon = ms.geometry.circleCorridorPolygon(feature); 16 | geometry = polygon.geometry; 17 | if (polygon.annotation.hasOwnProperty("geometry")) { 18 | annotations[0].geometry = polygon.annotation.geometry; 19 | } 20 | 21 | return { geometry: geometry, annotations: annotations }; 22 | }; 23 | -------------------------------------------------------------------------------- /src/geometryconverter/terminally-guided-munition-footprint.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "TGMF"; 11 | /*if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1;*/ 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/geometryconverter/zone-of-responsibility.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | // Draws a Fire Support Area 4 | module.exports = function(feature) { 5 | var annotations = [{}]; 6 | var geometry; 7 | 8 | annotations[0].geometry = { type: "Point" }; 9 | annotations[0].properties = {}; 10 | annotations[0].properties.text = "ZOR"; 11 | if (feature.properties.uniqueDesignation) 12 | annotations[0].properties.text += 13 | "\n" + feature.properties.uniqueDesignation; 14 | if (feature.properties.dtg) 15 | annotations[0].properties.text += "\n" + feature.properties.dtg; 16 | if (feature.properties.dtg1) 17 | annotations[0].properties.text += "\n" + feature.properties.dtg1; 18 | 19 | var polygon = ms.geometry.circleCorridorPolygon(feature); 20 | geometry = polygon.geometry; 21 | if (polygon.annotation.hasOwnProperty("geometry")) { 22 | annotations[0].geometry = polygon.annotation.geometry; 23 | } 24 | 25 | return { geometry: geometry, annotations: annotations }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/graphic.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function graphic(feature) { 4 | this.SIDC = feature.properties.sidc; 5 | this.converted = false; 6 | this.geometry = feature.geometry; 7 | this.properties = this.getProperties(); 8 | 9 | if (this.properties.graphic) { 10 | // If we don't have a graphics cache, create one 11 | if (typeof ms._graphicCache === "undefined") { 12 | ms._graphicCache = {}; 13 | } 14 | 15 | // Letter based SIDC. 16 | if (!this.properties.numberSIDC) { 17 | if ( 18 | !ms._graphicCache.hasOwnProperty("letter-" + this.properties.numberSIDC) 19 | ) { 20 | var sidc = {}; 21 | ms._getLetterSIDCgraphic(sidc, this.properties.numberSIDC); 22 | ms._graphicCache["letter-" + this.properties.numberSIDC] = sidc; 23 | } 24 | var graphics = ms._graphicCache["letter-" + this.properties.numberSIDC]; 25 | var genericSIDC = 26 | this.SIDC.substr(0, 1) + 27 | "-" + 28 | this.SIDC.substr(2, 1) + 29 | "-" + 30 | this.SIDC.substr(4, 6); 31 | if (graphics[genericSIDC]) { 32 | var graphicObject = graphics[genericSIDC].call(this, feature); 33 | this.geometry = graphicObject.geometry; 34 | this.annotations = graphicObject.annotations; 35 | this.converted = true; 36 | } else { 37 | if (this.geometry.type != "Point") { 38 | // Points is likely symbols, remove this when everything is implemented. 39 | console.log( 40 | "Did not find graphic converter for: " + 41 | this.SIDC + 42 | " (" + 43 | this.geometry.type + 44 | ")" 45 | ); 46 | } 47 | } 48 | } else { 49 | // Number based SIDC 50 | console.log("TODO number sidc stuff"); 51 | } 52 | } 53 | } 54 | 55 | graphic.prototype.getProperties = require("./graphic/getproperties.js"); 56 | graphic.prototype.isConverted = function() { 57 | return this.converted; 58 | }; 59 | 60 | module.exports = graphic; 61 | -------------------------------------------------------------------------------- /src/graphic/getproperties.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | module.exports = function() { 4 | var properties = { 5 | // "activity" : false, //Is it an Activity 6 | affiliation: "", //Affiliation it is shown as (Friend/Hostile...) 7 | // "baseAffilation" : "", //Affiliation it belongs to (Friend/Hostile...) 8 | // "baseDimension" : "", //Dimension it belongs to (Air/Ground...) 9 | // "baseGeometry" : {g:"",bbox:{}}, //Geometry is a combination of dimension and affiliation (AirFriend/GroundHostile...) 10 | // "civilian" : false, //Is it Civilian 11 | // "condition" : "", //What condition is it in 12 | context: "", //Context of the symbol (Reality/Exercise...) 13 | dimension: "", //Dimension it is shown as (Air/Ground...) 14 | dimensionUnknown: false, //Is the dimension unknown 15 | echelon: "", //What echelon (Platoon/Company...) 16 | faker: false, //Is it a Faker 17 | fenintDummy: false, //Is it a feint/dummy 18 | // "fill" : this.fill, //Standard says it should be filled 19 | // "frame" : this.frame, //Standard says it should be framed 20 | functionid: "", //Part of SIDC referring to the icon. 21 | // "headquarters" : false, //Is it a Headquarters 22 | // "installation" : false, //Is it an Instalation 23 | joker: false, //Is it a Joker 24 | // "mobility" : "", //What mobility (Tracked/Sled) 25 | notpresent: "", //Is it Anticipated or Pending 26 | numberSIDC: false, //Is the SIDC number based 27 | // "space" : false, //Is it in Space 28 | // "taskForce" : false //Is it a task force 29 | graphic: false 30 | }; 31 | var mapping = {}; 32 | mapping.context = ["Reality", "Exercise", "Simulation"]; 33 | mapping.status = [ 34 | "Present", 35 | "Planned", 36 | "FullyCapable", 37 | "Damaged", 38 | "Destroyed", 39 | "FullToCapacity" 40 | ]; 41 | mapping.affiliation = ["Hostile", "Friend", "Neutral", "Unknown"]; 42 | mapping.dimension = ["Air", "Ground", "Sea", "Subsurface"]; 43 | 44 | properties.context = mapping.context[0]; 45 | 46 | if (this.monoColor != "") { 47 | properties.fill = false; 48 | } 49 | this.SIDC = String(this.SIDC).replace(/\*/g, "-").replace(/ /g, ""); 50 | 51 | properties.numberSIDC = !isNaN(this.SIDC); 52 | if (properties.numberSIDC) { 53 | //This is for new number based SIDCs 54 | 55 | if (typeof ms._getNumberProperties === "function") { 56 | properties = ms._getNumberPropertiesGraphic.call( 57 | this, 58 | properties, 59 | mapping 60 | ); 61 | } else { 62 | console.warn( 63 | "ms._getNumberPropertiesGraphic() is not present, you will need to load functionality for letter based SIDCs" 64 | ); 65 | } 66 | } else { 67 | //This would be old letter based SIDCs 68 | 69 | if (typeof ms._getLetterProperties === "function") { 70 | properties = ms._getLetterPropertiesGraphic.call( 71 | this, 72 | properties, 73 | mapping 74 | ); 75 | } else { 76 | console.warn( 77 | "ms._getLetterPropertiesGraphic() is not present, you will need to load functionality for letter based SIDCs" 78 | ); 79 | } 80 | } 81 | 82 | return properties; 83 | }; 84 | -------------------------------------------------------------------------------- /src/graphicslayer.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | function GraphicsLayer(data) { 4 | this.data = data; 5 | for (var i = 0; i < this.data.features.length; i++) { 6 | var feature = this.data.features[i]; 7 | 8 | feature.graphic = new ms.Graphic(feature); 9 | feature.geometry = feature.graphic.geometry; 10 | 11 | if (feature.geometry && feature.geometry.type == "Point") { 12 | var properties = feature.properties; 13 | properties.size = properties.size || 30; //TODO set default size value from setting 14 | if (properties.sidc.charAt(0) != "X") { 15 | //Skip SitaWare custom graphics for now 16 | feature.symbol = new ms.Symbol(properties); 17 | } 18 | } 19 | } 20 | } 21 | 22 | GraphicsLayer.prototype.asCesium = require("./graphicslayer/ascesium.js"); 23 | 24 | GraphicsLayer.prototype.asOpenLayers = require("./graphicslayer/asopenlayers.js"); 25 | 26 | module.exports = GraphicsLayer; 27 | -------------------------------------------------------------------------------- /src/graphicslayer/ascesium.js: -------------------------------------------------------------------------------- 1 | function asCesium() { 2 | var ratio = window.devicePixelRatio || 1; 3 | var entities = new Cesium.EntityCollection(); 4 | 5 | for (var i = 0; i < this.data.features.length; i++) { 6 | var feature = this.data.features[i]; 7 | 8 | if (feature.geometry.type == "Point") { 9 | console.info("point"); 10 | var properties = feature.properties; 11 | if (properties.sidc.charAt(0) != "X") { 12 | //TODO handle sitaware custom graphics 13 | var milsymbol = feature.symbol; 14 | var ctx = milsymbol.asCanvas(ratio); 15 | var entity = { 16 | position: Cesium.Cartesian3.fromDegrees( 17 | feature.geometry.coordinates[0], 18 | feature.geometry.coordinates[1] 19 | ), //Cesium.Cartesian3.fromArray( feature.geometry.coordinates ), 20 | billboard: { 21 | horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // default 22 | verticalOrigin: Cesium.VerticalOrigin.TOP, 23 | image: ctx, 24 | imageSubRegion: new Cesium.BoundingRectangle( 25 | 0, 26 | 0, 27 | ctx.width + 2, 28 | ctx.height + 2 29 | ), 30 | height: milsymbol.getSize().height, 31 | width: milsymbol.getSize().width, 32 | pixelOffset: new Cesium.Cartesian2( 33 | -milsymbol.getAnchor().x, 34 | -milsymbol.getAnchor().y 35 | ) // default: (0, 0) 36 | } 37 | }; 38 | entities.add(entity); 39 | } 40 | } 41 | 42 | if ( 43 | feature.graphic.isConverted() && 44 | (feature.geometry.type == "LineString" || 45 | feature.geometry.type == "MultiLineString") 46 | ) { 47 | //console.log('line') 48 | var lineparts; 49 | if (feature.geometry.type == "LineString") { 50 | lineparts = [feature.geometry.coordinates]; // Make linestring to a sort of multiline 51 | } else { 52 | lineparts = feature.geometry.coordinates; 53 | } 54 | 55 | for (var key in lineparts) { 56 | var coordinates = lineparts[key]; 57 | var positions = []; 58 | for (var c in coordinates) { 59 | positions.push( 60 | Cesium.Cartesian3.fromDegrees( 61 | coordinates[c][0], 62 | coordinates[c][1], 63 | coordinates[c][2] 64 | ) 65 | ); 66 | } 67 | 68 | entity = new Cesium.Entity({ 69 | polyline: new Cesium.PolylineGraphics({ 70 | positions: positions, 71 | material: Cesium.Color.BLACK, 72 | width: 1.5 73 | }) 74 | }); 75 | 76 | entities.add(entity); 77 | } 78 | } 79 | 80 | if (feature.graphic.isConverted() && feature.geometry.type == "Polygon") { 81 | coordinates = feature.geometry.coordinates[0]; 82 | positions = []; 83 | for (c in coordinates) { 84 | positions.push( 85 | Cesium.Cartesian3.fromDegrees( 86 | coordinates[c][0], 87 | coordinates[c][1], 88 | coordinates[c][2] 89 | ) 90 | ); 91 | } 92 | 93 | /*var entity = new Cesium.Entity({ 94 | polygon: new Cesium.PolygonGraphics({ 95 | hierarchy: new Cesium.PolygonHierarchy(positions), 96 | fill: false, 97 | outline: true, 98 | outlineColor: Cesium.Color.BLACK, 99 | outlineWidth: 3 100 | }) 101 | });*/ 102 | 103 | entity = new Cesium.Entity({ 104 | polyline: new Cesium.PolylineGraphics({ 105 | positions: positions, 106 | material: Cesium.Color.BLACK, 107 | width: 1.5 108 | }) 109 | }); 110 | 111 | entities.add(entity); 112 | } 113 | } 114 | 115 | return entities; 116 | } 117 | 118 | module.exports = asCesium; 119 | -------------------------------------------------------------------------------- /src/graphicslayer/asopenlayers.js: -------------------------------------------------------------------------------- 1 | function asOpenLayers(crs) { 2 | crs = crs || "EPSG:3857"; 3 | //var ua = window.navigator.userAgent; 4 | //var isIE = ( ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0) ? true : false; 5 | var ratio = window.devicePixelRatio || 1; 6 | var geoJSON = new ol.format.GeoJSON(); 7 | var features = []; 8 | 9 | for (var i = 0; i < this.data.features.length; i++) { 10 | var feature = this.data.features[i]; 11 | var olFeature = geoJSON.readFeature(feature, { 12 | featureProjection: ol.proj.get(crs) 13 | }); 14 | 15 | if ( 16 | olFeature.getGeometry() && 17 | olFeature.getGeometry().getType() == "Point" 18 | ) { 19 | var properties = olFeature.getProperties(); 20 | if (properties.sidc.charAt(0) != "X") { 21 | //TODO handle sitaware custom graphics 22 | var milsymbol = this.data.features[i].symbol; 23 | //var image = isIE ? mysymbol.asCanvas() : mysymbol.toDataURL(); 24 | olFeature.setStyle( 25 | new ol.style.Style({ 26 | image: new ol.style.Icon({ 27 | scale: 1 / ratio, 28 | anchor: [ 29 | milsymbol.getAnchor().x * ratio, 30 | milsymbol.getAnchor().y * ratio 31 | ], 32 | anchorXUnits: "pixels", 33 | anchorYUnits: "pixels", 34 | imgSize: [ 35 | Math.floor(milsymbol.getSize().width * ratio), 36 | Math.floor(milsymbol.getSize().height * ratio) 37 | ], 38 | img: milsymbol.asCanvas(ratio) 39 | }) 40 | }) 41 | ); 42 | } 43 | } 44 | 45 | if ( 46 | feature.graphic.isConverted() && 47 | (olFeature.getGeometry().getType() == "LineString" || 48 | olFeature.getGeometry().getType() == "MultiLineString") 49 | ) { 50 | var styles = [ 51 | new ol.style.Style({ 52 | stroke: new ol.style.Stroke({ 53 | lineCap: "butt", 54 | color: "#000000", 55 | width: 2 56 | }) 57 | }) 58 | ]; 59 | if (feature.graphic.annotations) { 60 | var labelgeom = geoJSON 61 | .readFeature(feature.graphic.annotations[0].geometry, { 62 | featureProjection: ol.proj.get(crs) 63 | }) 64 | .getGeometry(); 65 | styles.push( 66 | new ol.style.Style({ 67 | text: new ol.style.Text({ 68 | fill: new ol.style.Fill({ color: "black" }), 69 | font: "bold 16px sans-serif", 70 | stroke: new ol.style.Stroke({ 71 | color: "rgb(239, 239, 239)", // off-white 72 | width: 4 73 | }), 74 | text: feature.graphic.annotations[0].properties.text 75 | }), 76 | geometry: labelgeom 77 | }) 78 | ); 79 | } 80 | olFeature.setStyle(styles); 81 | } 82 | 83 | if ( 84 | feature.graphic.isConverted() && 85 | olFeature.getGeometry().getType() == "Polygon" 86 | ) { 87 | style = new ol.style.Style({ 88 | stroke: new ol.style.Stroke({ 89 | lineCap: "butt", 90 | color: "#000000", 91 | width: 2 92 | }), 93 | fill: new ol.style.Fill({ color: "rgba(0,0,0,0)" }), 94 | text: new ol.style.Text({ 95 | fill: new ol.style.Fill({ color: "black" }), 96 | font: "bold 16px sans-serif", 97 | stroke: new ol.style.Stroke({ 98 | color: "rgb(239, 239, 239)", // off-white 99 | width: 4 100 | }), 101 | text: feature.graphic.annotations 102 | ? feature.graphic.annotations[0].properties.text 103 | : "" 104 | }) 105 | }); 106 | olFeature.setStyle(style); 107 | } 108 | 109 | features.push(olFeature); 110 | } 111 | 112 | return features; 113 | } 114 | 115 | module.exports = asOpenLayers; 116 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* *************************************************************************************** 2 | Creating the base of milgraphics by importing milsymbol 3 | *************************************************************************************** */ 4 | var ms = require("milsymbol"); 5 | 6 | ms.addSIDCgraphics = require("./ms/addsidcgraphics.js"); 7 | 8 | ms.format = require("./format.js"); 9 | ms.geometry = require("./geometry.js"); 10 | ms.geometryConverter = require("./geometryconverter.js"); 11 | 12 | ms.Graphic = require("./graphic.js"); 13 | 14 | ms.GraphicsLayer = require("./graphicslayer.js"); 15 | 16 | /* *************************************************************************************** 17 | Letter based SIDC 18 | *************************************************************************************** */ 19 | ms._getLetterPropertiesGraphic = require("./letter-sidc/properties.js"); 20 | 21 | ms._getLetterSIDCgraphic = require("./letter-sidc/getgraphic.js"); 22 | ms.addSIDCgraphics(require("./letter-sidc/tactical-2525.js"), "letter"); 23 | ms.addSIDCgraphics(require("./letter-sidc/tactical-app6.js"), "letter"); 24 | /* *************************************************************************************** 25 | Number based SIDC 26 | *************************************************************************************** */ 27 | ms._getNumberPropertiesGraphic = require("./number-sidc/properties.js"); 28 | 29 | /* *************************************************************************************** 30 | Export ms to the world 31 | *************************************************************************************** */ 32 | module.exports = ms; 33 | -------------------------------------------------------------------------------- /src/letter-sidc/getgraphic.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | module.exports = function(sidc, STD2525) { 4 | // We modify sidc directly in the called functions so we don't need to return anything. 5 | // Might change this later since it adds complexity to understand the code. 6 | for (var i in ms._letterSIDCgraphics) { 7 | if (!ms._letterSIDCgraphics.hasOwnProperty(i)) continue; 8 | ms._letterSIDCgraphics[i].call(this, sidc, STD2525); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/letter-sidc/properties.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | module.exports = function(properties, mapping) { 4 | this.SIDC = this.SIDC.toUpperCase(); 5 | 6 | var codingscheme = this.SIDC.charAt(0) != "" ? this.SIDC.charAt(0) : "-"; 7 | var affiliation = this.SIDC.charAt(1) != "" ? this.SIDC.charAt(1) : "-"; 8 | var battledimension = this.SIDC.charAt(2) != "" ? this.SIDC.charAt(2) : "-"; 9 | var status = this.SIDC.charAt(3) != "" ? this.SIDC.charAt(3) : "-"; 10 | var functionid = (properties.functionid = this.SIDC.substr(4, 6) != "" 11 | ? this.SIDC.substr(4, 6) 12 | : "------"); 13 | var symbolmodifier11 = this.SIDC.charAt(10) != "" 14 | ? this.SIDC.charAt(10) 15 | : "-"; 16 | var symbolmodifier12 = this.SIDC.charAt(11) != "" 17 | ? this.SIDC.charAt(11) 18 | : "-"; 19 | var countrycode = this.SIDC.substr(12, 2) != "" 20 | ? this.SIDC.substr(12, 2) 21 | : "--"; 22 | var orderofbattle = this.SIDC.charAt(14) != "" ? this.SIDC.charAt(14) : "-"; 23 | 24 | if (["H", "S", "J", "K"].indexOf(affiliation) > -1) 25 | properties.affiliation = mapping.affiliation[0]; 26 | if (["F", "A", "D", "M"].indexOf(affiliation) > -1) 27 | properties.affiliation = mapping.affiliation[1]; 28 | if (["N", "L"].indexOf(affiliation) > -1) 29 | properties.affiliation = mapping.affiliation[2]; 30 | if (["P", "U", "G", "W", "O"].indexOf(affiliation) > -1) 31 | properties.affiliation = mapping.affiliation[3]; 32 | 33 | if (["P", "A"].indexOf(battledimension) > -1) 34 | properties.dimension = mapping.dimension[0]; 35 | if (["G", "Z", "F", "X"].indexOf(battledimension) > -1) 36 | properties.dimension = mapping.dimension[1]; 37 | if (["S"].indexOf(battledimension) > -1) 38 | properties.dimension = mapping.dimension[2]; 39 | if (["U"].indexOf(battledimension) > -1) 40 | properties.dimension = mapping.dimension[3]; 41 | 42 | //Planned/Anticipated/Suspect symbols should have a dashed outline 43 | if (status == "A") { 44 | properties.notpresent = ms._dashArrays.anticipated; 45 | } 46 | if (["P", "A", "S", "G", "M"].indexOf(affiliation) > -1) { 47 | properties.notpresent = ms._dashArrays.pending; 48 | } 49 | 50 | if (orderofbattle == "X") { 51 | properties.graphic = true; 52 | } 53 | 54 | // Army XML compability 55 | //sidc['CIRCLE----'] = ms.geometryConverter.circle; 56 | 57 | // Systematic SitaWare compatibility 58 | var genericSIDC = 59 | this.SIDC.substr(0, 1) + 60 | "-" + 61 | this.SIDC.substr(2, 1) + 62 | "-" + 63 | this.SIDC.substr(4, 6); 64 | if (["X---C-----", "X---I-----", "X---A-----"].indexOf(genericSIDC) != -1) { 65 | properties.graphic = true; 66 | } 67 | 68 | return properties; 69 | }; 70 | -------------------------------------------------------------------------------- /src/letter-sidc/tactical-app6.js: -------------------------------------------------------------------------------- 1 | // Tactical graphics in APP6-B 2 | module.exportS = function tacticalPoints(sidc, std2525) { 3 | //sidc['G---------'] = [];//2.X 4 | //sidc['G-T-------'] = [];//2.X.1 5 | //sidc['G-T-G-----'] = [];//2.X.1.1 6 | sidc["G-T-GB----"] = ms.geometryConverter["BLOCK"]; //2.X.1.1.1 7 | sidc["G-T-GH----"] = ms.geometryConverter["BYPASS"]; //2.X.1.1.2 8 | sidc["G-T-GY----"] = ms.geometryConverter["BYPASS"]; //2.X.1.1.3 9 | sidc["G-T-GC----"] = ms.geometryConverter["CANALIZE"]; //2.X.1.1.4 10 | sidc["G-T-GX----"] = ms.geometryConverter["CLEAR"]; //2.X.1.1.5 11 | //sidc['G-T-GJ----'] = [];//2.X.1.1.6 12 | //sidc['G-T-GK----'] = [];//2.X.1.1.7 13 | //sidc['G-T-GKF---'] = [];//2.X.1.1.7.1 14 | sidc["G-T-GL----"] = ms.geometryConverter["DELAY"]; //2.X.1.1.8 15 | //sidc['G-T-GLT---'] = [];//2.X.1.1.8.1 16 | //sidc['G-T-GT----'] = [];//2.X.1.1.10 17 | sidc["G-T-GF----"] = ms.geometryConverter["FIX"]; //2.X.1.1.11 18 | //sidc['G-T-GA----'] = [];//2.X.1.1.12 19 | //sidc['G-T-GAS---'] = [];//2.X.1.1.12.1 20 | sidc["G-T-GE----"] = ms.geometryConverter["ISOLATE"]; //2.X.1.1.14 21 | //sidc['G-T-GO----'] = [];//2.X.1.1.16 22 | //sidc['G-T-GP----'] = [];//2.X.1.1.17 23 | //sidc['G-T-GR----'] = [];//2.X.1.1.18 24 | //sidc['G-T-GQ----'] = [];//2.X.1.1.19 25 | //sidc['G-T-GM----'] = [];//2.X.1.1.20 26 | //sidc['G-T-GS----'] = [];//2.X.1.1.21 27 | //sidc['G-T-GSS---'] = [];//2.X.1.1.21.1 28 | //sidc['G-T-GSG---'] = [];//2.X.1.1.21.2 29 | //sidc['G-T-GSC---'] = [];//2.X.1.1.21.3 30 | //sidc['G-T-GZ----'] = [];//2.X.1.1.22 31 | //sidc['G-T-GW----'] = [];//2.X.1.1.23 32 | //sidc['G-T-GWP---'] = [];//2.X.1.1.23.1 33 | //sidc['G-C-------'] = [];//2.X.2 34 | //sidc['G-C-M-----'] = [];//2.X.2.1 35 | //sidc['G-C-MG----'] = [];//2.X.2.1.1 36 | //sidc['G-C-MGP---'] = [];//2.X.2.1.1.1 37 | //sidc['G-C-MGPF--'] = [];//2.X.2.1.1.1.1 38 | //sidc['G-C-MGL---'] = [];//2.X.2.1.1.2 39 | //sidc['G-C-MGLB--'] = [];//2.X.2.1.1.2.1 40 | //sidc['G-C-MGLBG-'] = [];//2.X.2.1.1.2.1.1 41 | //sidc['G-C-MGLBGF'] = [];//2.X.2.1.1.2.1.1.1 42 | //sidc['G-C-MGLBGO'] = [];//2.X.2.1.1.2.1.1.2 43 | //sidc['G-C-MGLBGK'] = [];//2.X.2.1.1.2.1.1.3 44 | //sidc['G-C-MGLBGS'] = [];//2.X.2.1.1.2.1.1.4 45 | //sidc['G-C-MGLBL-'] = [];//2.X.2.1.1.2.1.2 46 | //sidc['G-C-MGLBF-'] = [];//2.X.2.1.1.2.1.3 47 | //sidc['G-C-MGLBR-'] = [];//2.X.2.1.1.2.1.4 48 | //sidc['G-C-MGLF--'] = [];//2.X.2.1.1.2.2 49 | //sidc['G-C-MGLL--'] = [];//2.X.2.1.1.2.3 50 | //sidc['G-C-MGLP--'] = [];//2.X.2.1.1.2.4 51 | //sidc['G-C-MGLE--'] = [];//2.X.2.1.1.2.5 52 | //sidc['G-C-MGLEE-'] = [];//2.X.2.1.1.2.5.1 53 | //sidc['G-C-MGLEA-'] = [];//2.X.2.1.1.2.5.2 54 | //sidc['G-C-MGLET-'] = [];//2.X.2.1.1.2.5.3 55 | //sidc['G-C-MGLEO-'] = [];//2.X.2.1.1.2.5.4 56 | //sidc['G-C-MGA---'] = [];//2.X.2.1.1.3 57 | //sidc['G-C-MGAU--'] = [];//2.X.2.1.1.3.1 58 | //sidc['G-C-MGAUA-'] = [];//2.X.2.1.1.3.1.1 59 | //sidc['G-C-MGAUAF'] = [];//2.X.2.1.1.3.1.1.1 60 | //sidc['G-C-MGAUAP'] = [];//2.X.2.1.1.3.1.1.2 61 | //sidc['G-C-MGAUAE'] = [];//2.X.2.1.1.3.1.1.3 62 | //sidc['G-C-MGAUAS'] = [];//2.X.2.1.1.3.1.1.4 63 | //sidc['G-C-MGAUB-'] = [];//2.X.2.1.1.3.1.2 64 | //sidc['G-C-MGAUBO'] = [];//2.X.2.1.1.3.1.2.1 65 | //sidc['G-C-MGAUBM'] = [];//2.X.2.1.1.3.1.2.2 66 | //sidc['G-C-MGAUBR'] = [];//2.X.2.1.1.3.1.2.3 67 | //sidc['G-C-MGAS--'] = [];//2.X.2.1.1.3.2 68 | //sidc['G-C-MGASD-'] = [];//2.X.2.1.1.3.2.1 69 | //sidc['G-C-MGASE-'] = [];//2.X.2.1.1.3.2.2 70 | //sidc['G-C-MGASL-'] = [];//2.X.2.1.1.3.2.3 71 | //sidc['G-C-MGASP-'] = [];//2.X.2.1.1.3.2.4 72 | //sidc['G-C-MGASS-'] = [];//2.X.2.1.1.3.2.5 73 | //sidc['G-C-MGASM-'] = [];//2.X.2.1.1.3.2.6 74 | //sidc['G-C-MGASG-'] = [];//2.X.2.1.1.3.2.7 75 | //sidc['G-C-MGASF-'] = [];//2.X.2.1.1.3.2.8 76 | //sidc['G-C-MGAST-'] = [];//2.X.2.1.1.3.2.9 77 | //sidc['G-C-MA----'] = [];//2.X.2.1.2 78 | //sidc['G-C-MAA---'] = [];//2.X.2.1.2.1 79 | //sidc['G-C-MAL---'] = [];//2.X.2.1.2.2 80 | //sidc['G-C-MALC--'] = [];//2.X.2.1.2.2.1 81 | //sidc['G-C-MALM--'] = [];//2.X.2.1.2.2.2 82 | //sidc['G-C-MALS--'] = [];//2.X.2.1.2.2.3 83 | //sidc['G-C-MALU--'] = [];//2.X.2.1.2.2.4 84 | //sidc['G-C-MALL--'] = [];//2.X.2.1.2.2.5 85 | //sidc['G-C-MALIN-'] = [];//2.X.2.1.2.2.6 86 | //sidc['G-C-MALIF-'] = [];//2.X.2.1.2.2.7 87 | //sidc['G-C-MAV---'] = [];//2.X.2.1.2.3 88 | //sidc['G-C-MAVR--'] = [];//2.X.2.1.2.3.1 89 | //sidc['G-C-MAVF--'] = [];//2.X.2.1.2.3.2 90 | //sidc['G-C-MAVH--'] = [];//2.X.2.1.2.3.3 91 | //sidc['G-C-MAVM--'] = [];//2.X.2.1.2.3.4 92 | //sidc['G-C-MAVML-'] = [];//2.X.2.1.2.3.4.1 93 | //sidc['G-C-MAVMH-'] = [];//2.X.2.1.2.3.4.2 94 | //sidc['G-C-MAVW--'] = [];//2.X.2.1.2.3.5 95 | //sidc['G-C-MD----'] = [];//2.X.2.1.3 96 | //sidc['G-C-MDD---'] = [];//2.X.2.1.3.1 97 | //sidc['G-C-MDA---'] = [];//2.X.2.1.3.2 98 | //sidc['G-C-MDF---'] = [];//2.X.2.1.3.3 99 | //sidc['G-C-MDM---'] = [];//2.X.2.1.3.4 100 | //sidc['G-C-MDY---'] = [];//2.X.2.1.3.5 101 | //sidc['G-C-MM----'] = [];//2.X.2.1.4 102 | //sidc['G-C-MMP---'] = [];//2.X.2.1.4.1 103 | //sidc['G-C-MMPB--'] = [];//2.X.2.1.4.1.2 104 | //sidc['G-C-MMPBO-'] = [];//2.X.2.1.4.1.2.1 105 | //sidc['G-C-MMPBP-'] = [];//2.X.2.1.4.1.2.2 106 | //sidc['G-C-MMPBL-'] = [];//2.X.2.1.4.1.2.3 107 | //sidc['G-C-*'] = [];//2.X.2.1.4.1.3 108 | //sidc['G-C-MMPSF-'] = [];//2.X.2.1.4.1.3.1 109 | //sidc['G-C-MMPSE-'] = [];//2.X.2.1.4.1.3.2 110 | //sidc['G-C-MMD---'] = [];//2.X.2.1.4.2 111 | //sidc['G-C-MMDF--'] = [];//2.X.2.1.4.2.1 112 | //sidc['G-C-MMDFA-'] = [];//2.X.2.1.4.2.1.1 113 | //sidc['G-C-MMDFP-'] = [];//2.X.2.1.4.2.1.2 114 | //sidc['G-C-MMDP--'] = [];//2.X.2.1.4.2.2 115 | //sidc['G-C-MMA---'] = [];//2.X.2.1.4.3 116 | //sidc['G-C-MMAE--'] = [];//2.X.2.1.4.3.1 117 | //sidc['G-C-MO----'] = [];//2.X.2.1.5 118 | //sidc['G-C-MOP---'] = [];//2.X.2.1.5.1 119 | //sidc['G-C-MOL---'] = [];//2.X.2.1.5.2 120 | //sidc['G-C-MOLA--'] = [];//2.X.2.1.5.2.1 121 | //sidc['G-C-MOLAF-'] = [];//2.X.2.1.5.2.1.1 122 | //sidc['G-C-MOLAA-'] = [];//2.X.2.1.5.2.1.2 123 | //sidc['G-C-MOLAH-'] = [];//2.X.2.1.5.2.1.3 124 | sidc["G-C-MOLAS-"] = ms.geometryConverter["SUPPORTING ATTACK"]; //2.X.2.1.5.2.1.4 125 | sidc["G-C-MOLAM-"] = ms.geometryConverter["MAIN ATTACK"]; //2.X.2.1.5.2.1.5 126 | //sidc['G-C-MOLAO-'] = [];//2.X.2.1.5.2.1.6 127 | //sidc['G-C-MOLAE-'] = [];//2.X.2.1.5.2.1.7 128 | //sidc['G-C-MOLAT-'] = [];//2.X.2.1.5.2.1.8 129 | //sidc['G-C-MOLD--'] = [];//2.X.2.1.5.2.2 130 | //sidc['G-C-MOLDF-'] = [];//2.X.2.1.5.2.2.1 131 | //sidc['G-C-MOLDY-'] = [];//2.X.2.1.5.2.2.2 132 | //sidc['G-C-MOLDE-'] = [];//2.X.2.1.5.2.2.3 133 | //sidc['G-C-MOLDT-'] = [];//2.X.2.1.5.2.2.4 134 | //sidc['G-C-MOLDG-'] = [];//2.X.2.1.5.2.2.5 135 | //sidc['G-C-MOLDR-'] = [];//2.X.2.1.5.2.2.6 136 | //sidc['G-C-MOLDS-'] = [];//2.X.2.1.5.2.2.7 137 | //sidc['G-C-MOLDM-'] = [];//2.X.2.1.5.2.2.8 138 | //sidc['G-C-MOLDO-'] = [];//2.X.2.1.5.2.2.9 139 | //sidc['G-C-MOLF--'] = [];//2.X.2.1.5.2.3 140 | //sidc['G-C-MOLI--'] = [];//2.X.2.1.5.2.4 141 | //sidc['G-C-MOLL--'] = [];//2.X.2.1.5.2.5 142 | //sidc['G-C-MOLT--'] = [];//2.X.2.1.5.2.6 143 | //sidc['G-C-MOLC--'] = [];//2.X.2.1.5.2.7 144 | //sidc['G-C-MOLP--'] = [];//2.X.2.1.5.2.8 145 | //sidc['G-C-MOLR--'] = [];//2.X.2.1.5.2.9 146 | //sidc['G-C-MOO---'] = [];//2.X.2.1.5.3 147 | //sidc['G-C-MOOA--'] = [];//2.X.2.1.5.3.1 148 | //sidc['G-C-MOOT--'] = [];//2.X.2.1.5.3.2 149 | //sidc['G-C-MOOTF-'] = [];//2.X.2.1.5.3.2.1 150 | //sidc['G-C-MOOTC-'] = [];//2.X.2.1.5.3.2.2 151 | //sidc['G-C-MOOTP-'] = [];//2.X.2.1.5.3.2.3 152 | //sidc['G-C-MOOP--'] = [];//2.X.2.1.5.3.3 153 | //sidc['G-C-MOOS--'] = [];//2.X.2.1.5.3.4 154 | //sidc['G-C-MOOJ--'] = [];//2.X.2.1.5.3.5 155 | //sidc['G-C-MOOX--'] = [];//2.X.2.1.5.3.6 156 | //sidc['G-C-MOOR--'] = [];//2.X.2.1.5.3.7 157 | //sidc['G-C-MS----'] = [];//2.X.2.1.6 158 | //sidc['G-C-MSG---'] = [];//2.X.2.1.6.1 159 | //sidc['G-C-MSGE--'] = [];//2.X.2.1.6.1.1 160 | //sidc['G-C-MSGEF-'] = [];//2.X.2.1.6.1.1.1 161 | //sidc['G-C-MSGEY-'] = [];//2.X.2.1.6.1.1.2 162 | sidc["G-C-MSGA--"] = ms.geometryConverter["AMBUSH"]; //2.X.2.1.6.1.2 163 | //sidc['G-C-MSL---'] = [];//2.X.2.1.6.2 164 | //sidc['G-C-MSLA--'] = [];//2.X.2.1.6.2.1 165 | //sidc['G-C-MSLB--'] = [];//2.X.2.1.6.2.2 166 | //sidc['G-C-MSLH--'] = [];//2.X.2.1.6.2.3 167 | //sidc['G-C-MSLR--'] = [];//2.X.2.1.6.2.4 168 | //sidc['G-C-MSA---'] = [];//2.X.2.1.6.3 169 | //sidc['G-C-MSAO--'] = [];//2.X.2.1.6.3.1 170 | sidc["G-C-MSAN--"] = ms.geometryConverter["NAMED AREA OF INTEREST"]; //2.X.2.1.6.3.2 171 | sidc["G-C-MSAT--"] = ms.geometryConverter["TARGETED AREA OF INTEREST"]; //2.X.2.1.6.3.3 172 | //sidc['G-C-B-----'] = [];//2.X.2.2 173 | //sidc['G-C-BO----'] = [];//2.X.2.2.1 174 | //sidc['G-C-BOG---'] = [];//2.X.2.2.1.1 175 | //sidc['G-C-BOGB--'] = [];//2.X.2.2.1.1.1 176 | //sidc['G-C-BOGL--'] = [];//2.X.2.2.1.1.2 177 | //sidc['G-C-BOGZ--'] = [];//2.X.2.2.1.1.3 178 | //sidc['G-C-BOA---'] = [];//2.X.2.2.1.2 179 | //sidc['G-C-BOAT--'] = [];//2.X.2.2.1.3 180 | //sidc['G-C-BOATO-'] = [];//2.X.2.2.1.3.1 181 | //sidc['G-C-BOATM-'] = [];//2.X.2.2.1.3.2 182 | //sidc['G-C-BOATW-'] = [];//2.X.2.2.1.3.4 183 | //sidc['G-C-BOAM--'] = [];//2.X.2.2.1.5 184 | //sidc['G-C-BOAMW-'] = [];//2.X.2.2.1.5.7 185 | //sidc['G-C-BOAI--'] = [];//2.X.2.2.1.6 186 | //sidc['G-C-BOAIL-'] = [];//2.X.2.2.1.6.3 187 | //sidc['G-C-BOAIG-'] = [];//2.X.2.2.1.6.4 188 | //sidc['G-C-BOAIM-'] = [];//2.X.2.2.1.6.9 189 | //sidc['G-C-BOAV--'] = [];//2.X.2.2.1.7 190 | //sidc['G-C-BOAE--'] = [];//2.X.2.2.1.8 191 | //sidc['G-C-BOAEB-'] = [];//2.X.2.2.1.8.1 192 | //sidc['G-C-BOAEF-'] = [];//2.X.2.2.1.8.2 193 | //sidc['G-C-BOAET-'] = [];//2.X.2.2.1.8.3 194 | //sidc['G-C-BOAED-'] = [];//2.X.2.2.1.8.4 195 | //sidc['G-C-BOAF--'] = [];//2.X.2.2.1.9 196 | //sidc['G-C-BOAFR-'] = [];//2.X.2.2.1.9.1 197 | //sidc['G-C-BOAU--'] = [];//2.X.2.2.1.10 198 | //sidc['G-C-BOAR--'] = [];//2.X.2.2.1.11 199 | //sidc['G-C-BOARP-'] = [];//2.X.2.2.1.11.1 200 | //sidc['G-C-BOARE-'] = [];//2.X.2.2.1.11.2 201 | //sidc['G-C-BOARS-'] = [];//2.X.2.2.1.11.3 202 | //sidc['G-C-BOARC-'] = [];//2.X.2.2.1.11.4 203 | //sidc['G-C-BOAP--'] = [];//2.X.2.2.1.12 204 | //sidc['G-C-BOAW--'] = [];//2.X.2.2.1.13 205 | //sidc['G-C-BOAWU-'] = [];//2.X.2.2.1.13.1 206 | //sidc['G-C-BOAWS-'] = [];//2.X.2.2.1.13.2 207 | //sidc['G-C-BOAWD-'] = [];//2.X.2.2.1.13.3 208 | //sidc['G-C-BOAWA-'] = [];//2.X.2.2.1.13.4 209 | //sidc['G-C-BOAWL-'] = [];//2.X.2.2.1.13.5 210 | //sidc['G-C-BOAWH-'] = [];//2.X.2.2.1.13.6 211 | //sidc['G-C-BOAWC-'] = [];//2.X.2.2.1.13.7 212 | //sidc['G-C-BOAWB-'] = [];//2.X.2.2.1.13.8 213 | //sidc['G-C-BOAWR-'] = [];//2.X.2.2.1.13.9 214 | //sidc['G-C-BY----'] = [];//2.X.2.2.2 215 | //sidc['G-C-BYO---'] = [];//2.X.2.2.2.1 216 | //sidc['G-C-BYOE--'] = [];//2.X.2.2.2.1.1 217 | //sidc['G-C-BYOD--'] = [];//2.X.2.2.2.1.2 218 | //sidc['G-C-BYOI--'] = [];//2.X.2.2.2.1.3 219 | //sidc['G-C-BYC---'] = [];//2.X.2.2.2.2 220 | //sidc['G-C-BYCA--'] = [];//2.X.2.2.2.2.1 221 | //sidc['G-C-BYCB--'] = [];//2.X.2.2.2.2.2 222 | //sidc['G-C-BYCF--'] = [];//2.X.2.2.2.2.3 223 | //sidc['G-C-BYCE--'] = [];//2.X.2.2.2.2.4 224 | //sidc['G-C-BYCD--'] = [];//2.X.2.2.2.2.5 225 | //sidc['G-C-BYCL--'] = [];//2.X.2.2.2.2.6 226 | //sidc['G-C-BYCR--'] = [];//2.X.2.2.2.2.7 227 | //sidc['G-C-BS----'] = [];//2.X.2.2.3 228 | //sidc['G-C-BSL---'] = [];//2.X.2.2.3.3 229 | //sidc['G-C-BSW---'] = [];//2.X.2.2.3.4 230 | //sidc['G-C-BSP---'] = [];//2.X.2.2.3.5 231 | //sidc['G-C-BW----'] = [];//2.X.2.2.4 232 | //sidc['G-C-BWM---'] = [];//2.X.2.2.4.1 233 | //sidc['G-C-BWA---'] = [];//2.X.2.2.4.7 234 | //sidc['G-C-BWC---'] = [];//2.X.2.2.4.8 235 | //sidc['G-C-BWH---'] = [];//2.X.2.2.4.9 236 | //sidc['G-C-BWK---'] = [];//2.X.2.2.4.10 237 | //sidc['G-C-BWD---'] = [];//2.X.2.2.4.11 238 | //sidc['G-C-BWR---'] = [];//2.X.2.2.4.12 239 | //sidc['G-C-F-----'] = [];//2.X.2.3 240 | //sidc['G-C-FS----'] = [];//2.X.2.3.1 241 | //sidc['G-C-FST---'] = [];//2.X.2.3.1.1 242 | //sidc['G-C-FSTC--'] = [];//2.X.2.3.1.1.2 243 | //sidc['G-C-FL----'] = [];//2.X.2.3.2 244 | //sidc['G-C-FLC---'] = [];//2.X.2.3.2.1 245 | //sidc['G-C-FLF---'] = [];//2.X.2.3.2.2 246 | //sidc['G-C-FLT---'] = [];//2.X.2.3.2.3 247 | //sidc['G-C-FLTP--'] = [];//2.X.2.3.2.3.1 248 | //sidc['G-C-FLK---'] = [];//2.X.2.3.2.4 249 | //sidc['G-C-FLKP--'] = [];//2.X.2.3.2.4.1 250 | //sidc['G-C-FLKS--'] = [];//2.X.2.3.2.4.2 251 | //sidc['G-C-FLKT--'] = [];//2.X.2.3.2.4.3 252 | //sidc['G-C-FLN---'] = [];//2.X.2.3.2.5 253 | //sidc['G-C-FLR---'] = [];//2.X.2.3.2.6 254 | //sidc['G-C-FA----'] = [];//2.X.2.3.3 255 | sidc["G-C-FAS---"] = ms.geometryConverter["FIRE SUPPORT AREA"]; //2.X.2.3.3.1 256 | sidc["G-C-FAC---"] = ms.geometryConverter["AIRSPACE COORDINATION AREA"]; //2.X.2.3.3.2 257 | //sidc['G-C-FAT---'] = [];//2.X.2.3.3.3 258 | //sidc['G-C-FAR---'] = [];//2.X.2.3.3.4 259 | //sidc['G-C-FARS--'] = [];//2.X.2.3.3.4.1 260 | //sidc['G-C-FARU--'] = [];//2.X.2.3.3.4.2 261 | //sidc['G-C-FAB---'] = [];//2.X.2.3.3.5 262 | sidc["G-C-FAI---"] = ms.geometryConverter["FREE FIRE AREA"]; //2.X.2.3.3.6 263 | //sidc['G-C-FAZ---'] = [];//2.X.2.3.3.7 264 | //sidc['G-C-FAZT--'] = [];//2.X.2.3.3.7.1 265 | //sidc['G-C-FAZU--'] = [];//2.X.2.3.3.7.2 266 | //sidc['G-C-FAN---'] = [];//2.X.2.3.3.8 267 | //sidc['G-C-FAD---'] = [];//2.X.2.3.3.10 268 | //sidc['G-C-FAP---'] = [];//2.X.2.3.3.11 269 | //sidc['G-C-FATA--'] = [];//2.X.2.3.3.12 270 | //sidc['*-*-*'] = [];//G 271 | //sidc['G-C-SP----'] = [];//2.X.2.4.1 272 | //sidc['G-C-SPQ---'] = [];//2.X.2.4.1.14 273 | //sidc['G-C-SPM---'] = [];//2.X.2.4.1.15 274 | //sidc['G-C-SL----'] = [];//2.X.2.4.2 275 | //sidc['G-C-SLC---'] = [];//2.X.2.4.2.1 276 | //sidc['G-C-SLCM--'] = [];//2.X.2.4.2.1.1 277 | //sidc['G-C-SLCH--'] = [];//2.X.2.4.2.1.2 278 | //sidc['G-C-SLR---'] = [];//2.X.2.4.2.2 279 | //sidc['G-C-SLRM--'] = [];//2.X.2.4.2.2.1 280 | //sidc['G-C-SLRA--'] = [];//2.X.2.4.2.2.2 281 | //sidc['G-C-SLRO--'] = [];//2.X.2.4.2.2.3 282 | //sidc['G-C-SLRT--'] = [];//2.X.2.4.2.2.4 283 | //sidc['G-C-SLRW--'] = [];//2.X.2.4.2.2.5 284 | //sidc['G-C-SA----'] = [];//2.X.2.4.3 285 | //sidc['G-C-SAD---'] = [];//2.X.2.4.3.1 286 | //sidc['G-C-SAP---'] = [];//2.X.2.4.3.2 287 | //sidc['G-C-SAR---'] = [];//2.X.2.4.3.3 288 | //sidc['G-C-SAH---'] = [];//2.X.2.4.3.4 289 | //sidc['G-C-SAT---'] = [];//2.X.2.4.3.5 290 | //sidc['G-C-SATB--'] = [];//2.X.2.4.3.5.1 291 | //sidc['G-C-SATD--'] = [];//2.X.2.4.3.5.2 292 | //sidc['G-C-SATR--'] = [];//2.X.2.4.3.5.3 293 | //sidc['G-C-SARR--'] = [];//2.X.2.4.3.6 294 | //sidc['G-C-O-----'] = [];//2.X.2.5 295 | //sidc['G-C-OXE---'] = [];//2.X.2.5.1.1 296 | //sidc['G-C-OXU---'] = [];//2.X.2.5.1.2 297 | //sidc['G-C-OXW---'] = [];//2.X.2.5.1.3 298 | //sidc['G-C-OXST--'] = [];//2.X.2.5.1.8 299 | //sidc['G-C-OXA---'] = [];//2.X.2.5.1.10 300 | //sidc['G-C-OL----'] = [];//2.X.2.5.3 301 | //sidc['*-*-*'] = [];//G 302 | //sidc['*-*-*'] = [];//G 303 | //sidc['*-*-*'] = [];//G 304 | //sidc['*-*-*'] = [];//G 305 | //sidc['G-O-------'] = [];//2.X.3 306 | //sidc['G-O-V-----'] = [];//2.X.3.1 307 | //sidc['G-O-L-----'] = [];//2.X.3.2 308 | //sidc['G-O-P-----'] = [];//2.X.3.3 309 | //sidc['G-O-PJ----'] = [];//2.X.3.3.13 310 | //sidc['G-O-I-----'] = [];//2.X.3.4 311 | }; 312 | -------------------------------------------------------------------------------- /src/ms/addsidcgraphics.js: -------------------------------------------------------------------------------- 1 | var addSIDCgraphics = function(parts, type) { 2 | if (typeof parts === "function") { 3 | if (typeof this["_" + type + "SIDCgraphics"] === "undefined") { 4 | this["_" + type + "SIDCgraphics"] = []; 5 | } 6 | this["_" + type + "SIDCgraphics"] = this[ 7 | "_" + type + "SIDCgraphics" 8 | ].concat(parts); 9 | } 10 | return this; 11 | }; 12 | 13 | module.exports = addSIDCgraphics; 14 | -------------------------------------------------------------------------------- /src/number-sidc/properties.js: -------------------------------------------------------------------------------- 1 | var ms = require("milsymbol"); 2 | 3 | module.exports = function(properties, mapping) { 4 | var version = this.SIDC.substr(0, 2); 5 | var standardIdentity1 = this.SIDC.substr(2, 1); 6 | var standardIdentity2 = this.SIDC.substr(3, 1); 7 | var symbolSet = this.SIDC.substr(4, 2); 8 | var status = this.SIDC.substr(6, 1); 9 | var headquartersTaskForceDummy = this.SIDC.substr(7, 1); 10 | var echelonMobility = this.SIDC.substr(8, 2); 11 | 12 | var affiliationMapping = { 13 | "0": "Unknown", 14 | "1": "Unknown", 15 | "2": "Friend", 16 | "3": "Friend", 17 | "4": "Neutral", 18 | "5": "Hostile", 19 | "6": "Hostile" 20 | }; 21 | 22 | var dimensionMapping = { 23 | "00": "Sea", 24 | "01": "Air", 25 | "02": "Air", 26 | "05": "Air", 27 | "06": "Air", 28 | "10": "Ground", 29 | "11": "Ground", 30 | "12": "Ground", 31 | "15": "Ground", 32 | "20": "Ground", 33 | "30": "Sea", 34 | "35": "Subsurface", 35 | "36": "Subsurface", 36 | "39": "Subsurface", 37 | "40": "Ground", 38 | "50": "Air", 39 | "51": "Air", 40 | "52": "Ground", 41 | "53": "Sea", 42 | "54": "Subsurface", 43 | "60": "Ground" 44 | }; 45 | 46 | var functionid = (properties.functionid = this.SIDC.substr(10, 10)); 47 | 48 | properties.context = mapping.context[parseInt(this.SIDC.substr(2, 1))]; 49 | properties.affiliation = affiliationMapping[standardIdentity2]; 50 | properties.dimension = dimensionMapping[symbolSet]; 51 | 52 | //Planned/Anticipated/Suspect symbols should have a dashed outline 53 | if (status == "1") properties.notpresent = ms._dashArrays.anticipated; 54 | if ( 55 | standardIdentity2 == "0" || 56 | standardIdentity2 == "2" || 57 | standardIdentity2 == "5" 58 | ) 59 | properties.notpresent = ms._dashArrays.pending; 60 | 61 | if (echelonMobility >= 70 && echelonMobility < 80) { 62 | properties.leadership = mapping.echelonMobility[echelonMobility]; 63 | } 64 | 65 | return properties; 66 | }; 67 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | var CustomVarLibraryNamePlugin = require("webpack-custom-var-library-name-plugin"); 3 | 4 | module.exports = { 5 | entry: "./src/index.js", 6 | output: { 7 | filename: "milgraphics.js", 8 | path: path.resolve(__dirname, "dist"), 9 | library: "milgraphics", 10 | libraryTarget: "umd", 11 | umdNamedDefine: true 12 | }, 13 | plugins: [ 14 | new CustomVarLibraryNamePlugin({ 15 | name: "ms" 16 | }) 17 | ] 18 | }; 19 | --------------------------------------------------------------------------------