|
@@ -19,8 +19,10 @@ import Select from "ol/interaction/Select";
|
|
|
import { singleClick } from "ol/events/condition";
|
|
import { singleClick } from "ol/events/condition";
|
|
|
import { reactive } from "vue";
|
|
import { reactive } from "vue";
|
|
|
import WKT from "ol/format/WKT.js";
|
|
import WKT from "ol/format/WKT.js";
|
|
|
|
|
+import GeoJSON from "ol/format/GeoJSON";
|
|
|
import * as proj from "ol/proj";
|
|
import * as proj from "ol/proj";
|
|
|
import { getArea } from "ol/sphere.js";
|
|
import { getArea } from "ol/sphere.js";
|
|
|
|
|
+import * as turf from "@turf/turf";
|
|
|
|
|
|
|
|
const VIEWPORT_INTERACTION_TYPES = [
|
|
const VIEWPORT_INTERACTION_TYPES = [
|
|
|
DragPan,
|
|
DragPan,
|
|
@@ -64,6 +66,12 @@ class MapManage {
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
+ this.boundaryLayer = new KMap.VectorLayer("drawBoundaryLayer", 1050, {
|
|
|
|
|
+ style: () => this.createBoundaryStyle(),
|
|
|
|
|
+ });
|
|
|
|
|
+ this.boundaryGeometry = null;
|
|
|
|
|
+ this.constrainedDrawing = false;
|
|
|
|
|
+ this.constrainedDrawingReady = false;
|
|
|
this.gridLayer = new KMap.VectorLayer("terrainGridLayer", 1100, {
|
|
this.gridLayer = new KMap.VectorLayer("terrainGridLayer", 1100, {
|
|
|
style: (feature) => {
|
|
style: (feature) => {
|
|
|
const selected = !!feature.get("selected");
|
|
const selected = !!feature.get("selected");
|
|
@@ -97,24 +105,172 @@ class MapManage {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ createBoundaryStyle() {
|
|
|
|
|
+ return new Style({
|
|
|
|
|
+ fill: new Fill({
|
|
|
|
|
+ color: "rgba(124, 124, 124, 0.12)",
|
|
|
|
|
+ }),
|
|
|
|
|
+ stroke: new Stroke({
|
|
|
|
|
+ color: "rgba(255, 255, 255, 0.85)",
|
|
|
|
|
+ width: 2,
|
|
|
|
|
+ lineDash: [8, 4],
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ createDrawnPestStyle() {
|
|
|
|
|
+ return new Style({
|
|
|
|
|
+ fill: new Fill({
|
|
|
|
|
+ color: "rgba(100, 0, 0, 0.45)",
|
|
|
|
|
+ }),
|
|
|
|
|
+ stroke: new Stroke({
|
|
|
|
|
+ color: "#E03131",
|
|
|
|
|
+ width: 1.8,
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
initMap(location, target, options = {}) {
|
|
initMap(location, target, options = {}) {
|
|
|
- const { editable = true } = options;
|
|
|
|
|
|
|
+ const { editable = true, constrainedDrawing = false } = options;
|
|
|
this.editable = editable;
|
|
this.editable = editable;
|
|
|
|
|
+ this.constrainedDrawing = constrainedDrawing;
|
|
|
|
|
+ this.constrainedDrawingReady = false;
|
|
|
|
|
+ this.boundaryGeometry = null;
|
|
|
let level = 16;
|
|
let level = 16;
|
|
|
let coordinate = util.wktCastGeom(location).getFirstCoordinate();
|
|
let coordinate = util.wktCastGeom(location).getFirstCoordinate();
|
|
|
this.kmap = new KMap.Map(target, level, coordinate[0], coordinate[1], null, 8, 22);
|
|
this.kmap = new KMap.Map(target, level, coordinate[0], coordinate[1], null, 8, 22);
|
|
|
let xyz2 = config.base_img_url3 + "map/lby/{z}/{x}/{y}.png";
|
|
let xyz2 = config.base_img_url3 + "map/lby/{z}/{x}/{y}.png";
|
|
|
this.kmap.addXYZLayer(xyz2, { minZoom: 8, maxZoom: 22 }, 2);
|
|
this.kmap.addXYZLayer(xyz2, { minZoom: 8, maxZoom: 22 }, 2);
|
|
|
// this.kmap.addLayer(this.clickPointLayer.layer);
|
|
// this.kmap.addLayer(this.clickPointLayer.layer);
|
|
|
|
|
+ this.kmap.addLayer(this.boundaryLayer.layer);
|
|
|
this.kmap.addLayer(this.gridLayer.layer);
|
|
this.kmap.addLayer(this.gridLayer.layer);
|
|
|
|
|
|
|
|
if (this.editable) {
|
|
if (this.editable) {
|
|
|
this.kmap.initDraw(() => {});
|
|
this.kmap.initDraw(() => {});
|
|
|
this.kmap.modifyDraw();
|
|
this.kmap.modifyDraw();
|
|
|
this.setRegionDrawingActive(false);
|
|
this.setRegionDrawingActive(false);
|
|
|
|
|
+ } else if (this.constrainedDrawing) {
|
|
|
|
|
+ this.setupConstrainedDrawing();
|
|
|
|
|
+ this.setConstrainedDrawingActive(false);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ setupConstrainedDrawing() {
|
|
|
|
|
+ if (!this.kmap || this.constrainedDrawingReady) return;
|
|
|
|
|
+ this.constrainedDrawingReady = true;
|
|
|
|
|
+ this.kmap.initDraw((e) => {
|
|
|
|
|
+ if (e.feature) {
|
|
|
|
|
+ this.clipFeatureToBoundary(e.feature);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ this.kmap.modifyDraw((e) => {
|
|
|
|
|
+ e.features.forEach((feature) => this.clipFeatureToBoundary(feature));
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setConstrainedDrawingActive(active) {
|
|
|
|
|
+ if (!this.kmap) return;
|
|
|
|
|
+ if (this.kmap.draw) {
|
|
|
|
|
+ this.kmap.draw.setActive(active);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.kmap.modify) {
|
|
|
|
|
+ this.kmap.modify.setActive(active);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ enableConstrainedDrawing() {
|
|
|
|
|
+ if (!this.boundaryGeometry) return;
|
|
|
|
|
+ this.setupConstrainedDrawing();
|
|
|
|
|
+ this.setConstrainedDrawingActive(true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ intersectWithBoundary(geometry) {
|
|
|
|
|
+ if (!this.boundaryGeometry || !geometry || !this.kmap) return null;
|
|
|
|
|
+ const geoJson = new GeoJSON();
|
|
|
|
|
+ const projection = this.kmap.map.getView().getProjection();
|
|
|
|
|
+ const opts = {
|
|
|
|
|
+ dataProjection: "EPSG:4326",
|
|
|
|
|
+ featureProjection: projection,
|
|
|
|
|
+ };
|
|
|
|
|
+ try {
|
|
|
|
|
+ const drawGeo = geoJson.writeGeometryObject(geometry, opts);
|
|
|
|
|
+ const boundaryGeo = geoJson.writeGeometryObject(this.boundaryGeometry, opts);
|
|
|
|
|
+ const drawnFeature = turf.feature(drawGeo);
|
|
|
|
|
+ const boundaryFeature = turf.feature(boundaryGeo);
|
|
|
|
|
+ let result = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ result = turf.intersect(turf.featureCollection([drawnFeature, boundaryFeature]));
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ result = turf.intersect(drawnFeature, boundaryFeature);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!result?.geometry) return null;
|
|
|
|
|
+ return geoJson.readGeometry(result.geometry, opts);
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ clipFeatureToBoundary(feature) {
|
|
|
|
|
+ if (!feature || !this.boundaryGeometry || !this.kmap?.polygonLayer?.source) return;
|
|
|
|
|
+ const geometry = feature.getGeometry();
|
|
|
|
|
+ if (!geometry) return;
|
|
|
|
|
+ const clipped = this.intersectWithBoundary(geometry);
|
|
|
|
|
+ if (!clipped) {
|
|
|
|
|
+ this.kmap.polygonLayer.source.removeFeature(feature);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ feature.setGeometry(clipped);
|
|
|
|
|
+ feature.setStyle(this.createDrawnPestStyle());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setBoundaryWkt(wkt) {
|
|
|
|
|
+ if (!this.kmap || !this.boundaryLayer?.source || !wkt) return;
|
|
|
|
|
+ this.boundaryLayer.source.clear();
|
|
|
|
|
+ const mapProjection = this.kmap.map.getView().getProjection();
|
|
|
|
|
+ const geometry = this.wktFormat.readGeometry(String(wkt).trim(), {
|
|
|
|
|
+ dataProjection: "EPSG:4326",
|
|
|
|
|
+ featureProjection: mapProjection,
|
|
|
|
|
+ });
|
|
|
|
|
+ this.boundaryGeometry = geometry.clone();
|
|
|
|
|
+ const feature = new Feature({ geometry });
|
|
|
|
|
+ feature.set("isBoundary", true);
|
|
|
|
|
+ this.boundaryLayer.addFeature(feature);
|
|
|
|
|
+ this.fitBoundaryView();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ clearBoundaryLayer() {
|
|
|
|
|
+ this.boundaryLayer?.source?.clear();
|
|
|
|
|
+ this.boundaryGeometry = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fitBoundaryView() {
|
|
|
|
|
+ if (!this.kmap || !this.boundaryLayer?.source) return;
|
|
|
|
|
+ const extent = this.boundaryLayer.source.getExtent();
|
|
|
|
|
+ if (!extent || extent.some((v) => !Number.isFinite(v))) return;
|
|
|
|
|
+ this.kmap.getView().fit(extent, { duration: 500, padding: [40, 40, 40, 40] });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setDrawnAreaGeometry(geometryArr) {
|
|
|
|
|
+ if (!this.kmap?.polygonLayer?.source || !Array.isArray(geometryArr)) return;
|
|
|
|
|
+ this.kmap.polygonLayer.source.clear();
|
|
|
|
|
+ const mapProjection = this.kmap.map.getView().getProjection();
|
|
|
|
|
+ geometryArr.forEach((item) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const geometry = this.wktFormat.readGeometry(String(item).trim(), {
|
|
|
|
|
+ dataProjection: "EPSG:4326",
|
|
|
|
|
+ featureProjection: mapProjection,
|
|
|
|
|
+ });
|
|
|
|
|
+ const feature = new Feature({ geometry });
|
|
|
|
|
+ this.clipFeatureToBoundary(feature);
|
|
|
|
|
+ if (feature.getGeometry()) {
|
|
|
|
|
+ this.kmap.polygonLayer.source.addFeature(feature);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ /* 单条解析失败则跳过 */
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 是否允许平移/缩放、勾画与编辑;为 false 时同时隐藏中心点位图标
|
|
* 是否允许平移/缩放、勾画与编辑;为 false 时同时隐藏中心点位图标
|
|
|
*/
|
|
*/
|
|
@@ -176,8 +332,9 @@ class MapManage {
|
|
|
if (!this.kmap) return null;
|
|
if (!this.kmap) return null;
|
|
|
const center = this.kmap.getView().getCenter();
|
|
const center = this.kmap.getView().getCenter();
|
|
|
const wkt = this.generateSquareWktByMu(center, mu);
|
|
const wkt = this.generateSquareWktByMu(center, mu);
|
|
|
- this.setAreaGeometry([wkt]);
|
|
|
|
|
|
|
+ this.setBoundaryWkt(wkt);
|
|
|
this.setMapPoint(center);
|
|
this.setMapPoint(center);
|
|
|
|
|
+ this.enableConstrainedDrawing();
|
|
|
return wkt;
|
|
return wkt;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -190,7 +347,8 @@ class MapManage {
|
|
|
});
|
|
});
|
|
|
this.setMapPoint(center);
|
|
this.setMapPoint(center);
|
|
|
const wkt = this.generateSquareWktByMu(center, mu);
|
|
const wkt = this.generateSquareWktByMu(center, mu);
|
|
|
- this.setAreaGeometry([wkt]);
|
|
|
|
|
|
|
+ this.setBoundaryWkt(wkt);
|
|
|
|
|
+ this.enableConstrainedDrawing();
|
|
|
return wkt;
|
|
return wkt;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -220,6 +378,11 @@ class MapManage {
|
|
|
this.clearGridLayer();
|
|
this.clearGridLayer();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ clearAllLayers() {
|
|
|
|
|
+ this.clearLayer();
|
|
|
|
|
+ this.clearBoundaryLayer();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
clearGridLayer() {
|
|
clearGridLayer() {
|
|
|
this.unbindGridClick();
|
|
this.unbindGridClick();
|
|
|
this.gridLayer?.source?.clear();
|
|
this.gridLayer?.source?.clear();
|
|
@@ -435,6 +598,14 @@ class MapManage {
|
|
|
this.kmap.getView().fit(extent, { duration: 500, padding: [40, 40, 40, 40] });
|
|
this.kmap.getView().fit(extent, { duration: 500, padding: [40, 40, 40, 40] });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ getBoundaryWkt() {
|
|
|
|
|
+ if (!this.boundaryGeometry || !this.kmap) return "";
|
|
|
|
|
+ return this.wktFormat.writeGeometry(this.boundaryGeometry, {
|
|
|
|
|
+ dataProjection: "EPSG:4326",
|
|
|
|
|
+ featureProjection: this.kmap.map.getView().getProjection(),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
getDisplayAreaWkt() {
|
|
getDisplayAreaWkt() {
|
|
|
if (!this.kmap?.polygonLayer?.source) return "";
|
|
if (!this.kmap?.polygonLayer?.source) return "";
|
|
|
const projection = this.kmap.map.getView().getProjection();
|
|
const projection = this.kmap.map.getView().getProjection();
|
|
@@ -492,12 +663,15 @@ class MapManage {
|
|
|
|
|
|
|
|
destroyMap() {
|
|
destroyMap() {
|
|
|
this.unbindGridClick();
|
|
this.unbindGridClick();
|
|
|
- this.clearLayer();
|
|
|
|
|
|
|
+ this.clearAllLayers();
|
|
|
if (this.kmap && typeof this.kmap.destroy === "function") {
|
|
if (this.kmap && typeof this.kmap.destroy === "function") {
|
|
|
this.kmap.destroy();
|
|
this.kmap.destroy();
|
|
|
}
|
|
}
|
|
|
this.kmap = null;
|
|
this.kmap = null;
|
|
|
this.regionDrawingActive = false;
|
|
this.regionDrawingActive = false;
|
|
|
|
|
+ this.constrainedDrawing = false;
|
|
|
|
|
+ this.constrainedDrawingReady = false;
|
|
|
|
|
+ this.boundaryGeometry = null;
|
|
|
this.selectedGridIds?.clear();
|
|
this.selectedGridIds?.clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -505,6 +679,9 @@ class MapManage {
|
|
|
* 地图上全部已勾画地块:WKT 列表、每块亩数、合计亩数(亩换算与互动勾画页一致)
|
|
* 地图上全部已勾画地块:WKT 列表、每块亩数、合计亩数(亩换算与互动勾画页一致)
|
|
|
*/
|
|
*/
|
|
|
getAreaGeometry() {
|
|
getAreaGeometry() {
|
|
|
|
|
+ if (!this.kmap) {
|
|
|
|
|
+ return { geometryArr: [], mianji: "0.00", parcels: [] };
|
|
|
|
|
+ }
|
|
|
const features = this.kmap.getLayerFeatures();
|
|
const features = this.kmap.getLayerFeatures();
|
|
|
const format = new WKT();
|
|
const format = new WKT();
|
|
|
const projection = this.kmap.map.getView().getProjection();
|
|
const projection = this.kmap.map.getView().getProjection();
|
|
@@ -550,7 +727,11 @@ class MapManage {
|
|
|
}
|
|
}
|
|
|
this.kmap.polygonLayer.source.addFeature(feature);
|
|
this.kmap.polygonLayer.source.addFeature(feature);
|
|
|
});
|
|
});
|
|
|
- this.fitView();
|
|
|
|
|
|
|
+ if (this.boundaryGeometry) {
|
|
|
|
|
+ this.fitBoundaryView();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.fitView();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
fitView(){
|
|
fitView(){
|