mirror of
https://github.com/sakitam-fdd/maptalks.plot.git
synced 2026-01-25 16:08:13 +00:00
# update
This commit is contained in:
parent
88ae29dc4b
commit
84e9197196
@ -1,3 +1,8 @@
|
||||
## 0.0.1 (完善PlotDraw)
|
||||
|
||||
* 完善PlotDraw
|
||||
* 添加部分geometry构造类(Ployline,Arror,Polygon)
|
||||
|
||||
## 0.0.0 (搭建框架)
|
||||
|
||||
* 搭建框架
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
var map = new maptalks.Map('map', {
|
||||
center: [-0.113049, 51.498568],
|
||||
zoom: 14,
|
||||
projection: 'EPSG:4326',
|
||||
attribution: {
|
||||
content: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>'
|
||||
},
|
||||
@ -42,7 +43,11 @@
|
||||
console.log(param.geometry);
|
||||
layer.addGeometry(param.geometry);
|
||||
});
|
||||
var items = ['Polyline', 'Curve', 'Arc', 'FreeLine'].map(function (value) {
|
||||
var items = ['Polyline', 'Curve',
|
||||
'Arc', 'FreeLine', 'AttackArrow',
|
||||
'ClosedCurve', 'FreePolygon',
|
||||
'GatheringPlace', 'Lune', 'Sector', 'Polygon',
|
||||
'RectAngle'].map(function (value) {
|
||||
return {
|
||||
item: value,
|
||||
click: function () {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "maptalks.plot",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.1",
|
||||
"description": "A maptalks plugins to plotting",
|
||||
"author": "FDD <smileFDD@gmail.com>",
|
||||
"homepage": "https://sakitam-fdd.github.io/maptalks.plot",
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
import * as maptalks from 'maptalks'
|
||||
import {BASE_LAYERNAME} from '../Constants'
|
||||
import RegisterModes from '../geometry'
|
||||
import { merge } from '../utils/utils'
|
||||
import {merge} from '../utils/utils'
|
||||
import {MathDistance} from '../geometry/helper'
|
||||
|
||||
const _options = {
|
||||
'symbol': {
|
||||
'lineColor': '#000',
|
||||
@ -29,6 +31,7 @@ const stopPropagation = function (e) {
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
class PlotDraw extends maptalks.MapTool {
|
||||
constructor (options = {}) {
|
||||
const $options = merge(_options, options)
|
||||
@ -188,6 +191,14 @@ class PlotDraw extends maptalks.MapTool {
|
||||
const registerMode = this._getRegisterMode()
|
||||
const coordinate = event['coordinate']
|
||||
if (this._geometry) {
|
||||
if (!registerMode.freehand) {
|
||||
if (MathDistance([
|
||||
coordinate['x'], coordinate['y']], [
|
||||
this._clickCoords[this._clickCoords.length - 1]['x'],
|
||||
this._clickCoords[this._clickCoords.length - 1]['y']]) < 0.0001) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!(this._historyPointer === null)) {
|
||||
this._clickCoords = this._clickCoords.slice(0, this._historyPointer)
|
||||
}
|
||||
@ -232,14 +243,20 @@ class PlotDraw extends maptalks.MapTool {
|
||||
*/
|
||||
_mouseMoveHandler (event) {
|
||||
const map = this.getMap()
|
||||
const coordinate = event['coordinate']
|
||||
if (!this._geometry || !map || map.isInteracting()) {
|
||||
return
|
||||
}
|
||||
if (MathDistance([
|
||||
coordinate['x'], coordinate['y']], [
|
||||
this._clickCoords[this._clickCoords.length - 1]['x'],
|
||||
this._clickCoords[this._clickCoords.length - 1]['y']]) < 0.0001) {
|
||||
return
|
||||
}
|
||||
const containerPoint = this._getMouseContainerPoint(event)
|
||||
if (!this._isValidContainerPoint(containerPoint)) {
|
||||
return
|
||||
}
|
||||
const coordinate = event['coordinate']
|
||||
const registerMode = this._getRegisterMode()
|
||||
const path = this._clickCoords.slice(0, this._historyPointer)
|
||||
if (path && path.length > 0 && coordinate.equals(path[path.length - 1])) {
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
/**
|
||||
* Created by FDD on 2017/5/20.
|
||||
*/
|
||||
const TextArea = 'TextArea' // 文本标绘(特殊)
|
||||
const ARC = 'Arc'
|
||||
const CURVE = 'Curve'
|
||||
|
||||
162
src/geometry/Arrow/AttackArrow.js
Normal file
162
src/geometry/Arrow/AttackArrow.js
Normal file
@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 进攻方向
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
MathDistance,
|
||||
getBaseLength,
|
||||
wholeDistance,
|
||||
isClockWise,
|
||||
getQBSplinePoints,
|
||||
getAngleOfThreePoints
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
class AttackArrow extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'AttackArrow'
|
||||
this._coordinates = []
|
||||
this.headHeightFactor = 0.18
|
||||
this.headWidthFactor = 0.3
|
||||
this.neckHeightFactor = 0.85
|
||||
this.neckWidthFactor = 0.15
|
||||
this.headTailFactor = 0.8
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理插值
|
||||
*/
|
||||
_generate () {
|
||||
try {
|
||||
const count = this._coordinates.length
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
this.setCoordinates([this._coordinates])
|
||||
} else {
|
||||
let pnts = Coordinate.toNumberArrays(this._coordinates)
|
||||
let [tailLeft, tailRight] = [pnts[0], pnts[1]]
|
||||
if (isClockWise(pnts[0], pnts[1], pnts[2])) {
|
||||
tailLeft = pnts[1]
|
||||
tailRight = pnts[0]
|
||||
}
|
||||
let midTail = Mid(tailLeft, tailRight)
|
||||
let bonePnts = [midTail].concat(pnts.slice(2))
|
||||
let headPnts = this._getArrowHeadPoints(bonePnts, tailLeft, tailRight)
|
||||
let [neckLeft, neckRight] = [headPnts[0], headPnts[4]]
|
||||
let tailWidthFactor = MathDistance(tailLeft, tailRight) / getBaseLength(bonePnts)
|
||||
let bodyPnts = this._getArrowBodyPoints(bonePnts, neckLeft, neckRight, tailWidthFactor)
|
||||
let count = bodyPnts.length
|
||||
let leftPnts = [tailLeft].concat(bodyPnts.slice(0, count / 2))
|
||||
leftPnts.push(neckLeft)
|
||||
let rightPnts = [tailRight].concat(bodyPnts.slice(count / 2, count))
|
||||
rightPnts.push(neckRight)
|
||||
leftPnts = getQBSplinePoints(leftPnts)
|
||||
rightPnts = getQBSplinePoints(rightPnts)
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(leftPnts.concat(headPnts, rightPnts.reverse()))
|
||||
])
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插值头部点
|
||||
* @param points
|
||||
* @param tailLeft
|
||||
* @param tailRight
|
||||
* @returns {*[]}
|
||||
*/
|
||||
_getArrowHeadPoints (points, tailLeft, tailRight) {
|
||||
let len = getBaseLength(points)
|
||||
let headHeight = len * this.headHeightFactor
|
||||
let headPnt = points[points.length - 1]
|
||||
len = MathDistance(headPnt, points[points.length - 2])
|
||||
let tailWidth = MathDistance(tailLeft, tailRight)
|
||||
if (headHeight > tailWidth * this.headTailFactor) {
|
||||
headHeight = tailWidth * this.headTailFactor
|
||||
}
|
||||
let headWidth = headHeight * this.headWidthFactor
|
||||
let neckWidth = headHeight * this.neckWidthFactor
|
||||
headHeight = headHeight > len ? len : headHeight
|
||||
let neckHeight = headHeight * this.neckHeightFactor
|
||||
let headEndPnt = getThirdPoint(points[points.length - 2], headPnt, 0, headHeight, true)
|
||||
let neckEndPnt = getThirdPoint(points[points.length - 2], headPnt, 0, neckHeight, true)
|
||||
let headLeft = getThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, false)
|
||||
let headRight = getThirdPoint(headPnt, headEndPnt, Constants.HALF_PI, headWidth, true)
|
||||
let neckLeft = getThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, false)
|
||||
let neckRight = getThirdPoint(headPnt, neckEndPnt, Constants.HALF_PI, neckWidth, true)
|
||||
return [neckLeft, headLeft, headPnt, headRight, neckRight]
|
||||
}
|
||||
|
||||
/**
|
||||
* 插值面部分数据
|
||||
* @param points
|
||||
* @param neckLeft
|
||||
* @param neckRight
|
||||
* @param tailWidthFactor
|
||||
* @returns {*|T[]|string}
|
||||
*/
|
||||
_getArrowBodyPoints (points, neckLeft, neckRight, tailWidthFactor) {
|
||||
let allLen = wholeDistance(points)
|
||||
let len = getBaseLength(points)
|
||||
let tailWidth = len * tailWidthFactor
|
||||
let neckWidth = MathDistance(neckLeft, neckRight)
|
||||
let widthDif = (tailWidth - neckWidth) / 2
|
||||
let [tempLen, leftBodyPnts, rightBodyPnts] = [0, [], []]
|
||||
for (let i = 1; i < points.length - 1; i++) {
|
||||
let angle = getAngleOfThreePoints(points[i - 1], points[i], points[i + 1]) / 2
|
||||
tempLen += MathDistance(points[i - 1], points[i])
|
||||
let w = (tailWidth / 2 - tempLen / allLen * widthDif) / Math.sin(angle)
|
||||
let left = getThirdPoint(points[i - 1], points[i], Math.PI - angle, w, true)
|
||||
let right = getThirdPoint(points[i - 1], points[i], angle, w, false)
|
||||
leftBodyPnts.push(left)
|
||||
rightBodyPnts.push(right)
|
||||
}
|
||||
return leftBodyPnts.concat(rightBodyPnts)
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'AttackArrow'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new AttackArrow(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
AttackArrow.registerJSONType('AttackArrow')
|
||||
|
||||
export default AttackArrow
|
||||
92
src/geometry/Polygon/ClosedCurve.js
Normal file
92
src/geometry/Polygon/ClosedCurve.js
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 闭合曲面
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
getBisectorNormals,
|
||||
getCubicValue
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class ClosedCurve extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'ClosedCurve'
|
||||
this._offset = 0.3
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理插值
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
const count = this._coordinates.length
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
this.setCoordinates([this._coordinates])
|
||||
} else {
|
||||
const points = Coordinate.toNumberArrays(this._coordinates)
|
||||
points.push(points[0], points[1])
|
||||
let [normals, pList] = [[], []]
|
||||
for (let i = 0; i < points.length - 2; i++) {
|
||||
let normalPoints = getBisectorNormals(this._offset, points[i], points[i + 1], points[i + 2])
|
||||
normals = normals.concat(normalPoints)
|
||||
}
|
||||
let count = normals.length
|
||||
normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
|
||||
for (let i = 0; i < points.length - 2; i++) {
|
||||
let pnt1 = points[i]
|
||||
let pnt2 = points[i + 1]
|
||||
pList.push(pnt1)
|
||||
for (let t = 0; t <= Constants.FITTING_COUNT; t++) {
|
||||
let pnt = getCubicValue(t / Constants.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
|
||||
pList.push(pnt)
|
||||
}
|
||||
pList.push(pnt2)
|
||||
}
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(pList)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'ClosedCurve'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new ClosedCurve(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
ClosedCurve.registerJSONType('ClosedCurve')
|
||||
|
||||
export default ClosedCurve
|
||||
58
src/geometry/Polygon/FreePolygon.js
Normal file
58
src/geometry/Polygon/FreePolygon.js
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 自由面
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class FreePolygon extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'FreePolygon'
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle coordinates
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
this.setCoordinates([this._coordinates])
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'FreePolygon'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new FreePolygon(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
FreePolygon.registerJSONType('FreePolygon')
|
||||
|
||||
export default FreePolygon
|
||||
101
src/geometry/Polygon/GatheringPlace.js
Normal file
101
src/geometry/Polygon/GatheringPlace.js
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 集结地
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
MathDistance,
|
||||
getBisectorNormals,
|
||||
getCubicValue
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class GatheringPlace extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'GatheringPlace'
|
||||
this._offset = 0.4
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle coordinates
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
let count = this._coordinates.length
|
||||
let _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
let mid = Mid(_points[0], _points[1])
|
||||
let d = MathDistance(_points[0], mid) / 0.9
|
||||
let pnt = getThirdPoint(_points[0], mid, Constants.HALF_PI, d, true)
|
||||
_points = [_points[0], pnt, _points[1]]
|
||||
}
|
||||
let mid = Mid(_points[0], _points[2])
|
||||
_points.push(mid, _points[0], _points[1])
|
||||
let [normals, pnt1, pnt2, pnt3, pList] = [[], undefined, undefined, undefined, []]
|
||||
for (let i = 0; i < _points.length - 2; i++) {
|
||||
pnt1 = _points[i]
|
||||
pnt2 = _points[i + 1]
|
||||
pnt3 = _points[i + 2]
|
||||
let normalPoints = getBisectorNormals(this._offset, pnt1, pnt2, pnt3)
|
||||
normals = normals.concat(normalPoints)
|
||||
}
|
||||
count = normals.length
|
||||
normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
|
||||
for (let i = 0; i < _points.length - 2; i++) {
|
||||
pnt1 = _points[i]
|
||||
pnt2 = _points[i + 1]
|
||||
pList.push(pnt1)
|
||||
for (let t = 0; t <= Constants.FITTING_COUNT; t++) {
|
||||
let pnt = getCubicValue(t / Constants.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
|
||||
pList.push(pnt)
|
||||
}
|
||||
pList.push(pnt2)
|
||||
}
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(pList)
|
||||
])
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'GatheringPlace'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new GatheringPlace(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
GatheringPlace.registerJSONType('GatheringPlace')
|
||||
|
||||
export default GatheringPlace
|
||||
93
src/geometry/Polygon/Lune.js
Normal file
93
src/geometry/Polygon/Lune.js
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 弓形
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
MathDistance,
|
||||
isClockWise,
|
||||
getAzimuth,
|
||||
getArcPoints,
|
||||
getCircleCenterOfThreePoints
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class Lune extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'Lune'
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle coordinates
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
const count = this._coordinates.length
|
||||
let _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
let mid = Mid(_points[0], _points[1])
|
||||
let d = MathDistance(_points[0], mid)
|
||||
let pnt = getThirdPoint(_points[0], mid, Constants.HALF_PI, d)
|
||||
_points.push(pnt)
|
||||
}
|
||||
let [pnt1, pnt2, pnt3, startAngle, endAngle] = [_points[0], _points[1], _points[2], undefined, undefined]
|
||||
let center = getCircleCenterOfThreePoints(pnt1, pnt2, pnt3)
|
||||
let radius = MathDistance(pnt1, center)
|
||||
let angle1 = getAzimuth(pnt1, center)
|
||||
let angle2 = getAzimuth(pnt2, center)
|
||||
if (isClockWise(pnt1, pnt2, pnt3)) {
|
||||
startAngle = angle2
|
||||
endAngle = angle1
|
||||
} else {
|
||||
startAngle = angle1
|
||||
endAngle = angle2
|
||||
}
|
||||
_points = getArcPoints(center, radius, startAngle, endAngle)
|
||||
_points.push(_points[0])
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(_points)
|
||||
])
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'Lune'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new Lune(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
Lune.registerJSONType('Lune')
|
||||
|
||||
export default Lune
|
||||
89
src/geometry/Polygon/RectAngle.js
Normal file
89
src/geometry/Polygon/RectAngle.js
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 规则矩形
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
maptalks.Polygon.getCoordinateFromExtent = function (extent) {
|
||||
let [minX, minY, maxX, maxY] = [extent[0], extent[1], extent[2], extent[3]]
|
||||
return [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY]
|
||||
}
|
||||
|
||||
const boundingExtent = function (coordinates) {
|
||||
let extent = new maptalks.Extent()
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
extent.add(extent, coordinates[i])
|
||||
}
|
||||
return extent
|
||||
}
|
||||
|
||||
class RectAngle extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'RectAngle'
|
||||
this._coordinates = []
|
||||
this.isFill = ((options['isFill'] === false) ? options['isFill'] : true)
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle coordinates
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
const count = this._coordinates.length
|
||||
let _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
let coordinates = []
|
||||
if (this.isFill) {
|
||||
let extent = boundingExtent(this._coordinates)
|
||||
coordinates = maptalks.Polygon.getCoordinateFromExtent(extent)
|
||||
} else {
|
||||
let start = _points[0]
|
||||
let end = _points[1]
|
||||
coordinates = [start, [start[0], end[1]], end, [end[0], start[1]], start]
|
||||
}
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(coordinates)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'RectAngle'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new RectAngle(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
RectAngle.registerJSONType('RectAngle')
|
||||
|
||||
export default RectAngle
|
||||
80
src/geometry/Polygon/Sector.js
Normal file
80
src/geometry/Polygon/Sector.js
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/26.
|
||||
* @desc 扇形
|
||||
* @Inherits maptalks.Polygon
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import {
|
||||
MathDistance,
|
||||
getAzimuth,
|
||||
getArcPoints
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
class Sector extends maptalks.Polygon {
|
||||
constructor (coordinates, options = {}) {
|
||||
super(options)
|
||||
this.type = 'Sector'
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this.setPoints(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle coordinates
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
const count = this._coordinates.length
|
||||
let _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
this.setCoordinates([this._coordinates])
|
||||
} else {
|
||||
let [center, pnt2, pnt3] = [_points[0], _points[1], _points[2]]
|
||||
let radius = MathDistance(pnt2, center)
|
||||
let startAngle = getAzimuth(pnt2, center)
|
||||
let endAngle = getAzimuth(pnt3, center)
|
||||
let pList = getArcPoints(center, radius, startAngle, endAngle)
|
||||
pList.push(center, pList[0])
|
||||
this.setCoordinates([
|
||||
Coordinate.toCoordinates(pList)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
setPoints (coordinates) {
|
||||
this._coordinates = !coordinates ? [] : coordinates
|
||||
if (this._coordinates.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const coordinates = Coordinate.toNumberArrays([this.getShell()])
|
||||
return {
|
||||
'type': 'Polygon',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
return {
|
||||
'feature': this.toGeoJSON(options),
|
||||
'subType': 'Sector'
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const attackArrow = new Sector(json['coordinates'], json['width'], json['height'], json['options'])
|
||||
attackArrow.setProperties(feature['properties'])
|
||||
return attackArrow
|
||||
}
|
||||
}
|
||||
|
||||
Sector.registerJSONType('Sector')
|
||||
|
||||
export default Sector
|
||||
@ -24,7 +24,8 @@ class Arc extends maptalks.LineString {
|
||||
}
|
||||
|
||||
_generate () {
|
||||
let count = this._coordinates.length
|
||||
const _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
let count = _points.length
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
this.setCoordinates(this._coordinates)
|
||||
@ -34,33 +35,21 @@ class Arc extends maptalks.LineString {
|
||||
pnt3, startAngle,
|
||||
endAngle
|
||||
] = [
|
||||
this._coordinates[0], this._coordinates[1],
|
||||
this._coordinates[2], null, null
|
||||
_points[0], _points[1],
|
||||
_points[2], null, null
|
||||
]
|
||||
let center = getCircleCenterOfThreePoints([pnt1['x'], pnt1['y']], [pnt2['x'], pnt2['y']], [pnt3['x'], pnt3['y']])
|
||||
let radius = MathDistance([pnt1['x'], pnt1['y']], center)
|
||||
let angle1 = getAzimuth([pnt1['x'], pnt1['y']], center)
|
||||
let angle2 = getAzimuth([pnt2['x'], pnt2['y']], center)
|
||||
if (isClockWise([pnt1['x'], pnt1['y']], [pnt2['x'], pnt2['y']], [pnt3['x'], pnt3['y']])) {
|
||||
let center = getCircleCenterOfThreePoints(pnt1, pnt2, pnt3)
|
||||
let radius = MathDistance(pnt1, center)
|
||||
let angle1 = getAzimuth(pnt1, center)
|
||||
let angle2 = getAzimuth(pnt2, center)
|
||||
if (isClockWise(pnt1, pnt2, pnt3)) {
|
||||
startAngle = angle2
|
||||
endAngle = angle1
|
||||
} else {
|
||||
startAngle = angle1
|
||||
endAngle = angle2
|
||||
}
|
||||
let points = getArcPoints(center, radius, startAngle, endAngle)
|
||||
if (Array.isArray(points)) {
|
||||
let _points = points.map(_item => {
|
||||
if (Array.isArray(_item)) {
|
||||
if (!isNaN(_item[0]) && !isNaN(_item[1])) {
|
||||
return new Coordinate(_item[0], _item[1])
|
||||
}
|
||||
} else {
|
||||
return _item
|
||||
}
|
||||
})
|
||||
this.setCoordinates(_points)
|
||||
}
|
||||
this.setCoordinates(Coordinate.toCoordinates(getArcPoints(center, radius, startAngle, endAngle)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,30 +22,15 @@ class Curve extends maptalks.LineString {
|
||||
}
|
||||
|
||||
_generate () {
|
||||
let count = this._coordinates.length
|
||||
const _points = Coordinate.toNumberArrays(this._coordinates)
|
||||
let count = _points.length
|
||||
if (count < 2) {
|
||||
return false
|
||||
} else if (count === 2) {
|
||||
this.setCoordinates(this._coordinates)
|
||||
} else {
|
||||
let _coordinates = this._coordinates.map(_item => {
|
||||
if (_item && _item.hasOwnProperty('x')) {
|
||||
return [_item['x'], _item['y']]
|
||||
} else if (Array.isArray(_item)) {
|
||||
return _item
|
||||
}
|
||||
})
|
||||
let points = getCurvePoints(0.3, _coordinates)
|
||||
if (Array.isArray(points)) {
|
||||
let _points = points.map(_item => {
|
||||
if (Array.isArray(_item)) {
|
||||
return new Coordinate(_item[0], _item[1])
|
||||
} else {
|
||||
return _item
|
||||
}
|
||||
})
|
||||
this.setCoordinates(_points)
|
||||
}
|
||||
let points = getCurvePoints(0.3, _points)
|
||||
this.setCoordinates(Coordinate.toCoordinates(points))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/12.
|
||||
* @desc 线
|
||||
* @Inherits maptalks.LineString
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
const options = {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import * as Constants from '../../Constants'
|
||||
import * as maptalks from 'maptalks'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
/**
|
||||
* 计算两个坐标之间的距离
|
||||
* @param pnt1
|
||||
@ -488,3 +490,27 @@ export const getQuadricBSplineFactor = (k, t) => {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
export const getCoordinatesArray = (coordinates) => {
|
||||
const _coordinates = []
|
||||
for (let i = 0; i < coordinates.length; i++) {
|
||||
if (coordinates[i] && coordinates[i].hasOwnProperty('x')) {
|
||||
_coordinates.push([coordinates[i]['x'], coordinates[i]['y']])
|
||||
} else {
|
||||
_coordinates.push(coordinates[i])
|
||||
}
|
||||
}
|
||||
return _coordinates
|
||||
}
|
||||
|
||||
export const getCoordinatesObject = (coordinates) => {
|
||||
const _coordinates = []
|
||||
for (let i = 0; i < coordinates.length; i++) {
|
||||
if (coordinates[i] && Array.isArray(coordinates[i])) {
|
||||
_coordinates.push(new Coordinate(coordinates[i][0], coordinates[i][1]))
|
||||
} else {
|
||||
_coordinates.push(coordinates[i])
|
||||
}
|
||||
}
|
||||
return _coordinates
|
||||
}
|
||||
|
||||
@ -1,13 +1,25 @@
|
||||
/**
|
||||
* Created by FDD on 2017/5/20.
|
||||
* Created by FDD on 2017/12/20.
|
||||
* @desc 标绘图形构造类
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
|
||||
import Arc from './Polyline/Arc'
|
||||
import Curve from './Polyline/Curve'
|
||||
import Polyline from './Polyline/Polyline'
|
||||
import FreeLine from './Polyline/FreeLine'
|
||||
|
||||
import AttackArrow from './Arrow/AttackArrow'
|
||||
|
||||
import Lune from './Polygon/Lune'
|
||||
import Sector from './Polygon/Sector'
|
||||
import ClosedCurve from './Polygon/ClosedCurve'
|
||||
import FreePolygon from './Polygon/FreePolygon'
|
||||
import RectAngle from './Polygon/RectAngle'
|
||||
import GatheringPlace from './Polygon/GatheringPlace'
|
||||
|
||||
import * as PlotTypes from '../core/PlotTypes'
|
||||
const Polygon = maptalks.Polygon
|
||||
const RegisterModes = {}
|
||||
RegisterModes[PlotTypes.ARC] = {
|
||||
'freehand': false,
|
||||
@ -62,5 +74,129 @@ RegisterModes[PlotTypes.FREE_LINE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.ATTACK_ARROW] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new AttackArrow(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.CLOSED_CURVE] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new ClosedCurve(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.LUNE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new Lune(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.SECTOR] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new Sector(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.POLYGON] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new Polygon(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setCoordinates(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.RECTANGLE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
'action': ['click', 'mousemove', 'click'],
|
||||
'create': function (path) {
|
||||
return new RectAngle(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setCoordinates(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.FREE_POLYGON] = {
|
||||
'freehand': true,
|
||||
'action': ['mousedown', 'drag', 'mouseup'],
|
||||
'create': function (path) {
|
||||
return new FreePolygon(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
RegisterModes[PlotTypes.GATHERING_PLACE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
'create': function (path) {
|
||||
return new GatheringPlace(path)
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return new Polygon(geometry.getCoordinates(), {
|
||||
'symbol': geometry.getSymbol()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default RegisterModes
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user