Commit 51e480f8 authored by Calvin Metcalf's avatar Calvin Metcalf
Browse files

move wkt and make it more functional

parent 8c5275ac
Loading
Loading
Loading
Loading
+56 −269
Original line number Diff line number Diff line
@@ -20,74 +20,34 @@ define(function(require, exports, module) {
  var constants = require('./constants');
  var datum = require('./datum');
  var projections = require('./projections');
  var wkt = require('./wkt');
  
  var proj = function proj(srsCode) {
    if (!(this instanceof proj)) {
      return new proj(srsCode);
    }
    this.srsCodeInput = srsCode;
  
    var obj;
    //check to see if this is a WKT string
    if ((srsCode.indexOf('GEOGCS') >= 0) || (srsCode.indexOf('GEOCCS') >= 0) || (srsCode.indexOf('PROJCS') >= 0) || (srsCode.indexOf('LOCAL_CS') >= 0)) {
      this.parseWKT(srsCode);
      this.deriveConstants();
      obj = wkt(srsCode);
      this.deriveConstants(obj);
      extend(this,obj);
      //this.loadProjCode(this.projName);
  
    }
    else {
      if (srsCode.indexOf(":") > -1) {
        this.srsAuth = srsCode.split(':')[0].toLowerCase();
        this.srsProjNumber = srsCode.split(':')[1];

      // DGR 2008-08-03 : support urn and url
      if (srsCode.indexOf('urn:') === 0) {
        //urn:ORIGINATOR:def:crs:CODESPACE:VERSION:ID
        var urn = srsCode.split(':');
        if ((urn[1] === 'ogc' || urn[1] === 'x-ogc') && (urn[2] === 'def') && (urn[3] === 'crs')) {
          srsCode = urn[4] + ':' + urn[urn.length - 1];
        }
      }
      else if (srsCode.indexOf('http://') === 0) {
        //url#ID
        var url = srsCode.split('#');
        if (url[0].match(/epsg.org/)) {
          // http://www.epsg.org/#
          srsCode = 'EPSG:' + url[1];
        }
        else if (url[0].match(/RIG.xml/)) {
          //http://librairies.ign.fr/geoportail/resources/RIG.xml#
          //http://interop.ign.fr/registers/ign/RIG.xml#
          srsCode = 'IGNF:' + url[1];
        }
        else if (url[0].indexOf('/def/crs/') !== -1) {
          // http://www.opengis.net/def/crs/EPSG/0/code
          url = srsCode.split('/');
          srsCode = url.pop(); //code
          url.pop(); //version FIXME
          srsCode = url.pop() + ':' + srsCode; //authority
        }
      }
      this.srsCode = srsCode.toUpperCase();
      if (this.srsCode.indexOf("EPSG") === 0) {
        this.srsCode = this.srsCode;
        this.srsAuth = 'epsg';
        this.srsProjNumber = this.srsCode.substring(5);
        // DGR 2007-11-20 : authority IGNF
      }
      else if (this.srsCode.indexOf("IGNF") === 0) {
        this.srsCode = this.srsCode;
        this.srsAuth = 'IGNF';
        this.srsProjNumber = this.srsCode.substring(5);
        // DGR 2008-06-19 : pseudo-authority CRS for WMS
      }
      else if (this.srsCode.indexOf("CRS") === 0) {
        this.srsCode = this.srsCode;
        this.srsAuth = 'CRS';
        this.srsProjNumber = this.srsCode.substring(4);
      }
      else {
        this.srsAuth = '';
        this.srsProjNumber = this.srsCode;
      }
      this.parseDefs(srsCode);

      this.parseDefs();
    }
    this.initTransforms(this.projName);
  };
@@ -159,197 +119,24 @@ define(function(require, exports, module) {
     * Parses a WKT string to get initialization parameters
     *
     */
    wktRE: /^(\w+)\[(.*)\]$/,
    parseWKT: function(wkt) {
      var wktMatch = wkt.match(this.wktRE);
      if (!wktMatch) {
        return;
      }
      var wktObject = wktMatch[1];
      var wktContent = wktMatch[2];
      var wktTemp = wktContent.split(",");
      var wktName;
      if (wktObject.toUpperCase() === "TOWGS84") {
        wktName = wktObject; //no name supplied for the TOWGS84 array
      }
      else {
        wktName = wktTemp.shift();
      }
      wktName = wktName.replace(/^\"/, "");
      wktName = wktName.replace(/\"$/, "");
  
      /*
      wktContent = wktTemp.join(",");
      var wktArray = wktContent.split("],");
      for (var i=0; i<wktArray.length-1; ++i) {
        wktArray[i] += "]";
      }
      */
  
      var wktArray = [];
      var bkCount = 0;
      var obj = "";
      for (var i = 0; i < wktTemp.length; ++i) {
        var token = wktTemp[i];
        for (var j2 = 0; j2 < token.length; ++j2) {
          if (token.charAt(j2) === "[") {
            ++bkCount;
          }
          if (token.charAt(j2) === "]") {
            --bkCount;
          }
        }
        obj += token;
        if (bkCount === 0) {
          wktArray.push(obj);
          obj = "";
        }
        else {
          obj += ",";
        }
      }
  
      //this is grotesque -cwm
      var name, value;
      switch (wktObject) {
      case 'LOCAL_CS':
        this.projName = 'identity';
        this.localCS = true;
        this.srsCode = wktName;
        break;
      case 'GEOGCS':
        this.projName = 'longlat';
        this.geocsCode = wktName;
        if (!this.srsCode) {
          this.srsCode = wktName;
        }
        break;
      case 'PROJCS':
        this.srsCode = wktName;
        break;
      case 'GEOCCS':
        break;
      case 'PROJECTION':
        this.projName = constants.wktProjections[wktName];
        break;
      case 'DATUM':
        this.datumName = wktName;
        break;
      case 'LOCAL_DATUM':
        this.datumCode = 'none';
        break;
      case 'SPHEROID':
        this.ellps = wktName;
        this.a = parseFloat(wktArray.shift());
        this.rf = parseFloat(wktArray.shift());
        break;
      case 'PRIMEM':
        this.from_greenwich = parseFloat(wktArray.shift()); //to radians?
        break;
      case 'UNIT':
        this.units = wktName;
        this.unitsPerMeter = parseFloat(wktArray.shift());
        break;
      case 'PARAMETER':
        name = wktName.toLowerCase();
        value = parseFloat(wktArray.shift());
        //there may be many variations on the wktName values, add in case
        //statements as required
        switch (name) {
        case 'false_easting':
          this.x0 = value;
          break;
        case 'false_northing':
          this.y0 = value;
          break;
        case 'scale_factor':
          this.k0 = value;
          break;
        case 'central_meridian':
          this.long0 = value * common.D2R;
          break;
        case 'latitude_of_origin':
          this.lat0 = value * common.D2R;
          break;
        case 'more_here':
          break;
        default:
          break;
        }
        break;
      case 'TOWGS84':
        this.datum_params = wktArray;
        break;
        //DGR 2010-11-12: AXIS
      case 'AXIS':
        name = wktName.toLowerCase();
        value = wktArray.shift();
        switch (value) {
        case 'EAST':
          value = 'e';
          break;
        case 'WEST':
          value = 'w';
          break;
        case 'NORTH':
          value = 'n';
          break;
        case 'SOUTH':
          value = 's';
          break;
        case 'UP':
          value = 'u';
          break;
        case 'DOWN':
          value = 'd';
          break;
          //case 'OTHER': 
        default:
          value = ' ';
          break; //FIXME
        }
        if (!this.axis) {
          this.axis = "enu";
        }
        switch (name) {
        case 'x':
          this.axis = value + this.axis.substr(1, 2);
          break;
        case 'y':
          this.axis = this.axis.substr(0, 1) + value + this.axis.substr(2, 1);
          break;
        case 'z':
          this.axis = this.axis.substr(0, 2) + value;
          break;
        default:
          break;
        }
        break;
      case 'MORE_HERE':
        break;
      default:
        break;
      }
      for (var j = 0; j < wktArray.length; ++j) {
        this.parseWKT(wktArray[j]);
      }
    },
  
    /**
     * Function: parseDefs
     * Parses the PROJ.4 initialization string and sets the associated properties.
     *
     */
    parseDefs: function() {
      this.defData = defs[this.srsCode];
    parseDefs: function(srsCode) {
      this.defData = defs[srsCode];
      if (!this.defData) {
        return;
      }else{
        this.srsCode = srsCode;
      }
      var key;
      for (key in this.defData) {
        this[key] = this.defData[key];
      }
      this.deriveConstants();
      extend(this,this.deriveConstants(this));
    },
  
    /**
@@ -358,75 +145,75 @@ define(function(require, exports, module) {
     *     parameters.
     *
     */
    deriveConstants: function() {
    deriveConstants: function(self) {
      // DGR 2011-03-20 : nagrids -> nadgrids
      if (this.nadgrids && this.nadgrids.length === 0) {
        this.nadgrids = null;
      if (self.nadgrids && self.nadgrids.length === 0) {
        self.nadgrids = null;
      }
      if (this.nadgrids) {
        this.grids = this.nadgrids.split(",");
      if (self.nadgrids) {
        self.grids = self.nadgrids.split(",");
        var g = null,
          l = this.grids.length;
          l = self.grids.length;
        if (l > 0) {
          for (var i = 0; i < l; i++) {
            g = this.grids[i];
            g = self.grids[i];
            var fg = g.split("@");
            if (fg[fg.length - 1] === "") {
              //proj4.reportError("nadgrids syntax error '" + this.nadgrids + "' : empty grid found");
              //proj4.reportError("nadgrids syntax error '" + self.nadgrids + "' : empty grid found");
              continue;
            }
            this.grids[i] = {
            self.grids[i] = {
              mandatory: fg.length === 1, //@=> optional grid (no error if not found)
              name: fg[fg.length - 1],
              grid: constants.grids[fg[fg.length - 1]] //FIXME: grids loading ...
            };
            if (this.grids[i].mandatory && !this.grids[i].grid) {
              //proj4.reportError("Missing '" + this.grids[i].name + "'");
            if (self.grids[i].mandatory && !self.grids[i].grid) {
              //proj4.reportError("Missing '" + self.grids[i].name + "'");
            }
          }
        }
        // DGR, 2011-03-20: grids is an array of objects that hold
        // the loaded grids, its name and the mandatory informations of it.
      }
      if (this.datumCode && this.datumCode !== 'none') {
        var datumDef = constants.Datum[this.datumCode];
      if (self.datumCode && self.datumCode !== 'none') {
        var datumDef = constants.Datum[self.datumCode];
        if (datumDef) {
          this.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
          this.ellps = datumDef.ellipse;
          this.datumName = datumDef.datumName ? datumDef.datumName : this.datumCode;
          self.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
          self.ellps = datumDef.ellipse;
          self.datumName = datumDef.datumName ? datumDef.datumName : self.datumCode;
        }
      }
      if (!this.a) { // do we have an ellipsoid?
        var ellipse = constants.Ellipsoid[this.ellps] ? constants.Ellipsoid[this.ellps] : constants.Ellipsoid.WGS84;
        extend(this, ellipse);
      if (!self.a) { // do we have an ellipsoid?
        var ellipse = constants.Ellipsoid[self.ellps] ? constants.Ellipsoid[self.ellps] : constants.Ellipsoid.WGS84;
        extend(self, ellipse);
      }
      if (this.rf && !this.b) {
        this.b = (1.0 - 1.0 / this.rf) * this.a;
      if (self.rf && !self.b) {
        self.b = (1.0 - 1.0 / self.rf) * self.a;
      }
      if (this.rf === 0 || Math.abs(this.a - this.b) < common.EPSLN) {
        this.sphere = true;
        this.b = this.a;
      if (self.rf === 0 || Math.abs(self.a - self.b) < common.EPSLN) {
        self.sphere = true;
        self.b = self.a;
      }
      this.a2 = this.a * this.a; // used in geocentric
      this.b2 = this.b * this.b; // used in geocentric
      this.es = (this.a2 - this.b2) / this.a2; // e ^ 2
      this.e = Math.sqrt(this.es); // eccentricity
      if (this.R_A) {
        this.a *= 1 - this.es * (common.SIXTH + this.es * (common.RA4 + this.es * common.RA6));
        this.a2 = this.a * this.a;
        this.b2 = this.b * this.b;
        this.es = 0;
      self.a2 = self.a * self.a; // used in geocentric
      self.b2 = self.b * self.b; // used in geocentric
      self.es = (self.a2 - self.b2) / self.a2; // e ^ 2
      self.e = Math.sqrt(self.es); // eccentricity
      if (self.R_A) {
        self.a *= 1 - self.es * (common.SIXTH + self.es * (common.RA4 + self.es * common.RA6));
        self.a2 = self.a * self.a;
        self.b2 = self.b * self.b;
        self.es = 0;
      }
      this.ep2 = (this.a2 - this.b2) / this.b2; // used in geocentric
      if (!this.k0) {
        this.k0 = 1.0; //default value
      self.ep2 = (self.a2 - self.b2) / self.b2; // used in geocentric
      if (!self.k0) {
        self.k0 = 1.0; //default value
      }
      //DGR 2010-11-12: axis
      if (!this.axis) {
        this.axis = "enu";
      if (!self.axis) {
        self.axis = "enu";
      }
  
      this.datum = datum(this);
      self.datum = datum(self);
    }
  };
  proj.projections = projections;

src/wkt.js

0 → 100644
+172 −0
Original line number Diff line number Diff line
define(function(require, exports, module) {
  var common = require('./common');
  var constants = require('./constants');
  function wkt(wktStr,self) {
    self = self || {};
    var wktMatch = wktStr.match(/^(\w+)\[(.*)\]$/);
    if (!wktMatch) {
      return;
    }
    var wktObject = wktMatch[1];
    var wktContent = wktMatch[2];
    var wktTemp = wktContent.split(",");
    var wktName;
    if (wktObject.toUpperCase() === "TOWGS84") {
      wktName = wktObject; //no name supplied for the TOWGS84 array
    }
    else {
      wktName = wktTemp.shift();
    }
    wktName = wktName.trim().replace(/^\"/, "").replace(/\"$/, "");

    var wktArray = [];
    var bkCount = 0;
    var obj = "";
    for (var i = 0; i < wktTemp.length; ++i) {
      var token = wktTemp[i];
      for (var j2 = 0; j2 < token.length; ++j2) {
        if (token.charAt(j2) === "[") {
          ++bkCount;
        }
        if (token.charAt(j2) === "]") {
          --bkCount;
        }
      }
      obj += token;
      if (bkCount === 0) {
        wktArray.push(obj);
        obj = "";
      }
      else {
        obj += ",";
      }
    }

    //g is grotesque -cwm
    var name, value;
    switch (wktObject) {
    case 'LOCAL_CS':
      self.projName = 'identity';
      self.localCS = true;
      self.srsCode = wktName;
      break;
    case 'GEOGCS':
      self.projName = 'longlat';
      self.geocsCode = wktName;
      if (!self.srsCode) {
        self.srsCode = wktName;
      }
      break;
    case 'PROJCS':
      self.srsCode = wktName;
      break;
    case 'GEOCCS':
      break;
    case 'PROJECTION':
      self.projName = constants.wktProjections[wktName];
      break;
    case 'DATUM':
      self.datumName = wktName;
      break;
    case 'LOCAL_DATUM':
      self.datumCode = 'none';
      break;
    case 'SPHEROID':
      self.ellps = wktName;
      self.a = parseFloat(wktArray.shift());
      self.rf = parseFloat(wktArray.shift());
      break;
    case 'PRIMEM':
      self.from_greenwich = parseFloat(wktArray.shift()); //to radians?
      break;
    case 'UNIT':
      self.units = wktName;
      self.unitsPerMeter = parseFloat(wktArray.shift());
      break;
    case 'PARAMETER':
      name = wktName.toLowerCase();
      value = parseFloat(wktArray.shift());
      //there may be many variations on the wktName values, add in case
      //statements as required
      switch (name) {
      case 'false_easting':
        self.x0 = value;
        break;
      case 'false_northing':
        self.y0 = value;
        break;
      case 'scale_factor':
        self.k0 = value;
        break;
      case 'central_meridian':
        self.long0 = value * common.D2R;
        break;
      case 'latitude_of_origin':
        self.lat0 = value * common.D2R;
        break;
      case 'more_here':
        break;
      default:
        break;
      }
      break;
    case 'TOWGS84':
      self.datum_params = wktArray;
      break;
      //DGR 2010-11-12: AXIS
    case 'AXIS':
      name = wktName.toLowerCase();
      value = wktArray.shift();
      switch (value) {
      case 'EAST':
        value = 'e';
        break;
      case 'WEST':
        value = 'w';
        break;
      case 'NORTH':
        value = 'n';
        break;
      case 'SOUTH':
        value = 's';
        break;
      case 'UP':
        value = 'u';
        break;
      case 'DOWN':
        value = 'd';
        break;
        //case 'OTHER': 
      default:
        value = ' ';
        break; //FIXME
      }
      if (!self.axis) {
        self.axis = "enu";
      }
      switch (name) {
      case 'x':
        self.axis = value + self.axis.substr(1, 2);
        break;
      case 'y':
        self.axis = self.axis.substr(0, 1) + value + self.axis.substr(2, 1);
        break;
      case 'z':
        self.axis = self.axis.substr(0, 2) + value;
        break;
      default:
        break;
      }
      break;
    case 'MORE_HERE':
      break;
    default:
      break;
    }
    for (var j = 0; j < wktArray.length; ++j) {
      wkt(wktArray[j],self);
    }
    return self;
  }
  module.exports = wkt;
});