您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
geoKMLer is a JavaScript library designed to convert KML data into GeoJSON format efficiently. It supports conversion of Placemarks containing Point, LineString, Polygon, and MultiGeometry elements.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/524747/1542062/GeoKMLer.js
// ==UserScript== // @name GeoKMLer // @namespace https://github.com/JS55CT // @description geoKMLer is a JavaScript library designed to convert KML data into GeoJSON format efficiently. It supports conversion of Placemarks containing Point, LineString, Polygon, and MultiGeometry elements. // @version 2.2.0 // @author JS55CT // @license MIT // @match *://this-library-is-not-supposed-to-run.com/* // ==/UserScript== /*********************************************************** * ## Project Home < https://github.com/JS55CT/GeoKMLer > * MIT License * Copyright (c) 2025 Justin * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. **************************************************************/ var GeoKMLer = (function () { /** * GeoKMLer constructor function. * @param {Object} obj - Optional object to wrap. * @returns {GeoKMLer} - An instance of GeoKMLer. */ function GeoKMLer(obj) { if (obj instanceof GeoKMLer) return obj; if (!(this instanceof GeoKMLer)) return new GeoKMLer(obj); this._wrapped = obj; } /** * Parses a KML string into an XML DOM. * @param {string} kmlText - The KML text to parse. * @returns {Document} - The parsed XML document. */ GeoKMLer.prototype.read = function (kmlText) { const parser = new DOMParser(); const xmlDoc = parser.parseFromString(kmlText, "application/xml"); // Check for parsing errors by looking for parser error tags const parseErrors = xmlDoc.getElementsByTagName("parsererror"); if (parseErrors.length > 0) { // If there are parsing errors, log them and throw an error const errorMessages = Array.from(parseErrors) .map((errorElement, index) => { return `Parsing Error ${index + 1}: ${errorElement.textContent}`; }) .join("\n"); console.error(errorMessages); // Throw an error to indicate parsing failure throw new Error("Failed to parse KML. See console for details."); } // If parsing is successful, return the parsed XML document return xmlDoc; }; /** * Converts a KML document to a GeoJSON FeatureCollection. * @param {Document} document - The KML document to convert. * @param {boolean} includeCrs - Optional boolean to determine if CRS should be included. * @returns {Object} - The resulting GeoJSON FeatureCollection. * * NOTE: * KML files inherently assume the use of the EPSG:4326 (WGS 84) coordinate reference system * for all geographic coordinates. As such, when converting from KML to GeoJSON, the coordinates * are retained in the standard WGS 84 format. * * The GeoJSON output will conform to this CRS standard, and no additional CRS transformation are needed. * Users can rely on the spatial information being accurate with respect to the WGS 84 datum. * * Additionally, this function includes an option to add CRS information explicitly to the GeoJSON output (none standard). * By setting the `includeCrs` parameter to `true`, the resulting GeoJSON will include a 'crs' property * that specifies the use of EPSG:4326: the geoJSON standard. * * crs: { * type: "name", * properties: { * name: "EPSG:4326", * }, * } */ GeoKMLer.prototype.toGeoJSON = function (document, includeCrs = false) { const features = []; for (const placemark of document.getElementsByTagName("Placemark")) { features.push(...this.handlePlacemark(placemark)); } const geoJson = { type: "FeatureCollection", features: features, }; if (includeCrs) { geoJson.crs = { type: "name", properties: { name: "EPSG:4326", }, }; } return geoJson; }; /** * Processes a KML Placemark and converts its geometries to GeoJSON features. * @param {Element} placemark - The Placemark element to process. * @returns {Array} - An array of GeoJSON features. */ GeoKMLer.prototype.handlePlacemark = function (placemark) { const features = []; const properties = this.extractProperties(placemark); // Merge extended data directly into the properties without an additional 'ExtendedData' entry Object.assign(properties, this.extractExtendedData(placemark)); for (let i = 0; i < placemark.children.length; i++) { const element = placemark.children[i]; switch (element.tagName) { case "Point": features.push(this.pointToPoint(element, placemark, properties)); break; case "LineString": features.push(this.lineStringToLineString(element, placemark, properties)); break; case "Polygon": features.push(this.polygonToPolygon(element, placemark, properties)); break; case "MultiGeometry": features.push(...this.handleMultiGeometry(element, placemark, properties)); break; } } return features; }; /** * Converts coordinate strings into arrays of [longitude, latitude]. * @param {string} coordString - The coordinate string from KML. * @returns {Array} - An array of [longitude, latitude] pairs. */ GeoKMLer.prototype.coordFromString = function(coordString) { return coordString.trim().split(/\s+/).map(coord => { const [lon, lat, ele] = coord.split(',').map(parseFloat); return [lon, lat, ele]; // Include ele for elevation }); }; /** * Parses a single coordinate string into a numeric array. * @param {string} v - The coordinate string. * @returns {Array} - An array of parsed coordinate values. */ GeoKMLer.prototype.coord1 = function (v) { const removeSpace = /\s*/g; return v.replace(removeSpace, "").split(",").map(parseFloat); }; /** * Parses multiple coordinate strings into an array of coordinate arrays. * @param {string} v - The coordinate string with multiple coordinates. * @returns {Array} - A nested array of parsed coordinate values. */ GeoKMLer.prototype.coord = function (v) { const trimSpace = /^\s*|\s*$/g; const splitSpace = /\s+/; const coords = v.replace(trimSpace, "").split(splitSpace); return coords.map((coord) => this.coord1(coord)); }; /** * Extracts extended data from a KML placemark. * @param {Element} placemark - The Placemark element to extract from. * @returns {Object} - An object containing extended data properties. */ GeoKMLer.prototype.extractExtendedData = function (placemark) { const extendedData = {}; const extendedDataTag = this.getChildNode(placemark, "ExtendedData"); if (!extendedDataTag) return extendedData; const simpleDatas = this.getChildNodes(extendedDataTag, "SimpleData"); simpleDatas.forEach((data) => { const name = data.getAttribute("name"); const value = this.nodeVal(data); if (name && value !== null) { extendedData[`ex_${name}`] = value.trim(); } }); return extendedData; }; /** * Fetches the value of a text node. * @param {Node} x - The node to extract the value from. * @returns {string} - The text content of the node. */ GeoKMLer.prototype.nodeVal = function (x) { return x ? x.textContent || "" : ""; }; /** * Retrieves a single child node of a specified tag name. * @param {Element} x - The parent element. * @param {string} y - The tag name of the child node. * @returns {Element|null} - The first matching child node or null if none are found. */ GeoKMLer.prototype.getChildNode = function (x, y) { const nodeList = x.getElementsByTagName(y); return nodeList.length ? nodeList[0] : null; }; /** * Retrieves all child nodes of a specified tag name. * @param {Element} x - The parent element. * @param {string} y - The tag name of the child nodes. * @returns {Array} - An array of matching child nodes. */ GeoKMLer.prototype.getChildNodes = function (x, y) { return Array.from(x.getElementsByTagName(y)); }; /** * Retrieves an attribute value from an element. * @param {Element} x - The element to extract the attribute from. * @param {string} y - The name of the attribute. * @returns {string|null} - The attribute value or null if not present. */ GeoKMLer.prototype.attr = function (x, y) { return x.getAttribute(y); }; /** * Retrieves a floating-point attribute value from an element. * @param {Element} x - The element to extract the attribute from. * @param {string} y - The name of the attribute. * @returns {number} - The parsed floating-point attribute value. */ GeoKMLer.prototype.attrf = function (x, y) { return parseFloat(this.attr(x, y)); }; /** * Normalizes an XML node to combine adjacent text nodes. * @param {Node} el - The XML node to normalize. * @returns {Node} - The normalized node. */ GeoKMLer.prototype.norm = function (el) { if (el.normalize) el.normalize(); return el; }; /** * Creates a GeoJSON feature for a given geometry type and coordinates. * @param {string} type - The geometry type (Point, LineString, Polygon). * @param {Array} coords - The coordinates for the geometry. * @param {Object} props - The properties of the feature. * @returns {Object} - The created GeoJSON feature. */ GeoKMLer.prototype.makeFeature = function (type, coords, props) { return { type: "Feature", geometry: { type: type, coordinates: coords, }, properties: props, }; }; /** * Converts a KML Point to a GeoJSON Point feature. * @param {Element} node - The Point element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON Point feature. */ GeoKMLer.prototype.pointToPoint = function (node, placemark, props) { const coord = this.coordFromString(node.getElementsByTagName("coordinates")[0].textContent)[0]; return this.makeFeature("Point", coord, props); }; /** * Converts a KML LineString to a GeoJSON LineString feature. * @param {Element} node - The LineString element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON LineString feature. */ GeoKMLer.prototype.lineStringToLineString = function (node, placemark, props) { const coords = this.coordFromString(node.getElementsByTagName("coordinates")[0].textContent); return this.makeFeature("LineString", coords, props); }; /** * Converts a KML Polygon to a GeoJSON Polygon feature. * @param {Element} node - The Polygon element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON Polygon feature. */ GeoKMLer.prototype.polygonToPolygon = function (node, placemark, props) { const coords = []; for (const boundary of node.getElementsByTagName("LinearRing")) { coords.push(this.coordFromString(boundary.getElementsByTagName("coordinates")[0].textContent)); } return this.makeFeature("Polygon", coords, props); }; /** * Processes a MultiGeometry and converts its geometries to GeoJSON features. * @param {Element} node - The MultiGeometry element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the features. * @returns {Array} - An array of GeoJSON features. */ GeoKMLer.prototype.handleMultiGeometry = function (node, placemark, props) { const features = []; for (const element of node.children) { switch (element.tagName) { case "Point": features.push(this.pointToPoint(element, placemark, props)); break; case "LineString": features.push(this.lineStringToLineString(element, placemark, props)); break; case "Polygon": features.push(this.polygonToPolygon(element, placemark, props)); break; case "MultiGeometry": features.push(...this.handleMultiGeometry(element, placemark, props)); break; } } return features; }; /** * Extracts properties from a Placemark, excluding geometry elements. * @param {Element} placemark - The Placemark element to extract properties from. * @returns {Object} - An object containing placemark properties. */ GeoKMLer.prototype.extractProperties = function (placemark) { const props = {}; for (const n of placemark.children) { if (!["Point", "LineString", "Polygon", "MultiGeometry", "LinearRing", "style", "styleMap", "styleUrl", "TimeSpan", "TimeStamp"].includes(n.tagName)) { // Ensure "ExtendedData" is not added directly. if (n.tagName !== "ExtendedData") { props[n.tagName] = n.textContent.trim(); } } } return props; }; return GeoKMLer; })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址