// 要素转leaflet图元
import {
Log,
GeometryType,
SymbolType,
Feature,
SimpleMarkerSymbol
} from '@mapgis/webclient-common'
import * as L from '@mapgis/leaflet'
import ConvertGeometryUtil from './ConvertGeometryUtil'
import ConvertSymbolUtil from './ConvertSymbolUtil'
import LeafletPlugin from './LeafletPlugin'
const toLeafletCoords = ConvertGeometryUtil.toLeafletCoords
const toLeafletStyle = ConvertSymbolUtil.convertSymboltoLeafletStyle
/**
* @description 根据类型创建marker
* @public
* @param {*} type
* @param {*} coords
* @param {*} style
* @return {*}
*/
function createGraphic(symbolType, coords, style) {
let graphic
switch (symbolType) {
case SymbolType.simpleMarker: {
graphic = new L.ShapeMarker(coords, style)
break
}
case SymbolType.pictureMarker: {
graphic = L.marker(coords, style)
break
}
case SymbolType.line: {
graphic = L.polyline(coords, style)
break
}
case SymbolType.text: {
graphic = L.marker(coords, style)
break
}
case SymbolType.fill: {
graphic = L.polygon(coords, style)
break
}
case SymbolType.pictureFill: {
graphic = L.polygon(coords, style)
break
}
default: {
Log.error('符号类型错误,不合法的符号类型')
}
}
return graphic
}
function convertPointToGraphic(feature) {
const coords = toLeafletCoords(feature.geometry)
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
return createGraphic(symbolType, coords[0], style)
}
function convertMultiPointToGraphic(feature) {
const coords = toLeafletCoords(feature.geometry)
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const layers = []
coords.forEach((coord) => {
const marker = createGraphic(symbolType, coord, style)
layers.push(marker)
})
return new L.FeatureGroup(layers)
}
function convertPolylineMarker(marker, width, coordinates) {
const layers = []
if (marker) {
const { color, style, placement } = marker
const markerDetail = LeafletPlugin.calcLineMarkerDetail(coordinates)
const { angle1, angle2, latlng1, latlng2 } = markerDetail
const leafletStyle = toLeafletStyle(
new SimpleMarkerSymbol({
angle: angle1,
color,
outline: {
color,
width
},
style,
size: Math.max(15, 4 * width)
})
)
const p1 = createGraphic(SymbolType.simpleMarker, latlng1, leafletStyle)
const p2 = createGraphic(
SymbolType.simpleMarker,
latlng2,
toLeafletStyle(
new SimpleMarkerSymbol({
angle: angle2,
color,
outline: {
color,
width
},
style,
size: Math.max(15, 4 * width)
})
)
)
if (placement === 'begin') {
layers.push(p1)
} else if (placement === 'end') {
layers.push(p2)
} else {
layers.push(p1)
layers.push(p2)
}
}
return layers
}
function updatePolylineMarkers(feature, graphic) {
if (graphic['__marker__group']) {
graphic.removeLayer(graphic['__marker__group'])
}
const width = feature.symbol.width
const marker = feature.symbol.marker
const layers = convertPolylineMarker(
marker,
width,
feature.geometry.coordinates
)
const markerGroup = new L.FeatureGroup(layers)
graphic['__marker__group'] = markerGroup
graphic.addLayer(markerGroup)
}
function updateMultiPolylineMarkers(feature, graphic) {
if (graphic['__marker__group']) {
graphic.removeLayer(graphic['__marker__group'])
}
const width = feature.symbol.width
const marker = feature.symbol.marker
let layers = []
feature.geometry.coordinates.forEach((coords) => {
const v = convertPolylineMarker(marker, width, coords)
layers = layers.concat(v)
})
const markerGroup = new L.FeatureGroup(layers)
graphic['__marker__group'] = markerGroup
graphic.addLayer(markerGroup)
}
function convertPolylineToGraphic(feature) {
const coords = toLeafletCoords(feature.geometry, {
additional: feature.additional
})
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const featureGroup = new L.FeatureGroup()
const lineGraphic = createGraphic(symbolType, coords, style)
featureGroup['__line__graphic'] = lineGraphic
featureGroup.addLayer(lineGraphic)
// 转换线首尾角marker
if (feature.symbol.marker) {
updatePolylineMarkers(feature, featureGroup)
}
return featureGroup
}
function convertMultiLineStringToGraphic(feature) {
const coords = toLeafletCoords(feature.geometry, {
additional: feature.additional
})
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const featureGroup = new L.FeatureGroup()
const lineGraphic = createGraphic(symbolType, coords, style)
featureGroup['__line__graphic'] = lineGraphic
featureGroup.addLayer(lineGraphic)
// 转换线首尾角marker
if (feature.symbol.marker) {
updateMultiPolylineMarkers(feature, featureGroup)
}
return featureGroup
}
function getAreaCoords(symbolType, geometry, feature) {
let coords
// 如果类型为点,则重新设置几何
if (
SymbolType.simpleMarker === symbolType ||
SymbolType.text === symbolType ||
SymbolType.pictureMarker === symbolType
) {
coords = LeafletPlugin.getAreaCenter(geometry)
} else {
coords = toLeafletCoords(geometry, {
additional: feature.additional
})
}
return coords
}
function convertPolygonToGraphic(feature) {
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const coords = getAreaCoords(symbolType, feature.geometry, feature)
return createGraphic(symbolType, coords, style)
}
function convertCircleToGraphic(feature) {
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const coords = getAreaCoords(
symbolType,
feature.geometry.toPolygon(),
feature
)
return createGraphic(symbolType, coords, style)
}
function convertExtentToGraphic(feature) {
const style = toLeafletStyle(feature.symbol)
const symbolType = feature.symbol.type
const coords = getAreaCoords(symbolType, feature.geometry, feature)
if (symbolType !== SymbolType.simpleFill) {
return createGraphic(symbolType, coords, style)
}
return L.rectangle(coords, style)
}
/**
* @description 转换要素为几何图形
* @public
* @param {Feature} feature
* @return {*}
*/
function convertFeature(feature) {
let graphic = null
if (!(feature instanceof Feature)) return graphic
if (!feature.geometry) {
Log.error('几何不存在')
return graphic
}
switch (feature.geometry.type) {
case GeometryType.point: {
graphic = convertPointToGraphic(feature)
break
}
case GeometryType.lineString: {
graphic = convertPolylineToGraphic(feature)
break
}
case GeometryType.multiPolygon:
case GeometryType.polygon: {
graphic = convertPolygonToGraphic(feature)
break
}
case GeometryType.extent: {
graphic = convertExtentToGraphic(feature)
break
}
case GeometryType.circle: {
graphic = convertCircleToGraphic(feature)
break
}
case GeometryType.multiPoint: {
graphic = convertMultiPointToGraphic(feature)
break
}
case GeometryType.multiLineString: {
graphic = convertMultiLineStringToGraphic(feature)
break
}
default: {
break
}
}
return graphic
}
export {
convertFeature,
createGraphic,
updatePolylineMarkers,
updateMultiPolylineMarkers,
getAreaCoords
}