WaBis

walter.bislins.ch

Datei: EarthMap: EarthMap.js

Inhalt der Datei: ./javascript/EarthMap/src/EarthMap.js
///////////////////////////////////////////////////////////////////////////
// Requires Moduls:
// * JsGraph (JsGraph.inc) for FlatEarth or
// * JsGraphX3D (JsGraphX3D.inc) for Globe Earth

var EarthMap =
{
  Type: 'EarthMap',
  Radius: 1,
  FEMode: 0,  // 0 -> use Polygon, 1 -> SplineCurve, 2 -> PolygonOnPlane, 3 -> SplineCurveOnPlane
  SplineTension: 0.5,
  WaterColor: '#a6c4ea',
  WaterBorderColor: '#729cd2',
  WaterBorderWidth: 1,
  WaterDrawMode: 3,
  LandColor: '#8cbe5d', // '#72a653',
  LandBorderColor: '#689a54',
  LandBorderWidth: 1,
  LandDrawMode: 3, // fill and border
  LakeColor: '#a6c4ea',
  LakeBorderColor: '#72a653',
  LakeBorderWidth: 1,
  LakeDrawMode: 3,
  Trans: null,     // JsgMat3
  ClipPlane: null,
  NContourPoints: 96,  // globe contour resolution
  ContinentList:
  [
    {
      Type: 'Continent',
      Name: 'America',
      Color: null,
      BorderColor: null,
      BorderWidth: null,
      DrawMode: null,
      LandList:
      [
        {
          Type: 'Land',
          Name: 'NorthAmerica',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 12, 14, 22, 15, 21, 25, 26, 29, 32, 40, 44, 49, 49, 53, 51, 56, 56, 60, 63, 64, 66, 70, 71, 65, 67, 70, 75, 74, 83, 86, 88, 92, 95, 99, 100, 97, 96, 97, 95, 91, 93, 93, 90, 89, 85, 82, 83, 86, 89, 91, 91, 97, 99, 100, 99, 99, 105, 104, 106, 110, 109, 114, 114, 120, 120, 117, 115, 116, 113, 113, 120, 121, 127, 127, 124, 124, 115, 113, 110, 107, 102, 102, 104, 101, 101, 98, 98, 88, 85, 90, 93, 97, 100, 96, 99, 98, 100, 104, 106, 108, 102, 102, 106, 110, 115, 116, 113, 113, 117, 119, 111, 99, 106, 118, 103, 86, 80, 68, 57, 52, 42, 24, 14 ],
          PolyY: [ 24, 30, 32, 36, 34, 32, 34, 31, 30, 30, 33, 38, 36, 39, 39, 42, 50, 56, 57, 60, 63, 67, 67, 59, 59, 63, 68, 70, 74, 74, 76, 77, 80, 83, 82, 80, 78, 75, 74, 74, 69, 68, 69, 71, 72, 68, 62, 60, 61, 61, 60, 60, 65, 64, 60, 58, 55, 53, 50, 49, 47, 45, 47, 44, 43, 44, 43, 41, 41, 40, 40, 42, 43, 41, 38, 37, 30, 32, 29, 28, 28, 31, 34, 35, 38, 37, 35, 33, 30, 26, 26, 28, 26, 25, 23, 22, 21, 23, 22, 23, 25, 26, 26, 28, 29, 26, 25, 24, 25, 24, 19, 16, 11, 8, 7, 9, 11, 11, 14, 20, 21, 19, 21 ],
          ClosePath: true,
          LakeList:
          [
            {
              Type: 'Lake',
              PolyX: [ 88, 92, 94, 96, 93, 92 ],
              PolyY: [ 43, 41, 41, 43, 44, 43 ],
              ClosePath: true,
            },
            {
              Type: 'Lake',
              PolyX: [ 92, 92, 93, 99, 100, 98, 97, 97, 95, 94, 94, 93 ],
              PolyY: [ 48, 46, 44, 44, 45, 47, 46, 45, 44, 45, 48, 49 ],
              ClosePath: true,
            },
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Greenland',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 107, 112, 120, 123, 125, 126, 126, 129, 132, 135, 137, 138, 140, 144, 148, 155, 158, 158, 160, 162, 161, 163, 167, 167, 162, 161, 157, 157, 145, 127, 119, 118, 115, 112, 115, 114, 110 ],
          PolyY: [ 12, 14, 14, 16, 20, 22, 24, 27, 29, 30, 30, 27, 25, 24, 22, 21, 20, 17, 16, 14, 11, 9, 9, 8, 8, 9, 9, 7, 6, 8, 8, 9, 9, 10, 10, 11, 11 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Cuba',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 95, 99, 103, 106, 100, 97 ],
          PolyY: [ 68, 68, 70, 70, 67, 67 ],
          ClosePath: true,
          LakeList: [],
        }, // end Land
        {
          Type: 'Land',
          Name: 'DominicanRepublic',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 106, 111, 112, 109, 107, 107 ],
          PolyY: [ 72, 72, 71, 70, 70, 71 ],
          ClosePath: true,
          LakeList: [],
        }, // end Land
        {
          Type: 'Land',
          Name: 'SouthAmerica',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 100, 102, 103, 99, 99, 101, 104, 110, 109, 108, 106, 105, 105, 106, 109, 112, 115, 113, 111, 114, 114, 113, 115, 115, 118, 118, 122, 123, 123, 124, 125, 128, 132, 132, 135, 138, 140, 141, 141, 145, 145, 144, 143, 140, 136, 132, 131, 129, 125, 123, 119, 116, 112, 110, 108, 105, 103, 102, 100, 99 ],
          PolyY: [ 81, 82, 85, 91, 96, 98, 105, 108, 118, 125, 129, 136, 140, 143, 145, 146, 145, 144, 141, 138, 137, 136, 134, 131, 131, 129, 128, 127, 126, 125, 125, 123, 117, 115, 113, 113, 109, 106, 103, 99, 96, 95, 95, 93, 92, 90, 87, 85, 84, 84, 80, 79, 79, 78, 78, 79, 82, 81, 80, 81 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Falkland',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 119, 122, 122, 120 ],
          PolyY: [ 142, 142, 141, 141 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
      ], // end LandList
    }, // end Continent
    {
      Type: 'Continent',
      Name: 'Africa',
      Color: null,
      BorderColor: null,
      BorderWidth: null,
      DrawMode: null,
      LandList:
      [
        {
          Type: 'Land',
          Name: 'Africa',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 163, 172, 175, 179, 182, 185, 186, 189, 190, 189, 192, 192, 193, 193, 194, 194, 192, 192, 194, 195, 195, 198, 198, 200, 202, 207, 210, 213, 213, 216, 215, 217, 219, 221, 221, 219, 219, 224, 227, 231, 231, 224, 223, 219, 219, 217, 217, 216, 214, 212, 212, 210, 209, 203, 201, 200, 200, 199, 196, 195, 191, 191, 183, 178, 175, 174, 173, 171, 170, 170, 168, 167, 163, 163, 164, 163 ],
          PolyY: [ 79, 86, 85, 85, 84, 84, 86, 85, 87, 91, 95, 96, 98, 100, 101, 102, 105, 108, 112, 115, 117, 121, 124, 125, 124, 124, 121, 118, 115, 114, 110, 108, 107, 105, 101, 98, 95, 89, 87, 81, 78, 80, 77, 74, 72, 71, 68, 67, 63, 60, 58, 58, 59, 57, 57, 58, 59, 60, 59, 58, 56, 53, 53, 55, 55, 54, 56, 57, 59, 60, 62, 62, 68, 69, 72, 75 ],
          ClosePath: true,
          LakeList:
          [
            {
              Type: 'Lake',
              PolyX: [ 212, 212, 214, 214, 213 ],
              PolyY: [ 92, 90, 90, 91, 92 ],
              ClosePath: true,
            },
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Madagaskar',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 223, 224, 225, 227, 230, 231, 230, 229, 227, 224, 224 ],
          PolyY: [ 112, 115, 116, 115, 106, 106, 103, 102, 105, 106, 111 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
      ], // end LandList
    }, // end Continent
    {
      Type: 'Continent',
      Name: 'Eurasia',
      Color: null,
      BorderColor: null,
      BorderWidth: null,
      DrawMode: null,
      LandList:
      [
        {
          Type: 'Land',
          Name: 'EuropeAsia',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 360, 356, 342, 340, 333, 329, 320, 318, 313, 311, 310, 311, 304, 303, 294, 293, 294, 291, 284, 266, 265, 252, 251, 250, 246, 248, 248, 244, 239, 240, 229, 223, 220, 215, 213, 218, 220, 221, 221, 214, 209, 203, 201, 199, 193, 195, 190, 185, 185, 186, 188, 191, 193, 196, 197, 199, 199, 197, 197, 201, 202, 204, 205, 201, 201, 208, 207, 202, 201, 194, 191, 190, 190, 188, 188, 185, 182, 180, 178, 178, 175, 178, 179, 178, 172, 171, 171, 170, 171, 171, 173, 174, 178, 180, 180, 183, 183, 186, 188, 190, 192, 196, 196, 192, 195, 196, 197, 198, 196, 194, 192, 193, 195, 199, 199, 201, 201, 203, 204, 203, 205, 206, 207, 210, 213, 215, 216, 215, 214, 212, 212, 214, 215, 215, 219, 219, 223, 223, 225, 232, 238, 240, 237, 236, 234, 232, 230, 230, 228, 230, 231, 235, 236, 237, 237, 242, 246, 251, 252, 256, 256, 257, 258, 260, 260, 261, 262, 260, 260, 267, 272, 274, 274, 277, 278, 278, 280, 281, 284, 284, 283, 281, 280, 279, 280, 281, 284, 284, 285, 289, 289, 286, 286, 288, 289, 289, 288, 289, 291, 291, 295, 297, 301, 303, 302, 301, 299, 300, 303, 303, 301, 299, 299, 301, 301, 305, 305, 306, 306, 307, 310, 308, 308, 310, 311, 314, 318, 320, 320, 321, 322, 322, 323, 323, 324, 323, 321, 320, 317, 316, 323, 334, 337, 340, 340, 342, 344, 344, 341, 335, 336, 337, 339, 340, 340, 342, 342, 343, 343, 342, 344, 350, 356, 359, 360, 358, 360 ],
          PolyY: [ 21, 20, 20, 19, 19, 17, 17, 18, 18, 19, 18, 17, 16, 17, 17, 16, 14, 13, 12, 15, 16, 17, 16, 16, 19, 21, 22, 20, 20, 21, 21, 22, 25, 25, 23, 24, 24, 23, 22, 21, 19, 19, 20, 20, 22, 22, 26, 28, 31, 32, 32, 31, 34, 34, 31, 31, 30, 29, 28, 26, 24, 24, 25, 27, 30, 30, 31, 31, 35, 36, 36, 35, 33, 33, 36, 37, 39, 41, 40, 41, 41, 43, 45, 47, 46, 47, 50, 51, 52, 53, 53, 54, 53, 51, 50, 48, 47, 47, 46, 46, 48, 50, 52, 52, 53, 52, 50, 50, 48, 47, 45, 44, 46, 48, 50, 52, 53, 54, 52, 50, 49, 50, 53, 54, 54, 53, 54, 58, 59, 59, 60, 62, 60, 62, 67, 69, 74, 77, 77, 75, 71, 68, 66, 64, 66, 66, 64, 63, 61, 60, 62, 64, 63, 63, 64, 65, 65, 70, 70, 80, 81, 82, 82, 80, 84, 84, 83, 79, 75, 69, 69, 72, 75, 75, 77, 82, 84, 87, 89, 88, 85, 83, 81, 80, 77, 77, 80, 82, 82, 79, 75, 72, 70, 69, 69, 70, 71, 72, 70, 69, 67, 67, 63, 59, 56, 55, 55, 54, 54, 53, 52, 52, 51, 49, 51, 50, 52, 53, 56, 56, 54, 51, 50, 49, 47, 47, 44, 41, 39, 38, 39, 44, 44, 41, 41, 36, 37, 36, 36, 35, 31, 31, 28, 28, 29, 29, 28, 29, 30, 34, 39, 39, 37, 37, 36, 36, 34, 34, 32, 32, 30, 30, 28, 28, 27, 25, 25 ],
          ClosePath: false,
          LakeList:
          [
            {
              Type: 'Lake',
              PolyX: [ 208, 208, 211, 213, 213, 214, 215, 217, 221, 222, 221, 217, 215, 213, 211 ],
              PolyY: [ 49, 47, 44, 44, 46, 46, 45, 45, 47, 48, 49, 49, 48, 48, 49 ],
              ClosePath: true,
            },
            {
              Type: 'Lake',
              PolyX: [ 229, 229, 230, 227, 227, 231, 233, 233, 230, 233, 234, 234, 233, 233, 234, 234, 232 ],
              PolyY: [ 53, 51, 50, 47, 45, 43, 43, 44, 46, 48, 48, 49, 49, 51, 51, 53, 54 ],
              ClosePath: true,
            },
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'EuropeAsiaContinued',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 0, 4, 5, 8, 10, 8, 6, 0 ],
          PolyY: [ 25, 25, 26, 26, 24, 23, 23, 21 ],
          ClosePath: false,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Iceland',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 157, 160, 162, 166, 167, 164, 159, 157, 156, 156 ],
          PolyY: [ 26, 27, 27, 26, 25, 24, 24, 23, 24, 25 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'GreatBritain',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 174, 181, 182, 182, 180, 180, 178, 177, 179, 176, 177, 175, 174, 174, 176, 177, 175, 176, 174, 176 ],
          PolyY: [ 40, 39, 38, 37, 37, 36, 34, 34, 32, 32, 31, 31, 33, 34, 36, 37, 37, 38, 38, 39 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Ireland',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 169, 170, 174, 174, 175, 174, 172, 171, 170, 170, 171 ],
          PolyY: [ 38, 39, 38, 36, 36, 35, 35, 36, 36, 37, 37 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'OstrovNakhodka',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 315, 321, 328, 332, 336, 336, 329, 320, 316, 313, 313 ],
          PolyY: [ 16, 15, 16, 17, 16, 15, 14, 14, 12, 13, 14 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'ZalivHedentrom',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 271, 275, 280, 279, 284, 286, 284, 281, 280, 280, 277, 277, 273 ],
          PolyY: [ 10, 11, 11, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Svalbard',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 191, 196, 197, 199, 200, 201, 204, 205, 203, 200, 206, 207, 191 ],
          PolyY: [ 11, 14, 14, 12, 12, 13, 13, 12, 12, 11, 11, 10, 10 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'RegionSjaelland',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 191, 192, 192, 191 ],
          PolyY: [ 35, 35, 34, 34 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Sardinia',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 188, 190, 190, 189, 190, 189, 188, 189, 188 ],
          PolyY: [ 51, 51, 49, 49, 48, 47, 48, 49, 49 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Majorca',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 182, 183, 184, 183 ],
          PolyY: [ 51, 51, 50, 50 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Sumatra',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 275, 275, 278, 279, 281, 284, 286, 285, 288, 294, 297, 302, 306, 295, 294, 292, 291, 290, 289, 288, 286, 286, 287, 286, 284, 284, 280, 278 ],
          PolyY: [ 84, 85, 88, 90, 93, 96, 96, 97, 98, 99, 99, 99, 98, 98, 97, 97, 96, 97, 97, 96, 96, 93, 93, 91, 91, 89, 87, 85 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Indonesia',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 289, 290, 292, 296, 296, 298, 299, 298, 298, 299, 297, 292, 291, 291, 289 ],
          PolyY: [ 91, 93, 94, 94, 92, 89, 89, 88, 86, 85, 83, 87, 87, 88, 88 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Sulawesi',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 299, 300, 300, 302, 303, 303, 302, 304, 304, 305, 305, 304, 300, 300, 303, 301, 299 ],
          PolyY: [ 96, 96, 93, 96, 96, 94, 92, 91, 90, 89, 88, 89, 89, 90, 90, 91, 91 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Philippines',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 304, 306, 307, 306, 306, 304, 302, 301, 302, 302, 301, 300, 300, 301, 303, 302, 304 ],
          PolyY: [ 84, 84, 83, 80, 78, 76, 76, 74, 73, 72, 72, 74, 75, 77, 81, 83, 83 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Taiwan',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 300, 301, 302, 301, 300 ],
          PolyY: [ 68, 68, 65, 65, 67 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Japan',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 310, 311, 312, 313, 320, 321, 322, 322, 321, 323, 325, 326, 324, 322, 321, 320, 320, 318, 316, 312, 309 ],
          PolyY: [ 59, 59, 57, 57, 55, 54, 51, 50, 48, 48, 47, 46, 46, 45, 47, 47, 51, 53, 54, 55, 57 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
      ], // end LandList
    }, // end Continent
    {
      Type: 'Continent',
      Name: 'Australia',
      Color: null,
      BorderColor: null,
      BorderWidth: null,
      DrawMode: null,
      LandList:
      [
        {
          Type: 'Land',
          Name: 'Australia',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 295, 296, 298, 300, 304, 304, 306, 308, 309, 311, 314, 315, 316, 317, 317, 318, 320, 323, 325, 326, 327, 328, 330, 330, 333, 334, 333, 331, 330, 329, 328, 326, 326, 325, 324, 323, 322, 321, 320, 315, 317, 315, 313, 310, 310, 309, 306, 302, 302, 301, 299, 295, 293, 293, 295, 295, 296, 296 ],
          PolyY: [ 124, 125, 125, 124, 124, 123, 122, 122, 121, 121, 123, 125, 125, 124, 125, 125, 128, 129, 128, 129, 129, 128, 128, 126, 122, 118, 115, 112, 112, 110, 110, 109, 107, 104, 104, 101, 101, 107, 108, 105, 102, 102, 101, 101, 103, 104, 104, 107, 108, 110, 110, 111, 114, 116, 119, 121, 122, 123 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'PapuaNewGuinea',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 312, 313, 317, 318, 318, 317, 318, 319, 320, 321, 323, 324, 326, 327, 331, 331, 329, 327, 328, 328, 331, 333, 332, 331, 328, 328, 327, 323, 317, 316, 315, 314, 314, 313, 312, 310, 311 ],
          PolyY: [ 92, 94, 95, 96, 97, 98, 99, 98, 98, 99, 99, 98, 98, 100, 101, 100, 99, 97, 97, 96, 96, 94, 94, 95, 95, 96, 96, 93, 91, 93, 93, 92, 91, 90, 90, 91, 92 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'Tasmania',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 324, 326, 327, 328, 328, 327, 326, 325 ],
          PolyY: [ 131, 134, 134, 133, 130, 131, 131, 130 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
        {
          Type: 'Land',
          Name: 'NewZealand',
          SpanPole: '',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 346, 349, 351, 352, 353, 353, 354, 354, 355, 357, 357, 358, 359, 358, 357, 356, 355, 354, 352, 355, 354, 355, 355, 354, 353, 353, 350, 348 ],
          PolyY: [ 136, 137, 136, 134, 134, 133, 132, 131, 132, 130, 129, 129, 127, 127, 128, 128, 127, 125, 124, 128, 129, 130, 131, 131, 131, 130, 133, 134 ],
          ClosePath: true,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
      ], // end LandList
    }, // end Continent
    {
      Type: 'Continent',
      Name: 'Antarctica',
      Color: null,
      BorderColor: null,
      BorderWidth: null,
      DrawMode: null,
      LandList:
      [
        {
          Type: 'Land',
          Name: 'Antarctica',
          SpanPole: 'S',
          Color: null,
          BorderColor: null,
          BorderWidth: null,
          DrawMode: null,
          PolyX: [ 360, 350, 350, 349, 346, 344, 343, 344, 346, 349, 351, 349, 346, 341, 334, 330, 330, 328, 320, 317, 315, 315, 308, 307, 300, 296, 297, 289, 285, 280, 277, 276, 276, 267, 263, 262, 261, 262, 257, 254, 250, 240, 236, 231, 219, 211, 204, 195, 184, 179, 178, 166, 165, 154, 155, 152, 153, 143, 136, 129, 119, 120, 120, 118, 120, 123, 123, 116, 113, 113, 111, 110, 107, 104, 105, 107, 107, 101, 97, 91, 85, 83, 78, 76, 73, 62, 55, 52, 52, 37, 27, 23, 21, 4, 0 ],
          PolyY: [ 167, 167, 166, 166, 167, 167, 166, 164, 164, 163, 161, 161, 160, 160, 158, 158, 156, 157, 157, 155, 155, 156, 156, 155, 157, 157, 155, 157, 155, 156, 154, 155, 156, 156, 157, 156, 156, 157, 159, 159, 158, 157, 156, 156, 159, 159, 160, 159, 160, 159, 160, 161, 162, 164, 165, 165, 166, 168, 168, 167, 165, 163, 157, 155, 155, 154, 153, 155, 157, 159, 160, 159, 159, 160, 162, 162, 163, 162, 164, 163, 162, 161, 161, 163, 164, 164, 163, 163, 164, 164, 166, 166, 168, 168, 167 ],
          ClosePath: false,
          LakeList:
          [
          ], // end LakeList
        }, // end Land
      ], // end LandList
    }, // end Continent
  ], // end ContinentList

  // private working objects (cache)
  clippedPolyList: new JsgPolygonList( true ),
  workPoly: new JsgPolygon(),
  plane: null,
  p: [ 0, 0, 0 ],
  p1: [ 0, 0, 0 ],
  p2: [ 0, 0, 0 ],
  p3: [ 0, 0, 0 ],
  shadowIsClipped: false,
  ToRad: Math.PI / 180,
  ToDeg: 180 / Math.PI,

  GetContinent: function( name ) {
    for (var c = 0; c < this.ContinentList.length; c++) {
      if (this.ContinentList[c].Name == name) return this.ContinentList[c];
    }
    return null;
  },

  GetLand: function( name ) {
    for (var c = 0; c < this.ContinentList.length; c++) {
      var continent = this.ContinentList[c];
      for (var l = 0; l < continent.LandList.length; l++) {
        if (continent.LandList[l].Name == name) return continent.LandList[l];
      }
    }
    return null;
  },

  SetColor: function( landColor, landBorderColor, landBorderWidth, landDrawMode ) {
    this.LandColor = xDefStr( landColor, this.LandColor );
    this.LandBorderColor = xDefStr( landBorderColor, this.LandBorderColor );
    this.LandBorderWidth = xDefNum( landBorderWidth, this.LandBorderWidth );
    this.LandDrawMode = xDefNum( landDrawMode, this.LandDrawMode );
    for (var c = 0; c < this.ContinentList.length; c++) {
      var continent = this.ContinentList[c];
      continent.Color = null;
      continent.BorderColor = null;
      continent.BorderWidth = null;
      continent.DrawMode = null;
      for (var l = 0; l < continent.LandList.length; l++) {
        var land = continent.LandList[l];
        land.Color = null;
        land.BorderColor = null;
        land.BorderWidth = null;
        land.DrawMode = null;
      }
    }
  },

  SetWaterColor: function( color, borderColor, borderWidth, drawMode ) {
    this.WaterColor = xDefStr( color, this.WaterColor );
    this.WaterBorderColor = xDefStr( borderColor, this.WaterBorderColor );
    this.WaterBorderWidth = xDefNum( borderWidth, this.WaterBorderWidth );
    this.WaterDrawMode = xDefNum( drawMode, this.WaterDrawMode );
  },

  SetLakeColor: function( color, borderColor, borderWidth, drawMode ) {
    this.LakeColor = xDefStr( color, this.LakeColor );
    this.LakeBorderColor = xDefStr( borderColor, this.LakeBorderColor );
    this.LakeBorderWidth = xDefNum( borderWidth, this.LakeBorderWidth );
    this.LakeDrawMode = xDefNum( drawMode, this.LakeDrawMode );
  },

  SetContinentColor: function( name, colors, borderColors, borderWidths, drawModes ) {
    // name: null or string; null -> set color for all contients according colors
    // colors, borderColors: string or array of string or null
    // borderWidths, drawModes: int or array of int or null
    // undefined values set attributes to parent attribute (null)
    if (name) {
      // set color for single continent
      if (xArray(colors)) colors = colors[0];
      if (xArray(borderColors)) borderColors = borderColors[0];
      if (xArray(borderWidths)) borderWidths = borderWidths[0];
      if (xArray(drawModes)) drawModes = drawModes[0];
      var continent = this.GetContinent( name );
      if (!continent) return;
      continent.Color = xDefStr( colors, null );
      continent.BorderColor = xDefStr( borderColors, null );
      continent.BorderWidth = xDefNum( borderWidths, null );
      continent.DrawMode = xDefNum( drawModes, null );
      for (var l = 0; l < continent.LandList.length; l++) {
        var land = continent.LandList[l];
        land.Color = null;
        land.BorderColor = null;
        land.BorderWidth = null;
        land.DrawMode = null;
      }
    } else {
      // set color for all continents
      if (!colors) colors = null;
      if (!borderColors) borderColors = null;
      if (!borderWidths) borderWidths = null;
      if (!drawModes) drawModes = null;
      if (!xArray(colors)) colors = [ colors ];
      if (!xArray(borderColors)) borderColors = [ borderColors ];
      if (!xArray(borderWidths)) borderWidths = [ borderWidths ];
      if (!xArray(drawModes)) drawModes = [ drawModes ];
      var nColors = colors.length;
      var nBorderColors = borderColors.length;
      var nBorderWidths = borderWidths.length;
      var nDrawModes = drawModes.length;
      for (var c = 0; c < this.ContinentList.length; c++) {
        var continent = this.ContinentList[c];
        continent.Color = colors[c % nColors];
        continent.BorderColor = borderColors[c % nBorderColors];
        continent.BorderWidth = borderWidths[c % nBorderWidths];
        continent.DrawMode = drawModes[c % nDrawModes];
        for (var l = 0; l < continent.LandList.length; l++) {
          var land = continent.LandList[l];
          land.Color = null;
          land.BorderColor = null;
          land.BorderWidth = null;
          land.DrawMode = null;
        }
      }
    }
  },

  SetLandColor: function( name, color, borderColor, borderWidth, drawMode ) {
    // name: string; land name
    // color, borderColor: string or null or undefined
    // borderWidth, drawMode: number or null or undefined
    // undefined or null attributes -> null -> set to parent attributes
    var land = this.GetLand( name );
    if (!land) return;
    land.Color = xDefStr( color, null );
    land.BorderColor = xDefStr( borderColor, null );
    land.BorderWidth = xDefNum( borderWidth, null );
    land.DrawMode = xDefNum( drawMode, null );
  },

  DrawGlobe: function( g ) {

    g.SaveTrans3D( true );

    // compute clipping plane
    this.CompClipPlane( g );

    // draw sea water
    g.SetAreaAttr( this.WaterColor, this.WaterBorderColor, this.WaterBorderWidth );
    g.SetPlane( this.ClipPlane );
    g.CircleOnPlane( 0, 0, this.ClipPlane.Radius, this.WaterDrawMode );

    // draw continents
    var nContinents = this.ContinentList.length;
    for (var i = 0; i < nContinents; i++) {
      this.DrawGlobeContinent( g, this.ContinentList[i] );
    }

    g.RestoreTrans3D();
  },

  DrawGlobeEquator: function( g, saveTrans ) {
    // set attributes before calling this function
    this.DrawGlobeLatitude( g, 0, saveTrans );
  },

  DrawGlobeMeridian: function( g, lng, asGreatCircle, saveTrans ) {
    // set attributes before calling this function
    lng = xDefNum( lng, 0 );
    asGreatCircle = xDefBool( asGreatCircle, false );
    this.DrawGlobeLongitude( g, lng, asGreatCircle, saveTrans );
  },

  DrawGlobeGrid: function( g, dLng, dLat ) {
    g.SaveTrans3D();
    g.SetTrans3D( this.Trans, true );

    dLng = xDefNum( dLng, 15 );
    dLat = xDefNum( dLat, dLng );
    dLat = Math.abs( dLat );
    dLng = Math.abs( dLng );
    var limit = 90 - dLat / 2;
    for (var a = 0; a < limit; a += dLat) {
      this.DrawGlobeLatitude( g, a, false );
    }
    var limit = -(90 - dLat / 2);
    for (var a = -dLat; a > limit; a -= dLat) {
      this.DrawGlobeLatitude( g, a, false );
    }
    var limit = 180 - dLng / 2;
    for (var a = 0; a < limit; a += dLng) {
      this.DrawGlobeLongitude( g, a, true, false );
    }

    g.RestoreTrans3D();
  },

  DrawGlobeLatitude: function( g, lat, saveTrans ) {
    // set attributes before calling this function
    saveTrans = xDefBool( saveTrans, true );
    if (saveTrans) {
      g.SaveTrans3D();
    }
    g.SetTrans3D( this.Trans, true );
    g.NewPoly3D( true );
    var dAng = 360 / this.NContourPoints;
    var lastAng = 360 + dAng / 2;
    for (var lng = 0; lng < lastAng; lng += dAng) {
      g.AddPointToPoly3D( this.PointOnGlobe( lat, lng ) );
    }
    g.ResetTrans3D();
    this.GlobeClipAndDrawPoly( g );
    if (saveTrans) {
      g.RestoreTrans3D();
    }
  },

  DrawGlobeLongitude: function( g, lng, asGreatCircle, saveTrans ) {
    // set attributes before calling this function
    saveTrans = xDefBool( saveTrans, true );
    if (saveTrans) {
      g.SaveTrans3D();
    }
    g.SetTrans3D( this.Trans, true );
    g.NewPoly3D( true );
    var dAng = 360 / this.NContourPoints;
    var lastAng = 90 + dAng / 2;
    if (asGreatCircle) lastAng += 180;
    for (var lat = -90; lat < lastAng; lat += dAng) {
      g.AddPointToPoly3D( this.PointOnGlobe( lat, lng ) );
    }
    g.ResetTrans3D();
    this.GlobeClipAndDrawPoly( g );
    if (saveTrans) {
      g.RestoreTrans3D();
    }
  },

  DrawGlobeShadow: function( g, sunVect, sunDist, drawMode ) {
    // sunVect: JsgVect3; direction from earth center to sun
    // if sunDist = 0 then sun is treated as infinte far in the distance sunVect
    // if sunDist > 0 then sun is treated as sunDist from earth origin

    g.SaveTrans3D( true );

    // compute shadow plane
    var shadowPlane = this.CompPlane( sunVect, sunDist );

    // create shadow terminator circle on shadow plane
    var dAng = 2 * Math.PI / this.NContourPoints;
    var lastAng = 2 * Math.PI - dAng / 2;
    g.NewPoly3D();
    for (var a = 0; a < lastAng; a += dAng) {
      var x = shadowPlane.Radius * Math.cos(a);
      var y = shadowPlane.Radius * Math.sin(a);
      var p = JsgVect3.CopyTo( shadowPlane.Pos, this.p );
      JsgVect3.AddTo( p, JsgVect3.Scale( shadowPlane.XDir, x ) );
      JsgVect3.AddTo( p, JsgVect3.Scale( shadowPlane.YDir, y ) );
      g.AddPointToPoly3D( p );
    }
    g.Poly3D.GetFirstPoint3D( p );
    g.AddPointToPoly3D( p );

    // clip shadow terminator and compute clip plane contour of shadow
    this.clippedPolyList.Reset();
    this.shadowIsClipped = false;
    this.ClipPlane.ClipArea( g.Poly3D, this.clippedPolyList, this.GlobeShadowClipFunc, this );
    if (this.clippedPolyList.IsEmpty()) {
      // lit part lies behind clip plane
      if (JsgVect3.ScalarProd( shadowPlane.Normal, this.ClipPlane.Normal ) < 0) {
        // sun is shining from into face of camera, so the whole earth is in shadow as seen from camera
        this.AddFullShadow( this.clippedPolyList );
      } else if (shadowPlane.Radius < this.ClipPlane.Radius) {
        // sun is shining from behind the camera,
        // so the radius of the shadow-clip defines whether shadow is visible or not
        // here the shadow circle is smaller than the earth and behind clip plane,
        // so the visible part of the earth is fully in shadow
        this.AddFullShadow( this.clippedPolyList );
      }
    } else {
      // lit part is at least partially visible
      if (!this.shadowIsClipped) {
        // if lit part is not clipped then some ring shadow is visible, so make this ring
        this.AddFullShadow( this.clippedPolyList );
      }
    }
    if (!this.clippedPolyList.IsEmpty()) {
      drawMode = xDefNum( drawMode, 2 );
      g.PolygonList3D( this.clippedPolyList, drawMode );
    }

    g.RestoreTrans3D();
  },

  DrawGlobeMarker: function( g, lat, lng, mode ) {
    // set marker attributes before
    mode = mode || 3;
    g.Marker3D( this.PointOnGlobe( lat, lng ), mode );
  },

  DrawGlobeGreatCircleArc: function( g, lat1, lng1, lat2, lng2, big ) {
    // draws a great circle line
    // line attributes must be set
    // changes g.Plane to draw
    // returns true if arc could be drawn,
    // returns false if points are identical or opposite so the arc is undefined
    var p1 = this.PointOnGlobe( lat1, lng1, this.p1 );
    var p2 = this.PointOnGlobe( lat2, lng2, this.p2 );
    var plane = this.GetGlobeGreatCirclePlane( p1, p2, this.plane, true );
    // assert: this.p1 and this.p2 get normed by GetGreatCirclePlane()
    if (!plane) return false;
    var a = this.GetGlobeGreatCircleAngle( p1, p2, true );
    if (g.AngleMeasure == 'deg') a *= this.ToDeg;
    g.SetPlane( plane );
    if (big) {
      ae = g.AngleMeasure == 'deg' ? 360 : 2 * Math.PI;
      g.ArcOnPlane( 0, 0, this.Radius, a, ae, 1 );
    } else {
      g.ArcOnPlane( 0, 0, this.Radius, 0, a, 1 );
    }
    return true;
  },

  GetGlobeGreatCircleAngle: function( p1, p2, isInternal ) {
    // returns the angle in rad between p1 and p2
    // isInternal can be set to true if p1, p2 are in this.p1, this.p2 and normed
    var p1normed, p2normed;
    if (isInternal) {
      p1normed = this.p1;
      p2normed = this.p2;
    } else {
      p1normed = JsgVect3.CopyTo( p1, this.p1 );
      p2normed = JsgVect3.CopyTo( p2, this.p2 );
      JsgVect3.NormTo( p1normed );
      JsgVect3.NormTo( p2normed );
    }
    return Math.acos( this.RangePM1( JsgVect3.ScalarProd( p1normed, p2normed ) ) );
  },

  GetGlobeGreatCirclePlane: function( p1, p2, plane, isInternal ) {
    // returns a plane through the center of the globe which contains p1 and p2
    // this plane can be used to draw a great circle arc
    // returns null if p1, p2 are identical or opposite so no unique plane can be computed
    // p1, p2: JsgVect3;
    // plane: JsgPlane or undefined
    // returns plane or this.plane or null
    // isInternal can be set to true if p1, p2 are in this.p1, this.p2
    if (!plane) {
      if (!this.plane) this.plane = new JsgPlane( [0,0,0], [1,0,0], [0,1,0], false );
      plane = this.plane;
    }
    var p1normed, p2normed;
    if (isInternal) {
      p1normed = this.p1;
      p2normed = this.p2;
    } else {
      p1normed = JsgVect3.CopyTo( p1, this.p1 );
      p2normed = JsgVect3.CopyTo( p2, this.p2 );
    }
    JsgVect3.NormTo( p1normed );
    JsgVect3.NormTo( p2normed );
    var n = JsgVect3.MultTo( this.p, p1normed, p2normed );
    if (JsgVect3.Length( n ) < 1e-8) {
      return null;
    }
    JsgVect3.NormTo( n );
    var y = JsgVect3.MultTo( this.p3, n, p1normed );
    plane.Set( [0,0,0], p1normed, y, false );
    return plane;
  },

  GetClipPointAngle: function( plane, clipPoint ) {
    // compute angle in range 0..2Pi as measured from planes x-axis CCW
    var x = JsgVect3.ScalarProd( plane.XDir, JsgVect3.Sub( clipPoint, plane.Pos ) );
    var y = JsgVect3.ScalarProd( plane.YDir, JsgVect3.Sub( clipPoint, plane.Pos ) );
    var ang = JsgVect2.Angle( [1,0], [x,y], true );
    if (ang < 0) ang += 2 * Math.PI;
    return ang;
  },

  AddFullShadow: function( clippedPolyList ) {
    var dAng = 2 * Math.PI / this.NContourPoints;
    var limitAng = 0 - dAng;
    for (var a = 2*Math.PI; a > limitAng; a -= dAng) {
      var px = this.ClipPlane.Radius * Math.cos( a );
      var py = this.ClipPlane.Radius * Math.sin( a );
      clippedPolyList.AddPoint3D( this.ClipPlane.PointOnPlane( px, py ) );
    }
    clippedPolyList.Close();
  },

  GlobeShadowClipFunc: function( plane, clippedPolyList, earth ) {
    // create surface circle between intersection points plane.ExitPoint and plane.EnterPoint
    // always clockwise and add them to clippedPolyList.
    // earth: this EarthMap

    var enterAng = earth.GetClipPointAngle( plane, plane.EnterPoint );
    var exitAng  = earth.GetClipPointAngle( plane, plane.ExitPoint );
    var dAng = 2 * Math.PI / earth.NContourPoints;
    if (exitAng < enterAng) {
      exitAng += 2 * Math.PI;
    }
    // assert exitAng > enterAng
    var angOffset = ((exitAng - enterAng) % dAng) / 2;
    for (var a = exitAng - angOffset; a > enterAng; a -= dAng) {
      var px = plane.Radius * Math.cos( a );
      var py = plane.Radius * Math.sin( a );
      clippedPolyList.AddPoint3D( plane.PointOnPlane( px, py ) );
    }
    earth.shadowIsClipped = true;

  },

  CompClipPlane: function( g ) {
    this.ClipPlane = this.CompPlane( g.Camera.CamPos, -1 );
  },

  CompPlane: function( vDest, dDest ) {
    // creates a JsgPlane where planes normal is facing vDest
    // adds properties Radius and Offset to JsgPlane
    // if dDest < 0 then vDest is treated as a point and dDest is computed as vDest-globe_origin
    // if dDest = 0 then vDest is treated as a vector and dDest as infinte
    // if dDest > 0 then vDest is treated as a vector and dDest gived the distance from globe_origin
    var origin = JsgVect3.Null();
    if (this.Trans) {
      // plane origin is moved to m[i][3]
      var m = this.Trans;
      JsgVect3.Set( origin, m[0][3], m[1][3], m[2][3] );
    }
    if (dDest < 0) {
      vDest = JsgVect3.Sub( vDest, origin );
      dDest = JsgVect3.Length( vDest );
    }
    var dPlane = 0;
    var rPlane = this.Radius;
    if (dDest > this.Radius) {
      var r2 = this.Radius * this.Radius;
      dPlane = r2 / dDest;
      rPlane = Math.sqrt( r2 - dPlane * dPlane );
    }
    var oPlane = JsgVect3.Add( origin, JsgVect3.Scale( JsgVect3.Norm(vDest), dPlane ) );
    var xPlane = JsgVect3.Mult( [0,0,1], vDest );
    var yPlane = JsgVect3.Mult( vDest, xPlane );
    var plane = new JsgPlane( oPlane, xPlane, yPlane, true );
    plane.Radius = rPlane;
    plane.Offset = dPlane;
    return plane;
  },

  DrawGlobeContinent: function( g, continent ) {
    var color = this.LandColor;
    var borderColor = this.LandBorderColor;
    var borderWidth = this.LandBorderWidth;
    var drawMode = this.LandDrawMode;
    if (continent.Color) color = continent.Color;
    if (continent.BorderColor) borderColor = continent.BorderColor;
    if (continent.BorderWidth) borderWidth = continent.BorderWidth;
    if (continent.DrawMode) drawMode = continent.DrawMode;

    var nLands = continent.LandList.length;
    for (var i = 0; i < nLands; i++) {
      this.DrawGlobeLand( g, continent.LandList[i], color, borderColor, borderWidth, drawMode );
    }
  },

  GlobeClipAndDrawArea: function( g, drawMode ) {
    // clip g.Poly3D at globe clipping plane and draw it
    this.clippedPolyList.Reset();
    this.ClipPlane.ClipArea( g.Poly3D, this.clippedPolyList, this.GlobeClipFunc, this );
    g.PolygonList3D( this.clippedPolyList, drawMode );
  },

  GlobeClipAndDrawPoly: function( g ) {
    // clip g.Poly3D at globe clipping plane and draw it
    this.clippedPolyList.Reset();
    this.ClipPlane.ClipPoly( g.Poly3D, this.clippedPolyList );
    g.PolygonList3D( this.clippedPolyList, 1 );
  },

  DrawGlobeLand: function( g, land, color, borderColor, borderWidth, drawMode ) {

    if (land.Color) color = land.Color;
    if (land.BorderColor) borderColor = land.BorderColor;
    if (land.BorderWidth) borderWidth = land.BorderWidth;
    if (land.DrawMode) drawMode = land.DrawMode;

    // build land polygon
    // note: this.Trans is used in g.AddPointToPoly3D() -> see NewPoly3D(true)
    g.SetTrans3D( this.Trans, true );
    g.NewPoly3D( true );
    var nLandPoints = land.PolyX.length;
    for (var i = 0; i < nLandPoints; i++) {
      g.AddPointToPoly3D( this.PointOnGlobe( 90-land.PolyY[i], land.PolyX[i]-180 ) );
    }
    g.AddPointToPoly3D( this.PointOnGlobe( 90-land.PolyY[0], land.PolyX[0]-180 ) );
    // g.Poly3D containes this.Trans transformed polygon, so it needs not to be transformed again
    g.ResetTrans3D();

    // clip land at clip plane and draw it
    g.SetAreaAttr( color, borderColor, borderWidth );
    // GlobeClipAndDrawArea uses g.Poly3D where the geom is stored
    this.GlobeClipAndDrawArea( g, drawMode );

    // draw lakes
    var nLakes = land.LakeList.length;
    if (nLakes > 0) {
      g.SetAreaAttr( this.LakeColor, this.LakeBorderColor, this.LakeBorderWidth );
      for (var i = 0; i < nLakes; i++) {
        this.DrawGlobeLake( g, land.LakeList[i] );
      }
    }
  },

  DrawGlobeLake: function( g, lake ) {

    // build lake polygon
    // note: this.Trans is used in g.AddPointToPoly3D() -> see NewPoly3D(true)
    g.SetTrans3D( this.Trans, true );
    g.NewPoly3D( true );
    var nLakePoints = lake.PolyX.length;
    for (var i = 0; i < nLakePoints; i++) {
      g.AddPointToPoly3D( this.PointOnGlobe( 90-lake.PolyY[i], lake.PolyX[i]-180 ) );
    }
    g.AddPointToPoly3D( this.PointOnGlobe( 90-lake.PolyY[0], lake.PolyX[0]-180 ) );
    // g.Poly3D containes this.Trans transformed polygon, so it needs not to be transformed again
    g.ResetTrans3D();

    // clip lake at clip plane and
    // GlobeClipAndDrawArea uses g.Poly3D where the geom is stored
    this.GlobeClipAndDrawArea( g, this.LakeDrawMode );

  },

  GlobeClipFunc: function( plane, clippedPolyList, earth ) {
    // create surface circle between intersection points plane.ExitPoint and plane.EnterPoint
    // and add them to clippedPolyList.
    // earth: this EarthMap
    // Note: this function is not perfectly correct, because it interpolates along the earth clip circle
    // always the shorter way between Exit- and EnterPoint.
    // This works well as long as the clip circle is not fully inside an area.

    var enterAng = earth.GetClipPointAngle( plane, plane.EnterPoint );
    var exitAng  = earth.GetClipPointAngle( plane, plane.ExitPoint );
    var dAng = 2 * Math.PI / earth.NContourPoints;
    var angRange = Math.abs( enterAng - exitAng );
    var angOffset;
    if (angRange < Math.PI) {
      angOffset = (angRange % dAng) / 2;
      if (enterAng < exitAng) {
        dAng = -dAng;
        angOffset = -angOffset;
      }
    } else {
      if (enterAng < exitAng) {
        enterAng += 2 * Math.PI;
        // assert enterAng > exitAng
        angRange = enterAng - exitAng;
        angOffset = (angRange % dAng) / 2;
      } else {
        exitAng += 2 * Math.PI;
        // asser exitAng > enterAng
        angRange = exitAng - enterAng;
        angOffset = -(angRange % dAng) / 2;
        dAng = -dAng;
      }
    }
    for (var a = exitAng + angOffset; dAng > 0 ? a < enterAng : a  > enterAng; a += dAng) {
      var px = earth.ClipPlane.Radius * Math.cos( a );
      var py = earth.ClipPlane.Radius * Math.sin( a );
      clippedPolyList.AddPoint3D( plane.PointOnPlane( px, py ) );
    }

  },

  PointOnGlobe: function( lat, lng, p ) {
    // lat, lng in deg
    // p: JsgVect3 or undefined
    // return p or this.p
    p = p || this.p;
    var rr = this.Radius * Math.cos( this.ToRad * lat );
    p[0] = rr * Math.cos( this.ToRad * lng );
    p[1] = rr * Math.sin( this.ToRad * lng );
    p[2] = this.Radius * Math.sin( this.ToRad * lat );
    return p;
  },

  GlobeCoordOfPoint: function( p, coord ) {
    // p: JsgVect3; p[0] is direction 0-Meridian, p[1] is direction x rot 90 deg east, p[2] is dir north
    // coord: JsgVect2 or undefined
    // returns coord or this.p: JsgVect2
    // return[0] -> latitude, return[1] -> longitude
    coord = coord || this.p;
    var pNormed = JsgVect3.Set( this.p1, p[0], p[1], p[2] );
    Jsgvect3.NormTo( pNormed );
    var sp = JsgVect3.ScalarProd( [0,0,1], pNormed );
    coord[0] = (Math.PI/2 - Math.acos( this.RangePM1(sp) ) ) * this.ToDeg;
    var pXYplane = JsgVect3.Set( this.p2, pNormed[0], pNormed[1], 0 );
    JsgVect3.NormTo( pXYplane );
    var sp = JsgVect3.ScalarProd( [1,0,0], pXYplane );
    coord[1] = Math.acos( this.RangePM1(sp) ) * this.ToDeg;
    if (pXYplane[1] < 0) coord[1] *= -1;
    return coord;
  },

  GlobeCoordOfPointXYZ: function( x, y, z, coord ) {
    // see GlobeCoordOfPoint() above
    JsgVect3.Set( this.p2, x, y, z );
    return this.GlobeCoordOfPoint( this.p2, coord );
  },

  DrawFlatEarth: function( g ) {

    // draw sea water
    g.SetAreaAttr( this.WaterColor, this.WaterBorderColor, this.WaterBorderWidth );
    if (this.FEMode >= 2) {
      g.CircleOnPlane( 0, 0, this.Radius, this.WaterDrawMode );
    } else {
      g.Circle( 0, 0, this.Radius, this.WaterDrawMode );
    }
    var nContinents = this.ContinentList.length;
    for (var c = 0; c < nContinents; c++) {
      this.DrawFlatEarthContinent( g, this.ContinentList[c] );
    }
  },

  DrawFlatEarthContinent: function( g, continent ) {
    var color = this.LandColor;
    var borderColor = this.LandBorderColor;
    var borderWidth = this.LandBorderWidth;
    var drawMode = this.LandDrawMode;
    if (continent.Color) color = continent.Color;
    if (continent.BorderColor) borderColor = continent.BorderColor;
    if (continent.BorderWidth) borderWidth = continent.BorderWidth;
    if (continent.DrawMode) drawMode = continent.DrawMode;

    var nLands = continent.LandList.length;
    for (var i = 0; i < nLands; i++) {
      this.DrawFlatEarthLand( g, continent.LandList[i], color, borderColor, borderWidth, drawMode );
    }
  },

  DrawFlatEarthLand: function( g, land, color, borderColor, borderWidth, drawMode ) {
    // this.FEMode: 0 -> use Polygon, 1 -> SplineCurve, 2 -> PolygonOnPlane, 3 -> SplineCurveOnPlane

    if (land.Color) color = land.Color;
    if (land.BorderColor) borderColor = land.BorderColor;
    if (land.BorderWidth) borderWidth = land.BorderWidth;
    if (land.DrawMode) drawMode = land.DrawMode;

    g.SetAreaAttr( color, borderColor, borderWidth );
    if (this.FEMode >= 2) {
      g.OpenPath3D();
    } else {
      g.OpenPath();
    }
    var lmode = drawMode & 2; // fill
    if (land.SpanPole == '') lmode += drawMode & 1; // border
    if (land.ClosePath) lmode += 4; // close
    this.DrawFlatEarthArea( g, land, lmode );

    // handle pole areas: fill and draw border separately
    if (land.SpanPole == 'S') {
      if (this.FEMode >= 2) {
        g.CircleOnPlane( 0, 0, this.Radius );
      } else {
        g.Circle( 0, 0, this.Radius, this.WaterDrawMode );
      }
      if (this.FEMode >= 2) {
        g.Path3D( lmode ); // fill with pole area
        g.OpenPath3D();
      } else {
        g.Path( lmode ); // fill with pole area
        g.OpenPath();
      }
      lmode = 1; // border
      if (land.ClosePath) lmode += 4; // close
      this.DrawFlatEarthArea( g, land, lmode );
      // earth border
      if (this.FEMode >= 2) {
        g.CircleOnPlane( 0, 0, this.Radius, 1 );
      } else {
        g.Circle( 0, 0, this.Radius, 1 );
      }
    }
    if (this.FEMode >= 2) {
      g.Path3D( lmode ); // fill with pole area
    } else {
      g.Path( lmode ); // fill with pole area
    }

    // draw lakes
    var nLakes = land.LakeList.length;
    if (nLakes > 0) {
      g.SetAreaAttr( this.LakeColor, this.LakeBorderColor, this.LakeBorderWidth );
      for (var i = 0; i < nLakes; i++) {
        var lake = land.LakeList[i];
        var mode = this.LakeDrawMode;
        if (lake.ClosePath) mode += 4;
        this.DrawFlatEarthArea( g, lake, mode );
      }
    }

  },

  DrawFlatEarthArea: function( g, area, mode ) {
    var poly = this.MapToFE( area );
    if (this.FEMode == 0) {
      g.Polygon( poly, mode );
    } else if (this.FEMode == 1) {
      g.SplineCurve( poly, this.SplineTension, mode );
    } else if (this.FEMode == 2) {
      g.PolygonOnPlane( poly, mode );
    } else {
      g.SplineCurveOnPlane( poly, this.SplineTension, mode );
    }
  },

  MapToFE: function( geom ) {
    var poly = this.workPoly.Reset();
    var size = geom.PolyX.length;
    for (var i = 0; i < size; i++) {
      var a = geom.PolyX[i]; // 0..360 180 = 0 meridian
      var r = geom.PolyY[i]; // 0..180 0 = north
      r *= this.Radius / 180;
      a = (a+90) * this.ToRad;
      poly.AddPoint( r * Math.cos(a), r * Math.sin(a) );
    }
    return poly;
  },

  PointOnFE: function( lat, lng, p ) {
    // lat: -90..90, 0 = equator
    // lng: -180..180, 0 = meridian
    // p: JsgVect2 or undefined
    // returns p: JsgVect2 or this.p
    p = p || this.p;
    var r = (90 - lat) * this.Radius / 180;
    var a = (lng - 90) * this.ToRad;
    p[0] = r * Math.cos(a);
    p[1] = r * Math.sin(a);
    return p;
  },

  RangePM1: function( x ) {
    if (x > 1) { x = 1; } else if (x < -1) { x = -1; }
    return x;
  },

  FECoordOfPoint: function( p, coord ) {
    // p: JsgVect2; p[0] is direction 0-Meridian, p[1] is direction x rot 90 deg left
    // coord: JsgVect2 or undefined
    // returns coord or this.p: JsgVect2
    // return[0] -> latitude, return[1] -> longitude
    coord = coord || this.p;
    coord[0] = (1 - JsgVect2.Length(p) / this.Radius) * 90;
    var sp = JsgVect2.ScalarProd( [1,0], p );
    coord[1] = Math.acos( this.RangePM1(sp) ) * this.ToDeg;
    if (p[1] < 0) coord[1] *= -1;
    return coord;
  },

  FECoordOfPointXY: function( x, y, coord ) {
    // see FECoordOfPoint() above
    JsgVect2.Set( this.p1, x, y );
    return this.FECoordOfPoint( this.p1, coord );
  },

  DrawFlatEarthMarker: function( g, lat, lng, mode ) {
    // set marker attributes before
    mode = mode || 3;
    var p = this.PointOnFE( lat, lng );
    if (this.FEMode >= 2) {
      g.MarkerOnPlane( p, mode );
    } else {
      g.Marker( p, mode );
    }
  },

  DrawFlatEarthLine: function( g, lat1, lng1, lat2, lng2 ) {
    // set attributes before
    var p1 = this.PointOnFE( lat1, lng1, this.p1 );
    var p2 = this.PointOnFE( lat2, lng2, this.p2 );
    if (this.FEMode >= 2) {
      g.LineOnPlane( p1, p2 );
    } else {
      g.Line( p1, p2 );
    }
  },

  DrawFlatEarthGrid: function( g, dLat, dLng ) {
    // set attributes before
    dLng = xDefNum( dLng, 15 );
    dLat = xDefNum( dLat, dLng );
    dLat = Math.abs( dLat );
    dLng = Math.abs( dLng );
    var limit = 90 - dLat / 2;
    for (var a = 0; a < limit; a += dLat) {
      this.DrawFlatEarthLatitude( g, a );
    }
    var limit = -(90 - dLat / 2);
    for (var a = -dLat; a > limit; a -= dLat) {
      this.DrawFlatEarthLatitude( g, a );
    }
    var limit = 180 - dLng / 2;
    for (var a = 0; a < limit; a += dLng) {
      this.DrawFlatEarthLongitude( g, a, true );
    }
  },

  DrawFlatEarthEquator: function( g ) {
    this.DrawFlatEarthLatitude( g, 0 );
  },

  DrawFlatEarthBorder: function( g ) {
    this.DrawFlatEarthLatitude( g, -90 );
  },

  DrawFlatEarthMeridian: function( g ) {
    this.DrawFlatEarthLongitude( g, 0 );
  },

  DrawFlatEarthLatitude: function( g, lat ) {
    // set attributes before
    var r = (90 - lat) * this.Radius / 180;
    if (this.FEMode >= 2) {
      g.CircleOnPlane( 0, 0, r, 1 );
    } else {
      g.Circle( 0, 0, r, 1 );
    }
  },

  DrawFlatEarthLongitude: function( g, lng, asGreatCircle ) {
    // set attributes before
    var p1 = JsgVect2.Set( this.p1, 0, 0 );
    var p2 = this.PointOnFE( -90, lng, this.p2 );
    if (asGreatCircle) {
      JsgVect2.Set( p1, -p2[0], -p2[1] );
    }
    if (this.FEMode >= 2) {
      g.LineOnPlane( p1, p2 );
    } else {
      g.Line( p1, p2 );
    }
  },

} // end EarthMap


More Page Infos / Sitemap
Created Dienstag, 10. Oktober 2017
Scroll to Top of Page
Changed Dienstag, 10. Oktober 2017