Skip to content

Commit

Permalink
feat: add iconScale extended metadata in KML (#711)
Browse files Browse the repository at this point in the history
* fix: fiy the automatic scaling calculation of google earth

* chore(release): 1.7.2-beta.0

* feat: fix kml reading

* chore(release): 1.8.0-beta.0

* build: use engines feld in package.json

* build: use engines feld in package.json

* build: remove engines
  • Loading branch information
oterral authored Dec 7, 2023
1 parent 1a7afe2 commit 1b8f2f8
Show file tree
Hide file tree
Showing 9 changed files with 1,314 additions and 687 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
44 changes: 22 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
"name": "react-spatial",
"license": "MIT",
"description": "Components to build React map apps.",
"version": "1.7.1",
"version": "1.8.0-beta.0",
"dependencies": {
"@geops/geops-ui": "0.1.18",
"@material-ui/core": "4.12.4",
"@material-ui/icons": "4.11.3",
"@material-ui/lab": "4.0.0-alpha.61",
"re-resizable": "6.9.11",
"react-icons": "4.11.0",
"react-icons": "4.12.0",
"resize-observer-polyfill": "1.5.1"
},
"peerDependencies": {
Expand All @@ -21,28 +21,28 @@
"react-dom": "^18"
},
"devDependencies": {
"@babel/preset-env": "7.23.2",
"@babel/preset-react": "7.22.15",
"@babel/preset-env": "7.23.5",
"@babel/preset-react": "7.23.3",
"@cfaester/enzyme-adapter-react-18": "0.7.1",
"@commitlint/cli": "18.1.0",
"@commitlint/config-conventional": "18.1.0",
"@commitlint/cli": "18.4.3",
"@commitlint/config-conventional": "18.4.3",
"@svgr/plugin-jsx": "^8.1.0",
"@svgr/webpack": "8.1.0",
"@testing-library/jest-dom": "6.1.4",
"@testing-library/react": "14.0.0",
"@testing-library/jest-dom": "6.1.5",
"@testing-library/react": "14.1.2",
"@testing-library/user-event": "14.5.1",
"babel-jest": "29.7.0",
"babel-loader": "9.1.3",
"canvas": "2.11.2",
"css-loader": "6.8.1",
"enzyme": "3.11.0",
"esbuild": "^0.19.5",
"esbuild": "^0.19.8",
"esbuild-loader": "^4.0.2",
"eslint": "8.52.0",
"eslint": "8.55.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "9.0.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-jsx-a11y": "6.7.1",
"eslint-plugin-jsx-a11y": "6.8.0",
"eslint-plugin-prettier": "5.0.1",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
Expand All @@ -61,29 +61,29 @@
"jest-transform-file": "1.1.1",
"jest-transformer-svg": "^2.0.1",
"jsts": "2.11.0",
"lint-staged": "15.0.2",
"lint-staged": "15.2.0",
"mapbox-gl": "1.13.1",
"maplibre-gl": "3.5.2",
"mobility-toolbox-js": "2.2.1",
"ol": "8.1.0",
"postcss": "^8.4.31",
"prettier": "3.0.3",
"maplibre-gl": "3.6.2",
"mobility-toolbox-js": "2.3.7",
"ol": "8.2.0",
"postcss": "^8.4.32",
"prettier": "3.1.0",
"proj4": "2.9.2",
"prop-types": "15.8.1",
"react": "18",
"react-dom": "18",
"react-styleguidist": "13.1.1",
"react-svg-loader": "3.0.3",
"react-test-renderer": "18.2.0",
"sass": "1.69.4",
"sass": "1.69.5",
"sass-loader": "13.3.2",
"standard-version": "9.5.0",
"stream-array": "1.1.2",
"style-loader": "3.3.3",
"stylelint": "15.11.0",
"stylelint-config-recommended-scss": "13.0.0",
"stylelint-config-recommended-scss": "13.1.0",
"stylelint-config-standard": "34.0.0",
"stylelint-scss": "5.2.1",
"stylelint-scss": "5.3.1",
"terser-webpack-plugin": "^5.3.9",
"url-loader": "4.1.1",
"vinyl-fs": "4.0.0",
Expand Down Expand Up @@ -166,7 +166,7 @@
".+\\.svg$": "jest-transformer-svg"
},
"transformIgnorePatterns": [
"node_modules/(?!(jsts|ol|mobility-toolbox-js)|@geops|geotiff|quick-lru)"
"node_modules/(?!(color-*|jsts|ol|mobility-toolbox-js)|@geops|geotiff|quick-lru)"
],
"testMatch": [
"<rootDir>/src/**/?(*.)+(spec|test).[jt]s?(x)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ exports[`FeatureExportButton triggers onClick #createFeatureString() using KMLFo
</Icon>
</IconStyle>
</Style>
<ExtendedData>
<Data name="iconScale">
<value>
1
</value>
</Data>
</ExtendedData>
<Point>
<coordinates>
7.358136177061042,48.07903229472336
Expand Down
2 changes: 1 addition & 1 deletion src/components/MousePosition/MousePosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function MousePosition({
useEffect(() => {
const mousePosition = new OLMousePosition({
target: ref.current,
undefinedHTML: "&nbsp;",
placeholder: "&nbsp;",
className: "",
});
map.addControl(mousePosition);
Expand Down
46 changes: 42 additions & 4 deletions src/utils/KML.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ import GeometryCollection from "ol/geom/GeometryCollection";
import { Style, Text, Icon, Circle, Fill, Stroke } from "ol/style";
import { asString } from "ol/color";
import { parse } from "ol/xml";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import { kmlStyle } from "./Styles";
import getPolygonPattern from "./getPolygonPattern";

// Comes from ol >= 6.7,
// https://github.com/openlayers/openlayers/blob/main/src/ol/format/KML.js#L320
const scaleForSize = (size) => {
return 32 / Math.min(size[0], size[1]);
};

const applyTextStyleForIcon = (olIcon, olText) => {
const size = olIcon.getSize() || [48, 48];
const scale = olIcon.getScale() || 1;
Expand Down Expand Up @@ -57,7 +65,7 @@ const getLineIcon = (feature, icon, color, start = true) => {
};

// Clean the unneeded feature's style and properties created by the KML parser.
const sanitizeFeature = (feature) => {
const sanitizeFeature = (feature, doNotRevert32pxScaling = false) => {
const geom = feature.getGeometry();
let styles = feature.getStyleFunction();

Expand Down Expand Up @@ -184,7 +192,6 @@ const sanitizeFeature = (feature) => {
}),
);
}

if (image instanceof Icon) {
applyTextStyleForIcon(image, text);
}
Expand All @@ -195,6 +202,15 @@ const sanitizeFeature = (feature) => {
* <heading> tag, which is not read as rotation value by the ol KML module)
*/
image.setRotation(parseFloat(feature.get("iconRotation")) || 0);

if (feature.get("iconScale")) {
image.setScale(parseFloat(feature.get("iconScale")) || 0);

// We fix the 32px scaling introduced by OL 6.7
} else if (!doNotRevert32pxScaling) {
const resizeScale = scaleForSize(image.getSize());
image.setScale(image.getScaleArray()[0] / resizeScale);
}
}

fill = undefined;
Expand Down Expand Up @@ -295,13 +311,23 @@ const sanitizeFeature = (feature) => {
* Read a KML string.
* @param {String} kmlString A string representing a KML file.
* @param {<ol.Projection|String>} featureProjection The projection used by the map.
* @param {<boolean>} doNotRevert32pxScaling Set it to true if you use ol < 6.7 and last version of react-spatial, Fix the 32px scaling, introduced by (ol >= 6.7), see https://github.com/openlayers/openlayers/pull/12695.
*/
const readFeatures = (kmlString, featureProjection) => {
const readFeatures = (
kmlString,
featureProjection,
doNotRevert32pxScaling = false,
) => {
// Since ol 6.7, the KML follows better the spec and GoogleEarth interpretation, see https://github.com/openlayers/openlayers/pull/12695.
// so the <scale> value is interpreted using an image size of 32px.
// So when revert32pxScaling is true we fix back the scale, to use only, if you use an OL < 6.7.
// Now the writeFeatures function use the iconScale extended data to set the image's scale.
// If the extended data is not found it will look at this boolean to define if we must revert the scale or not.
const features = new KML().readFeatures(kmlString, {
featureProjection,
});
features.forEach((feature) => {
sanitizeFeature(feature);
sanitizeFeature(feature, doNotRevert32pxScaling);
});
return features;
};
Expand All @@ -310,6 +336,7 @@ const readFeatures = (kmlString, featureProjection) => {
* Create a KML string.
* @param {VectorLayer} layer A react-spatial VectorLayer.
* @param {<ol.Projection|String>} featureProjection The current projection used by the features.
* @param {<boolean>} fixGxyAndGxh If the KML contains gx:w and gx:h, (ol >= 6.7), it will fix the bug introduced by https://github.com/openlayers/openlayers/pull/12695.
*/
const writeFeatures = (layer, featureProjection, mapResolution) => {
let featString;
Expand Down Expand Up @@ -431,6 +458,11 @@ const writeFeatures = (layer, featureProjection, mapResolution) => {
clone.set("iconRotation", newStyle.image.getRotation());
}

if (newStyle.image.getScale()) {
// We set the scale as extended metadata because the <scale> in the KML is related to a 32px img, since ol >= 6.10.
clone.set("iconScale", newStyle.image.getScale());
}

// Set map resolution to use for icon-to-map proportional scaling
if (feature.get("pictureOptions")) {
clone.set(
Expand Down Expand Up @@ -586,6 +618,12 @@ const writeDocumentCamera = (kmlString, cameraAttributes) => {
return new XMLSerializer().serializeToString(kmlDoc);
};

window.VectorLayer = VectorLayer;
window.VectorSource = VectorSource;

window.writeFeatures = writeFeatures;
window.readFeatures = readFeatures;

export default {
readFeatures,
writeFeatures,
Expand Down
Loading

1 comment on commit 1b8f2f8

@vercel
Copy link

@vercel vercel bot commented on 1b8f2f8 Dec 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.