|
View:
New views
16 Messages
—
Rating Filter:
Alert me
|
|
|
OpenLayers.Format.KML.write()I'd like to implement a bit of OpenLayers.Format.KML.write() method, and enhance OpenLayers.Format.KML.read() to enabl.e Polygon node parsing... Questions: 1/ Did you have any reason not to have implemented Polygon parsing at once with Point and LineString? I thought it could be because of the outerBoudaryIs node, which cannot be translated into OpenLayers.Geometry object...? Or was it just laziness? :-) 2/ How do you see the namespaces for KML? My view is that one can parse any KML as a 2.0, fetching Placemark nodes and digging into their geometries, since this seems not to change over versions. Do you think it's a good way of doing it? Cheers, Damien --
Camptocamp SA
Damien Corpataux PSE A CH-1015 Lausanne +41 21 619 10 22 (Direct)
+41 21 619 10 10 (Centrale) +41 21 619 10 00 (Fax) P
Please consider the environment
Do you really need to print this email? _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write()On Tue, Aug 14, 2007 at 04:16:32PM +0200, Damien Corpataux wrote:
> Hello, > > I'd like to implement a bit of OpenLayers.Format.KML.write() method, and > enhance OpenLayers.Format.KML.read() to enabl.e Polygon node parsing... > > Questions: > 1/ Did you have any reason not to have implemented Polygon parsing at > once with Point and LineString? I thought it could be because of the > outerBoudaryIs node, which cannot be translated into OpenLayers.Geometry > object...? Or was it just laziness? :-) Just laziness. > 2/ How do you see the namespaces for KML? My view is that one can parse > any KML as a 2.0, fetching Placemark nodes and digging into their > geometries, since this seems not to change over versions. Do you think > it's a good way of doing it? I didn't know enough about KML at the time I wrote it to know if this was true or not. I'd be happy to be better informed either way. Regards, -- Christopher Schmidt MetaCarta _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write()Here's what I did so far... Reading KML only work for KML 2.0 namespaces for write() uses OpenLayers.Ajax.getElementsByTagNameNS(), but I'm pretty sure it will work on future versions (2.1 parsing successful). Also, GML and KML write() returns a Dom Document rather than a string. Should one change the result type, breaking OpenLayers.Format interface, or parse it into a string using OpenLayers.XML.....? Cheers, Damien --8<------------------------------------------------------------------------------------- Index: /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js =================================================================== --- /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js (revision 3900) +++ /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js (working copy) @@ -8,8 +8,8 @@ * @requires OpenLayers/Ajax.js * * Class: OpenLayers.Format.KML - * Read only KML. Largely Proof of Concept: does not support advanced Features, - * including Polygons. Create a new instance with the + * Read/write KML 2.0. Does not support advanced Features. + * Create a new instance with the * <OpenLayers.Format.KML> constructor. * * Inherits from: @@ -100,6 +100,19 @@ // TBD Bounds only set for one of multiple geometries geom.extendBounds(p.bounds); } + + // match Polygon + } else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, + this.kmlns, "", "Polygon").length != 0) { + var polygon = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, + this.kmlns, "", "Polygon")[0]; + p = this.parseCoords(polygon); + if (p.points) { + var linearRing = new OpenLayers.Geometry.LinearRing(p.points); + geom = new OpenLayers.Geometry.Polygon(linearRing); + // TBD Bounds only set for one of multiple geometries + geom.extendBounds(p.bounds); + } } feature.geometry = geom; @@ -190,6 +203,136 @@ } return p; }, + + /** + * Accept Feature Collection, and return a string. + * + * @param {Array} List of features to serialize into a string. + */ + write: function(features) { + var kml = document.createElementNS("http://earth.google.com/kml/2.0", "kml:kml"); // 'kml:' NS to be removed? + for (var i=0; i < features.length; i++) { + kml.appendChild(this.createPlacemarkXML(features[i])); + } + return kml; + }, + + /** + * Accept an OpenLayers.Feature.Vector, and build a geometry for it. + * + * @param OpenLayers.Feature.Vector feature + * @return DOMElement + */ + createPlacemarkXML: function(feature) { + // Placemark name + var placemarkName = document.createElementNS(this.kmlns, "kml:" + "name"); + var placemarkNameText = document.createTextNode(feature.id); + placemarkName.appendChild(placemarkNameText); + + // Placemark description + var placemarkDesc = document.createElementNS(this.kmlns, "kml:" + "description"); + var placemarkDescText = document.createTextNode("Not available"); + placemarkDesc.appendChild(placemarkDescText); + + // Placemark + var placemarkNode = document.createElementNS(this.kmlns, "kml:" + "Placemark"); + placemarkNode.appendChild(placemarkName); + placemarkNode.appendChild(placemarkDesc); + + // Geometry node (Point, LineString, etc. nodes) + var geometryNode = this.buildGeometryNode(feature.geometry); + placemarkNode.appendChild(geometryNode); + + return placemarkNode; + }, + + /** + * builds a KML geometry node with a given geometry + * + * @param {OpenLayers.Geometry} geometry + */ + buildGeometryNode: function(geometry) { + // TBD test if geoserver can be given a Multi-geometry for a simple-geometry data store + // ie if multipolygon can be sent for a polygon feature type + var kml = ""; + // match MultiPolygon or Polygon + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon" + || geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { + kml = document.createElementNS(this.kmlns, 'kml:Polygon'); + + var polygon = document.createElementNS(this.kmlns, 'kml:Polygon'); + var outerRing = document.createElementNS(this.kmlns, 'kml:outerBoundaryIs'); + var linearRing = document.createElementNS(this.kmlns, 'kml:LinearRing'); + + // TBD manage polygons with holes + linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0])); + outerRing.appendChild(linearRing); + polygon.appendChild(outerRing); + + kml.appendChild(polygon); + } + // match MultiLineString or LineString + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString" + || geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { + kml = document.createElementNS(this.kmlns, 'kml:LineString'); + + var lineString = document.createElementNS(this.kmlns, 'kml:LineString'); + + lineString.appendChild(this.buildCoordinatesNode(geometry)); + + kml.appendChild(lineString); + } + // match MultiPoint or Point + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" || + geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") { + kml = document.createElementNS(this.kmlns, 'kml:Point'); + + // FIXME: There should be only one Point node per Placemark node + var parts = ""; + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") { + parts = geometry.components; + } else { + parts = [geometry]; + } + + for (var i = 0; i < parts.length; i++) { + var point = document.createElementNS(this.kmlns, 'kml:Point'); + point.appendChild(this.buildCoordinatesNode(parts[i])); + kml.appendChild(point); + } + } + return kml; + }, + + /** + * builds the coordinates XmlNode + * <kml:coordinates>...</kml:coordinates> + * + * @param {OpenLayers.Geometry} geometry + * @return {XmlNode} created xmlNode + */ + buildCoordinatesNode: function(geometry) { + var coordinatesNode = document.createElementNS(this.kmlns, "kml:coordinates"); + + var points = null; + if (geometry.components) { + points = geometry.components; + } + + var path = ""; + if (points) { + for (var i = 0; i < points.length; i++) { + path += points[i].x + "," + points[i].y + " "; + } + } else { + path += geometry.x + "," + geometry.y + " "; + } + + var txtNode = document.createTextNode(path); + coordinatesNode.appendChild(txtNode); + + return coordinatesNode; + }, CLASS_NAME: "OpenLayers.Format.KML" }); Christopher Schmidt wrote: On Tue, Aug 14, 2007 at 04:16:32PM +0200, Damien Corpataux wrote: --
Camptocamp SA
Damien Corpataux PSE A CH-1015 Lausanne +41 21 619 10 22 (Direct)
+41 21 619 10 10 (Centrale) +41 21 619 10 00 (Fax) P
Please consider the environment
Do you really need to print this email? _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write()Hi-
So, we're mid-way through changing how XML flavors are read/written in OpenLayers. I've checked a new XML format in to the trunk. This format has most of the methods we need for reading/writing XML cross-browser. To parse other XML flavors, format classes should be created that inherit from the XML format. For an (incomplete) example, see: http://dev.openlayers.org/sandbox/tschaub/xml/lib/OpenLayers/Format/GML.js (The important part to notice in the above example is that the GML format inherits from the XML format.) Instead of using OpenLayers.Ajax methods or document methods, DOM creation and traversal should be done with OpenLayers.Format.XML methods. I've created methods to reflect the W3C standard XML DOM methods - wrapping the standard ones and accommodating for non-compliant browsers. If you (or anyone) needs additional XML DOM methods, they should be added to the XML format. The next addition (in my mind) is setAttributeNS. Aside from that, you should be able to do efficient parsing and dom creation with the XML format methods. Please make modifications to the KML format in the trunk. Create a ticket and attach patches in Trac. I can offer review or other help as needed. I don't have time to keep these sandboxes entirely clean right now - so please forgive anything you find that is in a half-developed state. Tim PS - Eventually, I'll move the following example into the trunk. It would be nice if we could demonstrate read/write capability for all vector formats in this way: http://dev.openlayers.org/sandbox/tschaub/xml/examples/vector-formats.html (note again that this reflects partially complete work - and you should not be surprised to encounter errors or see changes at any time) Damien Corpataux wrote: > Hello, > > Here's what I did so far... Reading KML only work for KML 2.0 namespaces > for write() uses OpenLayers.Ajax.getElementsByTagNameNS(), but I'm > pretty sure it will work on future versions (2.1 parsing successful). > Also, GML and KML write() returns a Dom Document rather than a string. > Should one change the result type, breaking OpenLayers.Format interface, > or parse it into a string using OpenLayers.XML.....? > > Cheers, > Damien > > > --8<------------------------------------------------------------------------------------- > > Index: /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > =================================================================== > --- > /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > (revision 3900) > +++ > /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > (working copy) > @@ -8,8 +8,8 @@ > * @requires OpenLayers/Ajax.js > * > * Class: OpenLayers.Format.KML > - * Read only KML. Largely Proof of Concept: does not support advanced > Features, > - * including Polygons. Create a new instance with the > + * Read/write KML 2.0. Does not support advanced Features. > + * Create a new instance with the > * <OpenLayers.Format.KML> constructor. > * > * Inherits from: > @@ -100,6 +100,19 @@ > // TBD Bounds only set for one of multiple geometries > geom.extendBounds(p.bounds); > } > + > + // match Polygon > + } else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, > + this.kmlns, "", "Polygon").length != 0) { > + var polygon = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, > + this.kmlns, "", "Polygon")[0]; > + p = this.parseCoords(polygon); > + if (p.points) { > + var linearRing = new > OpenLayers.Geometry.LinearRing(p.points); > + geom = new OpenLayers.Geometry.Polygon(linearRing); > + // TBD Bounds only set for one of multiple geometries > + geom.extendBounds(p.bounds); > + } > } > > feature.geometry = geom; > @@ -190,6 +203,136 @@ > } > return p; > }, > + > + /** > + * Accept Feature Collection, and return a string. > + * > + * @param {Array} List of features to serialize into a string. > + */ > + write: function(features) { > + var kml = > document.createElementNS("http://earth.google.com/kml/2.0", "kml:kml"); > // 'kml:' NS to be removed? > + for (var i=0; i < features.length; i++) { > + kml.appendChild(this.createPlacemarkXML(features[i])); > + } > + return kml; > + }, > + > + /** > + * Accept an OpenLayers.Feature.Vector, and build a geometry for it. > + * > + * @param OpenLayers.Feature.Vector feature > + * @return DOMElement > + */ > + createPlacemarkXML: function(feature) { > + // Placemark name > + var placemarkName = document.createElementNS(this.kmlns, "kml:" > + "name"); > + var placemarkNameText = document.createTextNode(feature.id); > + placemarkName.appendChild(placemarkNameText); > + > + // Placemark description > + var placemarkDesc = document.createElementNS(this.kmlns, "kml:" > + "description"); > + var placemarkDescText = document.createTextNode("Not available"); > + placemarkDesc.appendChild(placemarkDescText); > + > + // Placemark > + var placemarkNode = document.createElementNS(this.kmlns, "kml:" > + "Placemark"); > + placemarkNode.appendChild(placemarkName); > + placemarkNode.appendChild(placemarkDesc); > + > + // Geometry node (Point, LineString, etc. nodes) > + var geometryNode = this.buildGeometryNode(feature.geometry); > + placemarkNode.appendChild(geometryNode); > + > + return placemarkNode; > + }, > + > + /** > + * builds a KML geometry node with a given geometry > + * > + * @param {OpenLayers.Geometry} geometry > + */ > + buildGeometryNode: function(geometry) { > + // TBD test if geoserver can be given a Multi-geometry for a > simple-geometry data store > + // ie if multipolygon can be sent for a polygon feature type > + var kml = ""; > + // match MultiPolygon or Polygon > + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon" > + || geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { > + kml = document.createElementNS(this.kmlns, 'kml:Polygon'); > + > + var polygon = document.createElementNS(this.kmlns, > 'kml:Polygon'); > + var outerRing = document.createElementNS(this.kmlns, > 'kml:outerBoundaryIs'); > + var linearRing = document.createElementNS(this.kmlns, > 'kml:LinearRing'); > + > + // TBD manage polygons with holes > + > linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0])); > + outerRing.appendChild(linearRing); > + polygon.appendChild(outerRing); > + > + kml.appendChild(polygon); > + } > + // match MultiLineString or LineString > + else if (geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiLineString" > + || geometry.CLASS_NAME == > "OpenLayers.Geometry.LineString") { > + kml = document.createElementNS(this.kmlns, > 'kml:LineString'); > + > + var lineString = > document.createElementNS(this.kmlns, 'kml:LineString'); > + > + > lineString.appendChild(this.buildCoordinatesNode(geometry)); > + > + kml.appendChild(lineString); > + } > + // match MultiPoint or Point > + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" || > + geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiPoint") { > + kml = document.createElementNS(this.kmlns, 'kml:Point'); > + > + // FIXME: There should be only one Point node per > Placemark node > + var parts = ""; > + if (geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiPoint") { > + parts = geometry.components; > + } else { > + parts = [geometry]; > + } > + > + for (var i = 0; i < parts.length; i++) { > + var point = document.createElementNS(this.kmlns, > 'kml:Point'); > + point.appendChild(this.buildCoordinatesNode(parts[i])); > + kml.appendChild(point); > + } > + } > + return kml; > + }, > + > + /** > + * builds the coordinates XmlNode > + * <kml:coordinates>...</kml:coordinates> > + * > + * @param {OpenLayers.Geometry} geometry > + * @return {XmlNode} created xmlNode > + */ > + buildCoordinatesNode: function(geometry) { > + var coordinatesNode = document.createElementNS(this.kmlns, > "kml:coordinates"); > + > + var points = null; > + if (geometry.components) { > + points = geometry.components; > + } > + > + var path = ""; > + if (points) { > + for (var i = 0; i < points.length; i++) { > + path += points[i].x + "," + points[i].y + " "; > + } > + } else { > + path += geometry.x + "," + geometry.y + " "; > + } > + > + var txtNode = document.createTextNode(path); > + coordinatesNode.appendChild(txtNode); > + > + return coordinatesNode; > + }, > > CLASS_NAME: "OpenLayers.Format.KML" > }); > > > > > Christopher Schmidt wrote: >> On Tue, Aug 14, 2007 at 04:16:32PM +0200, Damien Corpataux wrote: >> >>> Hello, >>> >>> I'd like to implement a bit of OpenLayers.Format.KML.write() method, and >>> enhance OpenLayers.Format.KML.read() to enabl.e Polygon node parsing... >>> >>> Questions: >>> 1/ Did you have any reason not to have implemented Polygon parsing at >>> once with Point and LineString? I thought it could be because of the >>> outerBoudaryIs node, which cannot be translated into OpenLayers.Geometry >>> object...? Or was it just laziness? :-) >>> >> >> Just laziness. >> >> >>> 2/ How do you see the namespaces for KML? My view is that one can parse >>> any KML as a 2.0, fetching Placemark nodes and digging into their >>> geometries, since this seems not to change over versions. Do you think >>> it's a good way of doing it? >>> >> >> I didn't know enough about KML at the time I wrote it to know if this >> was true or not. I'd be happy to be better informed either way. >> >> Regards, >> > > > -- > Camptocamp SA > Damien Corpataux > PSE A > CH-1015 Lausanne > +41 21 619 10 22 (Direct) > +41 21 619 10 10 (Centrale) > +41 21 619 10 00 (Fax) > P Please consider the environment > Do you really need to print this email? > !DSPAM:4033,46c30f78118678362916074! > > > ------------------------------------------------------------------------ > > _______________________________________________ > Dev mailing list > Dev@... > http://openlayers.org/mailman/listinfo/dev > > > !DSPAM:4033,46c30f78118678362916074! _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write()As far as I can see, the advantages of doing so are obvious. Althought I didn't have time to apply these, here is a new version of the patch: - puts placemarks in a folder tag (for google earth import) - bugfix with geometry tags Is the question about write() return type (string or DOMDocuemt/DOMNode) still open? Cheers, Damien Patch: Index: /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js =================================================================== --- /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js (revision 3900) +++ /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js (working copy) @@ -8,8 +8,8 @@ * @requires OpenLayers/Ajax.js * * Class: OpenLayers.Format.KML - * Read only KML. Largely Proof of Concept: does not support advanced Features, - * including Polygons. Create a new instance with the + * Read/write KML 2.0. Does not support advanced Features. + * Create a new instance with the * <OpenLayers.Format.KML> constructor. * * Inherits from: @@ -24,6 +24,24 @@ kmlns: "http://earth.google.com/kml/2.0", /** + * APIProperty: placemarksDesc + * Default description for a placemark + */ + placemarksDesc: "No description available", + + /** + * APIProperty: foldersName + * Default name for a folder + */ + foldersName: "OpenLayers export", + + /** + * APIProperty: foldersDesc + * Default description for a folder + */ + foldersDesc: "Exported on " + new Date(), + + /** * Constructor: OpenLayers.Format.KML * Create a new parser for KML * @@ -46,7 +64,7 @@ if (typeof data == "string") { data = OpenLayers.parseXMLString(data); } - var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, this.kmlns, "", "Placemark"); + var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, this.kmlns, "kml", "Placemark"); var features = []; @@ -100,6 +118,19 @@ // TBD Bounds only set for one of multiple geometries geom.extendBounds(p.bounds); } + + // match Polygon + } else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, + this.kmlns, "", "Polygon").length != 0) { + var polygon = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, + this.kmlns, "", "Polygon")[0]; + p = this.parseCoords(polygon); + if (p.points) { + var linearRing = new OpenLayers.Geometry.LinearRing(p.points); + geom = new OpenLayers.Geometry.Polygon(linearRing); + // TBD Bounds only set for one of multiple geometries + geom.extendBounds(p.bounds); + } } feature.geometry = geom; @@ -191,5 +222,171 @@ return p; }, + /** + * Method: write + * Accept Feature Collection, and return an XML Document. + * + * Parameters: + * features - An array of <OpenLayers.Feature.Vector> features. + * + * Returns: + * <DOMDocument> + */ + write: function(features) { + var kml = document.createElementNS(this.kmlns, "kml"); + var folder = this.createFolderXML(); + for (var i=0; i < features.length; i++) { + folder.appendChild(this.createPlacemarkXML(features[i])); + } + kml.appendChild(folder); + return kml; + }, + + /** + * Method: createFolderXML + * Creates and returns a KML Folder node with default name and description + * + * Returns: + * xmlNode - {<XMLNode>} + */ + createFolderXML: function() { + // Folder name + var folderName = document.createElementNS(this.kmlns, "name"); + var folderNameText = document.createTextNode(this.foldersName); + folderName.appendChild(folderNameText); + + // Folder description + var folderDesc = document.createElementNS(this.kmlns, "description"); + var folderDescText = document.createTextNode(this.foldersDesc); + folderDesc.appendChild(folderDescText); + + // Folder + var folder = document.createElementNS(this.kmlns, "Folder"); + folder.appendChild(folderName); + folder.appendChild(folderDesc); + + return folder; + }, + + /** + * Method: createPlacemarkXML + * Accept an OpenLayers.Feature.Vector, and create a KML Placemark node + * + * Parameters: + * feature - {<OpenLayers.Feature.Vector>} + * + * Returns: + * xmlNode - {<XMLNode>} + */ + createPlacemarkXML: function(feature) { + // Placemark name + var placemarkName = document.createElementNS(this.kmlns, "name"); + var placemarkNameText = document.createTextNode(feature.id); + placemarkName.appendChild(placemarkNameText); + + // Placemark description + var placemarkDesc = document.createElementNS(this.kmlns, "description"); + var placemarkDescText = document.createTextNode(this.placemarksDesc); + placemarkDesc.appendChild(placemarkDescText); + + // Placemark + var placemarkNode = document.createElementNS(this.kmlns, "Placemark"); + placemarkNode.appendChild(placemarkName); + placemarkNode.appendChild(placemarkDesc); + + // Geometry node (Point, LineString, etc. nodes) + var geometryNode = this.buildGeometryNode(feature.geometry); + placemarkNode.appendChild(geometryNode); + + return placemarkNode; + }, + + /** + * Method: buildGeometryNode + * Builds a KML geometry node with a given geometry + * + * Parameters: + * geometry - {<OpenLayers.Geometry>} + * + * Returns: + * xmlNode - {<XMLNode>} + */ + buildGeometryNode: function(geometry) { + // TBD test if geoserver can be given a Multi-geometry for a simple-geometry data store + // ie if multipolygon can be sent for a polygon feature type + var kml = ""; + // match MultiPolygon or Polygon + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon" + || geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { + kml = document.createElementNS(this.kmlns, 'Polygon'); + + var outerRing = document.createElementNS(this.kmlns, 'outerBoundaryIs'); + var linearRing = document.createElementNS(this.kmlns, 'LinearRing'); + + // TBD manage polygons with holes + linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0])); + outerRing.appendChild(linearRing); + + kml.appendChild(outerRing); + } + // match MultiLineString or LineString + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString" + || geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { + kml = document.createElementNS(this.kmlns, 'LineString'); + + kml.appendChild(this.buildCoordinatesNode(geometry)); + } + // match MultiPoint or Point + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" || + geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") { + kml = document.createElementNS(this.kmlns, 'Point'); + + // FIXME: There should be only one Point node per Placemark node + var parts = ""; + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") { + parts = geometry.components; + } else { + parts = [geometry]; + } + + for (var i = 0; i < parts.length; i++) { + kml.appendChild(this.buildCoordinatesNode(parts[i])); + } + } + return kml; + }, + /** + * Method: buildCoordinatesNode + * builds the KML coordinates node + * + * Parameters: + * geometry - {<OpenLayers.Geometry>} + * + * Returns: + * xmlNode - {<XMLNode>} + */ + buildCoordinatesNode: function(geometry) { + var coordinatesNode = document.createElementNS(this.kmlns, "coordinates"); + + var points = null; + if (geometry.components) { + points = geometry.components; + } + + var path = ""; + if (points) { + for (var i = 0; i < points.length; i++) { + path += points[i].x + "," + points[i].y + " "; + } + } else { + path += geometry.x + "," + geometry.y + " "; + } + + var txtNode = document.createTextNode(path); + coordinatesNode.appendChild(txtNode); + + return coordinatesNode; + }, + CLASS_NAME: "OpenLayers.Format.KML" }); Tim Schaub wrote: [patch stripped]Hi- So, we're mid-way through changing how XML flavors are read/written in OpenLayers. I've checked a new XML format in to the trunk. This format has most of the methods we need for reading/writing XML cross-browser. To parse other XML flavors, format classes should be created that inherit from the XML format. For an (incomplete) example, see: http://dev.openlayers.org/sandbox/tschaub/xml/lib/OpenLayers/Format/GML.js (The important part to notice in the above example is that the GML format inherits from the XML format.) Instead of using OpenLayers.Ajax methods or document methods, DOM creation and traversal should be done with OpenLayers.Format.XML methods. I've created methods to reflect the W3C standard XML DOM methods - wrapping the standard ones and accommodating for non-compliant browsers. If you (or anyone) needs additional XML DOM methods, they should be added to the XML format. The next addition (in my mind) is setAttributeNS. Aside from that, you should be able to do efficient parsing and dom creation with the XML format methods. Please make modifications to the KML format in the trunk. Create a ticket and attach patches in Trac. I can offer review or other help as needed. I don't have time to keep these sandboxes entirely clean right now - so please forgive anything you find that is in a half-developed state. Tim PS - Eventually, I'll move the following example into the trunk. It would be nice if we could demonstrate read/write capability for all vector formats in this way: http://dev.openlayers.org/sandbox/tschaub/xml/examples/vector-formats.html (note again that this reflects partially complete work - and you should not be surprised to encounter errors or see changes at any time) Damien Corpataux wrote: --
Camptocamp SA
Damien Corpataux PSE A CH-1015 Lausanne +41 21 619 10 22 (Direct)
+41 21 619 10 10 (Centrale) +41 21 619 10 00 (Fax) P
Please consider the environment
Do you really need to print this email? _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write()I've opened ticket #927 to track this.
If anybody has a patch for KML, please attach it to that ticket. Damien, I've referenced your email on the ticket. Since XML flavors should now all inherit from the XML format class, I'd say that write will always return a string. Thanks for any contributions. Tim Damien Corpataux wrote: > Hello, > > As far as I can see, the advantages of doing so are obvious. Althought I > didn't have time to apply these, here is a new version of the patch: > - puts placemarks in a folder tag (for google earth import) > - bugfix with geometry tags > > Is the question about write() return type (string or DOMDocuemt/DOMNode) > still open? > > Cheers, > Damien > > > Patch: > Index: /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > =================================================================== > --- > /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > (revision 3900) > +++ > /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js > (working copy) > @@ -8,8 +8,8 @@ > * @requires OpenLayers/Ajax.js > * > * Class: OpenLayers.Format.KML > - * Read only KML. Largely Proof of Concept: does not support advanced > Features, > - * including Polygons. Create a new instance with the > + * Read/write KML 2.0. Does not support advanced Features. > + * Create a new instance with the > * <OpenLayers.Format.KML> constructor. > * > * Inherits from: > @@ -24,6 +24,24 @@ > kmlns: "http://earth.google.com/kml/2.0", > > /** > + * APIProperty: placemarksDesc > + * Default description for a placemark > + */ > + placemarksDesc: "No description available", > + > + /** > + * APIProperty: foldersName > + * Default name for a folder > + */ > + foldersName: "OpenLayers export", > + > + /** > + * APIProperty: foldersDesc > + * Default description for a folder > + */ > + foldersDesc: "Exported on " + new Date(), > + > + /** > * Constructor: OpenLayers.Format.KML > * Create a new parser for KML > * > @@ -46,7 +64,7 @@ > if (typeof data == "string") { > data = OpenLayers.parseXMLString(data); > } > - var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, > this.kmlns, "", "Placemark"); > + var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, > this.kmlns, "kml", "Placemark"); > > var features = []; > > @@ -100,6 +118,19 @@ > // TBD Bounds only set for one of multiple geometries > geom.extendBounds(p.bounds); > } > + > + // match Polygon > + } else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, > + this.kmlns, "", "Polygon").length != 0) { > + var polygon = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, > + this.kmlns, "", "Polygon")[0]; > + p = this.parseCoords(polygon); > + if (p.points) { > + var linearRing = new > OpenLayers.Geometry.LinearRing(p.points); > + geom = new OpenLayers.Geometry.Polygon(linearRing); > + // TBD Bounds only set for one of multiple geometries > + geom.extendBounds(p.bounds); > + } > } > > feature.geometry = geom; > @@ -191,5 +222,171 @@ > return p; > }, > > + /** > + * Method: write > + * Accept Feature Collection, and return an XML Document. > + * > + * Parameters: > + * features - An array of <OpenLayers.Feature.Vector> features. > + * > + * Returns: > + * <DOMDocument> > + */ > + write: function(features) { > + var kml = document.createElementNS(this.kmlns, "kml"); > + var folder = this.createFolderXML(); > + for (var i=0; i < features.length; i++) { > + folder.appendChild(this.createPlacemarkXML(features[i])); > + } > + kml.appendChild(folder); > + return kml; > + }, > + > + /** > + * Method: createFolderXML > + * Creates and returns a KML Folder node with default name and > description > + * > + * Returns: > + * xmlNode - {<XMLNode>} > + */ > + createFolderXML: function() { > + // Folder name > + var folderName = document.createElementNS(this.kmlns, "name"); > + var folderNameText = document.createTextNode(this.foldersName); > + folderName.appendChild(folderNameText); > + > + // Folder description > + var folderDesc = document.createElementNS(this.kmlns, > "description"); > + var folderDescText = document.createTextNode(this.foldersDesc); > + folderDesc.appendChild(folderDescText); > + > + // Folder > + var folder = document.createElementNS(this.kmlns, "Folder"); > + folder.appendChild(folderName); > + folder.appendChild(folderDesc); > + > + return folder; > + }, > + > + /** > + * Method: createPlacemarkXML > + * Accept an OpenLayers.Feature.Vector, and create a KML Placemark node > + * > + * Parameters: > + * feature - {<OpenLayers.Feature.Vector>} > + * > + * Returns: > + * xmlNode - {<XMLNode>} > + */ > + createPlacemarkXML: function(feature) { > + // Placemark name > + var placemarkName = document.createElementNS(this.kmlns, "name"); > + var placemarkNameText = document.createTextNode(feature.id); > + placemarkName.appendChild(placemarkNameText); > + > + // Placemark description > + var placemarkDesc = document.createElementNS(this.kmlns, > "description"); > + var placemarkDescText = > document.createTextNode(this.placemarksDesc); > + placemarkDesc.appendChild(placemarkDescText); > + > + // Placemark > + var placemarkNode = document.createElementNS(this.kmlns, > "Placemark"); > + placemarkNode.appendChild(placemarkName); > + placemarkNode.appendChild(placemarkDesc); > + > + // Geometry node (Point, LineString, etc. nodes) > + var geometryNode = this.buildGeometryNode(feature.geometry); > + placemarkNode.appendChild(geometryNode); > + > + return placemarkNode; > + }, > + > + /** > + * Method: buildGeometryNode > + * Builds a KML geometry node with a given geometry > + * > + * Parameters: > + * geometry - {<OpenLayers.Geometry>} > + * > + * Returns: > + * xmlNode - {<XMLNode>} > + */ > + buildGeometryNode: function(geometry) { > + // TBD test if geoserver can be given a Multi-geometry for a > simple-geometry data store > + // ie if multipolygon can be sent for a polygon feature type > + var kml = ""; > + // match MultiPolygon or Polygon > + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon" > + || geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { > + kml = document.createElementNS(this.kmlns, 'Polygon'); > + > + var outerRing = document.createElementNS(this.kmlns, > 'outerBoundaryIs'); > + var linearRing = document.createElementNS(this.kmlns, > 'LinearRing'); > + > + // TBD manage polygons with holes > + > linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0])); > + outerRing.appendChild(linearRing); > + > + kml.appendChild(outerRing); > + } > + // match MultiLineString or LineString > + else if (geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiLineString" > + || geometry.CLASS_NAME == > "OpenLayers.Geometry.LineString") { > + kml = document.createElementNS(this.kmlns, > 'LineString'); > + > + kml.appendChild(this.buildCoordinatesNode(geometry)); > + } > + // match MultiPoint or Point > + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" || > + geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiPoint") { > + kml = document.createElementNS(this.kmlns, 'Point'); > + > + // FIXME: There should be only one Point node per > Placemark node > + var parts = ""; > + if (geometry.CLASS_NAME == > "OpenLayers.Geometry.MultiPoint") { > + parts = geometry.components; > + } else { > + parts = [geometry]; > + } > + > + for (var i = 0; i < parts.length; i++) { > + kml.appendChild(this.buildCoordinatesNode(parts[i])); > + } > + } > + return kml; > + }, > + /** > + * Method: buildCoordinatesNode > + * builds the KML coordinates node > + * > + * Parameters: > + * geometry - {<OpenLayers.Geometry>} > + * > + * Returns: > + * xmlNode - {<XMLNode>} > + */ > + buildCoordinatesNode: function(geometry) { > + var coordinatesNode = document.createElementNS(this.kmlns, > "coordinates"); > + > + var points = null; > + if (geometry.components) { > + points = geometry.components; > + } > + > + var path = ""; > + if (points) { > + for (var i = 0; i < points.length; i++) { > + path += points[i].x + "," + points[i].y + " "; > + } > + } else { > + path += geometry.x + "," + geometry.y + " "; > + } > + > + var txtNode = document.createTextNode(path); > + coordinatesNode.appendChild(txtNode); > + > + return coordinatesNode; > + }, > + > CLASS_NAME: "OpenLayers.Format.KML" > }); > > > Tim Schaub wrote: >> Hi- >> >> So, we're mid-way through changing how XML flavors are read/written in >> OpenLayers. >> >> I've checked a new XML format in to the trunk. This format has most of >> the methods we need for reading/writing XML cross-browser. >> >> To parse other XML flavors, format classes should be created that >> inherit from the XML format. >> >> For an (incomplete) example, see: >> http://dev.openlayers.org/sandbox/tschaub/xml/lib/OpenLayers/Format/GML.js >> >> (The important part to notice in the above example is that the GML >> format inherits from the XML format.) >> >> Instead of using OpenLayers.Ajax methods or document methods, DOM >> creation and traversal should be done with OpenLayers.Format.XML >> methods. I've created methods to reflect the W3C standard XML DOM >> methods - wrapping the standard ones and accommodating for non-compliant >> browsers. >> >> If you (or anyone) needs additional XML DOM methods, they should be >> added to the XML format. The next addition (in my mind) is >> setAttributeNS. Aside from that, you should be able to do efficient >> parsing and dom creation with the XML format methods. >> >> Please make modifications to the KML format in the trunk. Create a >> ticket and attach patches in Trac. I can offer review or other help as >> needed. >> >> I don't have time to keep these sandboxes entirely clean right now - so >> please forgive anything you find that is in a half-developed state. >> >> Tim >> >> PS - Eventually, I'll move the following example into the trunk. It >> would be nice if we could demonstrate read/write capability for all >> vector formats in this way: >> http://dev.openlayers.org/sandbox/tschaub/xml/examples/vector-formats.html >> >> (note again that this reflects partially complete work - and you should >> not be surprised to encounter errors or see changes at any time) >> >> >> Damien Corpataux wrote: >> >>> Hello, >>> >>> Here's what I did so far... Reading KML only work for KML 2.0 namespaces >>> for write() uses OpenLayers.Ajax.getElementsByTagNameNS(), but I'm >>> pretty sure it will work on future versions (2.1 parsing successful). >>> Also, GML and KML write() returns a Dom Document rather than a string. >>> Should one change the result type, breaking OpenLayers.Format interface, >>> or parse it into a string using OpenLayers.XML.....? >>> >>> Cheers, >>> Damien >>> >>> > [patch stripped] > > -- > Camptocamp SA > Damien Corpataux > PSE A > CH-1015 Lausanne > +41 21 619 10 22 (Direct) > +41 21 619 10 10 (Centrale) > +41 21 619 10 00 (Fax) > P Please consider the environment > Do you really need to print this email? > !DSPAM:4033,46cd662e41812090977483! > > > ------------------------------------------------------------------------ > > _______________________________________________ > Dev mailing list > Dev@... > http://openlayers.org/mailman/listinfo/dev > > > !DSPAM:4033,46cd662e41812090977483! _______________________________________________ Dev mailing list Dev@... http://openlayers.org/mailman/listinfo/dev |
|
|
Re: OpenLayers.Format.KML.write() |