mirror of
https://github.com/sakitam-fdd/maptalks.plot.git
synced 2026-01-18 16:03:28 +00:00
# pre re
This commit is contained in:
parent
718ab779d6
commit
067ef80f14
@ -4,11 +4,5 @@ cache:
|
||||
directories:
|
||||
- node_modules
|
||||
install: npm install
|
||||
addons:
|
||||
Chrome: "latest"
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- sleep 3 # give xvfb some time to start
|
||||
script:
|
||||
- npm run build
|
||||
|
||||
121
README.md
121
README.md
@ -1 +1,122 @@
|
||||
# maptalks.plot
|
||||
|
||||
> 对 `maptalks` 扩展的 `plot symbol` 的自定义绘制插件
|
||||
|
||||
[](https://www.travis-ci.org/sakitam-fdd/maptalks.plot)
|
||||
[](https://codecov.io/gh/sakitam-fdd/maptalks.plot)
|
||||
[](https://npmjs.org/package/maptalks.plot)
|
||||

|
||||
[](https://www.npmjs.org/package/maptalks.plot)
|
||||
[](https://github.com/sakitam-fdd/maptalks.plot/stargazers)
|
||||
[](https://raw.githubusercontent.com/sakitam-fdd/maptalks.plot/master/LICENSE)
|
||||
|
||||
## 下载
|
||||
|
||||
|
||||
```bash
|
||||
git clone https://github.com/sakitam-fdd/maptalks.plot.git
|
||||
npm install
|
||||
npm run dev
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 安装
|
||||
|
||||
#### npm安装
|
||||
|
||||
```bash
|
||||
npm install maptalks.plot --save
|
||||
import maptalksPlot from 'maptalks.plot'
|
||||
```
|
||||
|
||||
#### cdn
|
||||
|
||||
目前可通过 [unpkg.com](https://unpkg.com/maptalks.plot/dist/maptalks.plot.js) 获取最新版本的资源。
|
||||
|
||||
```bash
|
||||
https://unpkg.com/maptalks.plot/dist/maptalks.plot.js
|
||||
https://unpkg.com/maptalks.plot/dist/maptalks.plot.min.js
|
||||
```
|
||||
|
||||
#### [示例](//sakitam-fdd.github.io/maptalks.plot/)
|
||||
|
||||
##### maptalks demo
|
||||
|
||||
``` html
|
||||
<div id="map" class="container"></div>
|
||||
<script src="../node_modules/maptalks/dist/maptalks.js"></script>
|
||||
<script src="../dist/maptalks.plot.js"></script>
|
||||
<script>
|
||||
var map = new maptalks.Map('map', {
|
||||
center: [108.93, 34.27],
|
||||
zoom: 5,
|
||||
baseLayer: new maptalks.TileLayer('base', {
|
||||
urlTemplate: 'https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
|
||||
})
|
||||
});
|
||||
|
||||
var layer = new maptalks.VectorLayer('vector', {
|
||||
enableSimplify : false
|
||||
}).addTo(map);
|
||||
|
||||
var drawTool = new MaptalksPlot.PlotDraw({
|
||||
mode: 'Curve'
|
||||
}).addTo(map).disable();
|
||||
drawTool.on('drawend', function (param) {
|
||||
console.log(param.geometry);
|
||||
if (param.geometry.getPlotType() === 'PlotPoint') {
|
||||
param.geometry.setSymbol({
|
||||
'markerFile': './static/images/5.png',
|
||||
'markerWidth': 28,
|
||||
'markerHeight': 40,
|
||||
'markerDx': 0,
|
||||
'markerDy': 0,
|
||||
'markerOpacity': 1
|
||||
})
|
||||
}
|
||||
layer.addGeometry(param.geometry);
|
||||
});
|
||||
var itemsRight = ['Polygon',
|
||||
'CurveFlag', 'TriangleFlag', 'RectFlag',
|
||||
'RectAngle', 'Circle', 'Ellipse'].map(function (value) {
|
||||
return {
|
||||
item: value,
|
||||
click: function () {
|
||||
drawTool.setMode(value).enable();
|
||||
}
|
||||
};
|
||||
});
|
||||
// right
|
||||
new maptalks.control.Toolbar({
|
||||
position : 'top-right',
|
||||
items: [
|
||||
{
|
||||
item: 'Shape',
|
||||
children: itemsRight
|
||||
},
|
||||
{
|
||||
item: 'Disable',
|
||||
click: function () {
|
||||
drawTool.disable();
|
||||
}
|
||||
},
|
||||
{
|
||||
item: 'Clear',
|
||||
click: function () {
|
||||
layer.clear();
|
||||
}
|
||||
}
|
||||
]
|
||||
}).addTo(map);
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
## 截图示例
|
||||
|
||||
[](https://codepen.io/sakitam-fdd/pen/wpXxNW)
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
> [maptalks](https://github.com/maptalks/maptalks.js)
|
||||
|
||||
BIN
assets/images/plot.jpg
Normal file
BIN
assets/images/plot.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
@ -39,6 +39,16 @@
|
||||
}).addTo(map).disable();
|
||||
drawTool.on('drawend', function (param) {
|
||||
console.log(param.geometry);
|
||||
if (param.geometry.getPlotType() === 'PlotPoint') {
|
||||
param.geometry.setSymbol({
|
||||
'markerFile': './static/images/5.png',
|
||||
'markerWidth': 28,
|
||||
'markerHeight': 40,
|
||||
'markerDx': 0,
|
||||
'markerDy': 0,
|
||||
'markerOpacity': 1
|
||||
})
|
||||
}
|
||||
layer.addGeometry(param.geometry);
|
||||
});
|
||||
var itemsLeft = ['Point', 'Polyline', 'Curve',
|
||||
|
||||
BIN
examples/static/images/5.png
Normal file
BIN
examples/static/images/5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@ -186,19 +186,15 @@ class PlotDraw extends maptalks.MapTool {
|
||||
* @private
|
||||
*/
|
||||
_firstClickHandler (event) {
|
||||
this._createGeometry(event)
|
||||
const registerMode = this._getRegisterMode()
|
||||
const coordinate = event['coordinate']
|
||||
if (this._geometry) {
|
||||
if (this.getMode() === 'point') {
|
||||
this.endDraw(event)
|
||||
if (!this._geometry) {
|
||||
this._createGeometry(event)
|
||||
} else {
|
||||
if (this._clickCoords.length > 0 &&
|
||||
this.getMap().computeLength(coordinate, this._clickCoords[this._clickCoords.length - 1]) < 0.01) {
|
||||
return
|
||||
}
|
||||
if (!registerMode.freehand && registerMode['limitClickCount'] > 1) {
|
||||
if (this.getMap().computeLength(coordinate, this._clickCoords[this._clickCoords.length - 1]) < 0.01) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!(this._historyPointer === null)) {
|
||||
this._clickCoords = this._clickCoords.slice(0, this._historyPointer)
|
||||
}
|
||||
@ -212,6 +208,9 @@ class PlotDraw extends maptalks.MapTool {
|
||||
}
|
||||
this._fireEvent('drawvertex', event)
|
||||
}
|
||||
if (this.getMode() === 'point') {
|
||||
this.endDraw(event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,15 +6,11 @@
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {getMiddlePoint, mathBaseDistance} from '../helper/common'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
MathDistance,
|
||||
getBaseLength,
|
||||
wholeDistance,
|
||||
isClockWise,
|
||||
getQBSplinePoints,
|
||||
getAngleOfThreePoints
|
||||
getThirdPoint, isClockWise,
|
||||
getBaseLength, wholeDistance,
|
||||
getQBSplinePoints, getAngleOfThreePoints
|
||||
} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
// FIXME error
|
||||
@ -39,6 +35,7 @@ class AttackArrow extends maptalks.Polygon {
|
||||
*/
|
||||
_generate () {
|
||||
try {
|
||||
const measurer = this._getMeasurer()
|
||||
const count = this._points.length
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
@ -50,12 +47,12 @@ class AttackArrow extends maptalks.Polygon {
|
||||
tailLeft = _points[1]
|
||||
tailRight = _points[0]
|
||||
}
|
||||
let midTail = Mid(tailLeft, tailRight)
|
||||
let midTail = getMiddlePoint(tailLeft, tailRight)
|
||||
let bonePoints = [midTail].concat(_points.slice(2))
|
||||
let headPoints = this._getArrowHeadPoints(bonePoints, tailLeft, tailRight)
|
||||
let [neckLeft, neckRight] = [headPoints[0], headPoints[4]]
|
||||
let tailWidthFactor = MathDistance(tailLeft, tailRight) / getBaseLength(bonePoints)
|
||||
let bodyPoints = AttackArrow._getArrowBodyPoints(bonePoints, neckLeft, neckRight, tailWidthFactor)
|
||||
let tailWidthFactor = mathBaseDistance(tailLeft, tailRight) / getBaseLength(bonePoints)
|
||||
let bodyPoints = AttackArrow._getArrowBodyPoints(measurer, bonePoints, neckLeft, neckRight, tailWidthFactor)
|
||||
let count = bodyPoints.length
|
||||
let leftPoints = [tailLeft].concat(bodyPoints.slice(0, count / 2))
|
||||
leftPoints.push(neckLeft)
|
||||
@ -83,8 +80,8 @@ class AttackArrow extends maptalks.Polygon {
|
||||
let len = getBaseLength(points)
|
||||
let headHeight = len * 0.18
|
||||
let headPnt = points[points.length - 1]
|
||||
len = MathDistance(headPnt, points[points.length - 2])
|
||||
let tailWidth = MathDistance(tailLeft, tailRight)
|
||||
len = (headPnt, points[points.length - 2])
|
||||
let tailWidth = mathBaseDistance(tailLeft, tailRight)
|
||||
if (headHeight > tailWidth * this.headTailFactor) {
|
||||
headHeight = tailWidth * this.headTailFactor
|
||||
}
|
||||
@ -154,22 +151,23 @@ class AttackArrow extends maptalks.Polygon {
|
||||
|
||||
/**
|
||||
* 插值面部分数据
|
||||
* @param measurer
|
||||
* @param points
|
||||
* @param neckLeft
|
||||
* @param neckRight
|
||||
* @param tailWidthFactor
|
||||
* @returns {*|T[]|string}
|
||||
*/
|
||||
static _getArrowBodyPoints (points, neckLeft, neckRight, tailWidthFactor) {
|
||||
static _getArrowBodyPoints (measurer, points, neckLeft, neckRight, tailWidthFactor) {
|
||||
let allLen = wholeDistance(points)
|
||||
let len = getBaseLength(points)
|
||||
let tailWidth = len * tailWidthFactor
|
||||
let neckWidth = MathDistance(neckLeft, neckRight)
|
||||
let neckWidth = mathBaseDistance(neckLeft, neckRight)
|
||||
let widthDif = (tailWidth - neckWidth) / 2
|
||||
let [tempLen, leftBodyPoints, rightBodyPoints] = [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])
|
||||
tempLen += mathBaseDistance(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)
|
||||
|
||||
89
src/geometry/Point/Point.js
Normal file
89
src/geometry/Point/Point.js
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Created by FDD on 2017/12/12.
|
||||
* @desc 线
|
||||
* @Inherits maptalks.LineString
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
class PlotPoint extends maptalks.Marker {
|
||||
constructor (coordinates, points, options = {}) {
|
||||
super(coordinates, options)
|
||||
this.type = 'PlotPoint'
|
||||
this._coordinates = []
|
||||
if (coordinates) {
|
||||
this._points = coordinates || []
|
||||
this.setCoordinates(coordinates)
|
||||
}
|
||||
}
|
||||
|
||||
_generate () {
|
||||
if (this._points) {
|
||||
this.setCoordinates(this._points)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取geom类型
|
||||
* @returns {string}
|
||||
*/
|
||||
getPlotType () {
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控制点
|
||||
* @returns {Array|*}
|
||||
*/
|
||||
getPoints () {
|
||||
return this._points
|
||||
}
|
||||
|
||||
/**
|
||||
* set point
|
||||
* @param coordinates
|
||||
*/
|
||||
setPoints (coordinates) {
|
||||
this._points = !coordinates ? [] : coordinates
|
||||
if (this._points.length >= 1) {
|
||||
this._generate()
|
||||
}
|
||||
}
|
||||
|
||||
_exportGeoJSONGeometry () {
|
||||
const points = this.getCoordinates()
|
||||
const coordinates = Coordinate.toNumberArrays(points)
|
||||
return {
|
||||
'type': 'Point',
|
||||
'coordinates': coordinates
|
||||
}
|
||||
}
|
||||
|
||||
_toJSON (options) {
|
||||
const opts = maptalks.Util.extend({}, options)
|
||||
const coordinates = this.getCoordinates()
|
||||
opts.geometry = false
|
||||
const feature = this.toGeoJSON(opts)
|
||||
feature['geometry'] = {
|
||||
'type': 'Point'
|
||||
}
|
||||
return {
|
||||
'feature': feature,
|
||||
'subType': 'PlotPoint',
|
||||
'coordinates': coordinates,
|
||||
'points': this.getPoints()
|
||||
}
|
||||
}
|
||||
|
||||
static fromJSON (json) {
|
||||
const feature = json['feature']
|
||||
const _geometry = new PlotPoint(json['coordinates'], json['points'], json['options'])
|
||||
_geometry.setProperties(feature['properties'])
|
||||
return _geometry
|
||||
}
|
||||
}
|
||||
|
||||
PlotPoint.registerJSONType('PlotPoint')
|
||||
|
||||
export default PlotPoint
|
||||
@ -6,12 +6,8 @@
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
getBisectorNormals,
|
||||
getCubicValue
|
||||
} from '../helper/index'
|
||||
import {getMiddlePoint, mathBaseDistance} from '../helper/common'
|
||||
import {getThirdPoint, getBisectorNormals, getCubicValue} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class GatheringPlace extends maptalks.Polygon {
|
||||
constructor (coordinates, points, options = {}) {
|
||||
@ -42,13 +38,12 @@ class GatheringPlace extends maptalks.Polygon {
|
||||
let _points = Coordinate.toNumberArrays(this._points)
|
||||
if (count < 2) return
|
||||
if (count === 2) {
|
||||
let mid = Mid(_points[0], _points[1])
|
||||
const measurer = this._getMeasurer()
|
||||
const distance = measurer.measureLength(Coordinate.toCoordinates(_points[0]), Coordinate.toCoordinates(mid)) / 0.9
|
||||
let pnt = getThirdPoint(measurer, _points[0], mid, Constants.HALF_PI, distance, true)
|
||||
let mid = getMiddlePoint(_points[0], _points[1])
|
||||
const distance = mathBaseDistance(_points[0], mid) / 0.9
|
||||
let pnt = getThirdPoint(_points[0], mid, Constants.HALF_PI, distance, true)
|
||||
_points = [_points[0], pnt, _points[1]]
|
||||
}
|
||||
let mid = Mid(_points[0], _points[2])
|
||||
let mid = getMiddlePoint(_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++) {
|
||||
|
||||
@ -5,14 +5,8 @@
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
import * as Constants from '../../Constants'
|
||||
import {
|
||||
Mid,
|
||||
getThirdPoint,
|
||||
isClockWise,
|
||||
getAzimuth,
|
||||
getArcPoints,
|
||||
getCircleCenterOfThreePoints
|
||||
} from '../helper/index'
|
||||
import {getArcPoints, getMiddlePoint, mathDistance, mathBaseDistance} from '../helper/common'
|
||||
import {getThirdPoint, isClockWise, getAzimuth, getCircleCenterOfThreePoints} from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
class Lune extends maptalks.Polygon {
|
||||
constructor (coordinates, points, options = {}) {
|
||||
@ -38,21 +32,19 @@ class Lune extends maptalks.Polygon {
|
||||
* @private
|
||||
*/
|
||||
_generate () {
|
||||
const measurer = this._getMeasurer()
|
||||
const count = this._points.length
|
||||
let _points = Coordinate.toNumberArrays(this._points)
|
||||
if (count < 2) return
|
||||
const measurer = this._getMeasurer()
|
||||
if (count === 2) {
|
||||
let mid = Mid(_points[0], _points[1])
|
||||
let pnt = getThirdPoint(
|
||||
measurer, _points[0], mid, Constants.HALF_PI,
|
||||
measurer.measureLength(Coordinate.toCoordinates(_points[0]), Coordinate.toCoordinates(mid))
|
||||
)
|
||||
let mid = getMiddlePoint(_points[0], _points[1])
|
||||
let d = mathBaseDistance(_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 = measurer.measureLength(Coordinate.toCoordinates(pnt1), Coordinate.toCoordinates(center))
|
||||
let radius = mathDistance(measurer, pnt1, center)
|
||||
let angle1 = getAzimuth(pnt1, center)
|
||||
let angle2 = getAzimuth(pnt2, center)
|
||||
if (isClockWise(pnt1, pnt2, pnt3)) {
|
||||
|
||||
@ -5,10 +5,8 @@
|
||||
*/
|
||||
|
||||
import * as maptalks from 'maptalks'
|
||||
import {
|
||||
getAzimuth,
|
||||
getArcPoints
|
||||
} from '../helper/index'
|
||||
import { getArcPoints, mathDistance } from '../helper/common'
|
||||
import { getAzimuth } from '../helper/index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
class Sector extends maptalks.Polygon {
|
||||
@ -43,7 +41,7 @@ class Sector extends maptalks.Polygon {
|
||||
} else {
|
||||
let [center, pnt2, pnt3] = [_points[0], _points[1], _points[2]]
|
||||
const measurer = this._getMeasurer()
|
||||
const radius = measurer.measureLength(Coordinate.toCoordinates(pnt2), Coordinate.toCoordinates(center))
|
||||
const radius = mathDistance(measurer, pnt2, center)
|
||||
let startAngle = getAzimuth(pnt2, center)
|
||||
let endAngle = getAzimuth(pnt3, center)
|
||||
let pList = getArcPoints(measurer, center, radius, startAngle, endAngle)
|
||||
|
||||
@ -1,233 +1,120 @@
|
||||
import * as Constants from '../../Constants'
|
||||
// import * as maptalks from 'maptalks'
|
||||
// const Coordinate = maptalks.Coordinate
|
||||
import * as maptalks from 'maptalks'
|
||||
import {getAzimuth} from './index'
|
||||
const Coordinate = maptalks.Coordinate
|
||||
|
||||
/**
|
||||
* 计算两个坐标之间的距离
|
||||
* 获取两点中间位置
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @returns {number}
|
||||
* @constructor
|
||||
*/
|
||||
const mathDistance = (point1, point2) => {
|
||||
return (Math.sqrt(Math.pow((point1['x'] - point2['x']), 2) + Math.pow((point1['y'] - point2['y']), 2)))
|
||||
}
|
||||
|
||||
/**
|
||||
* 求取两个坐标的中间值
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @returns {[*,*]}
|
||||
* @constructor
|
||||
*/
|
||||
const getMiddlePoint = (point1, point2) => {
|
||||
return [(point1['x'] + point2['x']) / 2, (point1['y'] + point2['y']) / 2]
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是顺时针
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @param point3
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isClockWise = (point1, point2, point3) => {
|
||||
return ((point3['y'] - point1['y']) * (point2['x'] - point1['x']) > (point2['y'] - point1['y']) * (point3['x'] - point1['x']))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取立方值
|
||||
* @param t
|
||||
* @param startPnt
|
||||
* @param cPnt1
|
||||
* @param cPnt2
|
||||
* @param endPnt
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
const getCubicValue = (t, startPnt, cPnt1, cPnt2, endPnt) => {
|
||||
t = Math.max(Math.min(t, 1), 0)
|
||||
let [tp, t2] = [(1 - t), (t * t)]
|
||||
let t3 = t2 * t
|
||||
let tp2 = tp * tp
|
||||
let tp3 = tp2 * tp
|
||||
let x = (tp3 * startPnt['x']) + (3 * tp2 * t * cPnt1['x']) + (3 * tp * t2 * cPnt2['x']) + (t3 * endPnt['x'])
|
||||
let y = (tp3 * startPnt['y']) + (3 * tp2 * t * cPnt1['y']) + (3 * tp * t2 * cPnt2['y']) + (t3 * endPnt['y'])
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
/**
|
||||
* getBisectorNormals
|
||||
* @param t
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @param point3
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
const getBisectorNormals = (t, point1, point2, point3) => {
|
||||
let normal = getNormal(point1, point2, point3)
|
||||
let [bisectorNormalRight, bisectorNormalLeft, dt, x1, y1, x2, y2] = [null, null, null, null, null, null, null]
|
||||
let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
|
||||
let uX = normal[0] / dist
|
||||
let uY = normal[1] / dist
|
||||
let d1 = mathDistance(point1, point2)
|
||||
let d2 = mathDistance(point2, point3)
|
||||
if (dist > Constants.ZERO_TOLERANCE) {
|
||||
if (isClockWise(point1, point2, point3)) {
|
||||
dt = t * d1
|
||||
x1 = point2['x'] - dt * uY
|
||||
y1 = point2['y'] + dt * uX
|
||||
bisectorNormalRight = [x1, y1]
|
||||
dt = t * d2
|
||||
x2 = point2['x'] + dt * uY
|
||||
y2 = point2['y'] - dt * uX
|
||||
bisectorNormalLeft = [x2, y2]
|
||||
} else {
|
||||
dt = t * d1
|
||||
x1 = point2['x'] + dt * uY
|
||||
y1 = point2['y'] - dt * uX
|
||||
bisectorNormalRight = [x1, y1]
|
||||
dt = t * d2
|
||||
x2 = point2['x'] - dt * uY
|
||||
y2 = point2['y'] + dt * uX
|
||||
bisectorNormalLeft = [x2, y2]
|
||||
}
|
||||
} else {
|
||||
x1 = point2['x'] + t * (point1['x'] - point2['x'])
|
||||
y1 = point2['y'] + t * (point1['y'] - point2['y'])
|
||||
bisectorNormalRight = [x1, y1]
|
||||
x2 = point2['x'] + t * (point3['x'] - point2['x'])
|
||||
y2 = point2['y'] + t * (point3['y'] - point2['y'])
|
||||
bisectorNormalLeft = [x2, y2]
|
||||
}
|
||||
return [bisectorNormalRight, bisectorNormalLeft]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认三点的内切圆
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @param point3
|
||||
* @returns {*[]}
|
||||
*/
|
||||
const getNormal = (point1, point2, point3) => {
|
||||
let dX1 = point1['x'] - point2['x']
|
||||
let dY1 = point1['y'] - point2['y']
|
||||
let d1 = Math.sqrt(dX1 * dX1 + dY1 * dY1)
|
||||
dX1 /= d1
|
||||
dY1 /= d1
|
||||
let dX2 = point3['x'] - point2['x']
|
||||
let dY2 = point3['y'] - point2['y']
|
||||
let d2 = Math.sqrt(dX2 * dX2 + dY2 * dY2)
|
||||
dX2 /= d2
|
||||
dY2 /= d2
|
||||
let uX = dX1 + dX2
|
||||
let uY = dY1 + dY2
|
||||
return [uX, uY]
|
||||
const getMiddlePoint = (point1, point2) => {
|
||||
return [(point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取左边控制点
|
||||
* @param controlPoints
|
||||
* @param offset
|
||||
* 计算距离
|
||||
* @param measurer
|
||||
* @param pnt1
|
||||
* @param pnt2
|
||||
* @returns {*}
|
||||
*/
|
||||
const mathDistance = (measurer, pnt1, pnt2) => {
|
||||
return measurer.measureLength(Coordinate.toCoordinates(pnt1), Coordinate.toCoordinates(pnt2))
|
||||
}
|
||||
|
||||
/**
|
||||
* 平面坐标距离
|
||||
* @param pnt1
|
||||
* @param pnt2
|
||||
* @returns {number}
|
||||
*/
|
||||
const mathBaseDistance = (pnt1, pnt2) => {
|
||||
return (Math.sqrt(Math.pow((pnt1[0] - pnt2[0]), 2) + Math.pow((pnt1[1] - pnt2[1]), 2)))
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算点集合的总距离
|
||||
* @param measurer
|
||||
* @param points
|
||||
* @returns {number}
|
||||
*/
|
||||
const wholeDistance = (measurer, points) => {
|
||||
let distance = 0
|
||||
if (points && Array.isArray(points) && points.length > 0) {
|
||||
points.forEach((item, index) => {
|
||||
if (index < points.length - 1) {
|
||||
distance += (mathDistance(measurer, item, points[index + 1]))
|
||||
}
|
||||
})
|
||||
}
|
||||
return distance
|
||||
}
|
||||
/**
|
||||
* 获取基础长度
|
||||
* @param measurer
|
||||
* @param points
|
||||
* @returns {number}
|
||||
*/
|
||||
const getBaseLength = (measurer, points) => {
|
||||
return Math.pow(wholeDistance(measurer, points), 0.99)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据起止点和旋转方向求取第三个点
|
||||
* @param measurer
|
||||
* @param startPnt
|
||||
* @param endPnt
|
||||
* @param angle
|
||||
* @param distance
|
||||
* @param clockWise
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
const getLeftMostControlPoint = (controlPoints, offset) => {
|
||||
let [point1, point2, point3, controlX, controlY] = [controlPoints[0], controlPoints[1], controlPoints[2], null, null]
|
||||
let points = getBisectorNormals(0, point1, point2, point3)
|
||||
let normalRight = points[0]
|
||||
let normal = getNormal(point1, point2, point3)
|
||||
let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
|
||||
if (dist > Constants.ZERO_TOLERANCE) {
|
||||
let mid = getMiddlePoint(point1, point2)
|
||||
let pX = point1[0] - mid[0]
|
||||
let pY = point1[1] - mid[1]
|
||||
let d1 = mathDistance(point1, point2)
|
||||
let n = 2.0 / d1
|
||||
let nX = -n * pY
|
||||
let nY = n * pX
|
||||
let a11 = nX * nX - nY * nY
|
||||
let a12 = 2 * nX * nY
|
||||
let a22 = nY * nY - nX * nX
|
||||
let dX = normalRight[0] - mid[0]
|
||||
let dY = normalRight[1] - mid[1]
|
||||
controlX = mid[0] + a11 * dX + a12 * dY
|
||||
controlY = mid[1] + a12 * dX + a22 * dY
|
||||
} else {
|
||||
controlX = point1[0] + offset * (point2[0] - point1[0])
|
||||
controlY = point1[1] + offset * (point2[1] - point1[1])
|
||||
}
|
||||
return [controlX, controlY]
|
||||
const getThirdPoint = (measurer, startPnt, endPnt, angle, distance, clockWise) => {
|
||||
let azimuth = getAzimuth(measurer, startPnt, endPnt)
|
||||
let alpha = clockWise ? (azimuth + angle) : (azimuth - angle)
|
||||
let dx = distance * Math.cos(alpha)
|
||||
let dy = distance * Math.sin(alpha)
|
||||
const vertex = measurer.locate({
|
||||
'x': endPnt[0],
|
||||
'y': endPnt[1]
|
||||
}, dx, dy)
|
||||
return [vertex['x'], vertex['y']]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取右边控制点
|
||||
* @param controlPoints
|
||||
* @param t
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
const getRightMostControlPoint = (controlPoints, t) => {
|
||||
let count = controlPoints.length
|
||||
let point1 = controlPoints[count - 3]
|
||||
let point2 = controlPoints[count - 2]
|
||||
let point3 = controlPoints[count - 1]
|
||||
let pnts = getBisectorNormals(0, point1, point2, point3)
|
||||
let normalLeft = pnts[1]
|
||||
let normal = getNormal(point1, point2, point3)
|
||||
let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
|
||||
let [controlX, controlY] = [null, null]
|
||||
if (dist > Constants.ZERO_TOLERANCE) {
|
||||
let mid = getMiddlePoint(point2, point3)
|
||||
let pX = point3[0] - mid[0]
|
||||
let pY = point3[1] - mid[1]
|
||||
let d1 = mathDistance(point2, point3)
|
||||
let n = 2.0 / d1
|
||||
let nX = -n * pY
|
||||
let nY = n * pX
|
||||
let a11 = nX * nX - nY * nY
|
||||
let a12 = 2 * nX * nY
|
||||
let a22 = nY * nY - nX * nX
|
||||
let dX = normalLeft[0] - mid[0]
|
||||
let dY = normalLeft[1] - mid[1]
|
||||
controlX = mid[0] + a11 * dX + a12 * dY
|
||||
controlY = mid[1] + a12 * dX + a22 * dY
|
||||
} else {
|
||||
controlX = point3[0] + t * (point2[0] - point3[0])
|
||||
controlY = point3[1] + t * (point2[1] - point3[1])
|
||||
}
|
||||
return [controlX, controlY]
|
||||
}
|
||||
|
||||
/**
|
||||
* 插值曲线点
|
||||
* @param offset
|
||||
* @param controlPoints
|
||||
* 插值弓形线段点
|
||||
* @param measurer
|
||||
* @param center
|
||||
* @param radius
|
||||
* @param startAngle
|
||||
* @param endAngle
|
||||
* @param numberOfPoints
|
||||
* @returns {null}
|
||||
*/
|
||||
const getCurvePoints = (offset, controlPoints) => {
|
||||
let leftControl = getLeftMostControlPoint(controlPoints, offset)
|
||||
let [point1, point2, point3, normals, points] = [null, null, null, [leftControl], []]
|
||||
for (let i = 0; i < controlPoints.length - 2; i++) {
|
||||
[point1, point2, point3] = [controlPoints[i], controlPoints[i + 1], controlPoints[i + 2]]
|
||||
let normalPoints = getBisectorNormals(offset, point1, point2, point3)
|
||||
normals = normals.concat(normalPoints)
|
||||
}
|
||||
let rightControl = getRightMostControlPoint(controlPoints, offset)
|
||||
if (rightControl) {
|
||||
normals.push(rightControl)
|
||||
}
|
||||
for (let i = 0; i < controlPoints.length - 1; i++) {
|
||||
point1 = controlPoints[i]
|
||||
point2 = controlPoints[i + 1]
|
||||
points.push(point1)
|
||||
for (let t = 0; t < Constants.FITTING_COUNT; t++) {
|
||||
let pnt = getCubicValue(t / Constants.FITTING_COUNT, point1, normals[i * 2], normals[i * 2 + 1], point2)
|
||||
points.push(pnt)
|
||||
}
|
||||
points.push(point2)
|
||||
const getArcPoints = (measurer, center, radius, startAngle, endAngle, numberOfPoints = 100) => {
|
||||
let [dx, dy, points, angleDiff] = [null, null, [], (endAngle - startAngle)]
|
||||
angleDiff = ((angleDiff < 0) ? (angleDiff + (Math.PI * 2)) : angleDiff)
|
||||
for (let i = 0; i < numberOfPoints; i++) {
|
||||
const rad = angleDiff * i / numberOfPoints + startAngle
|
||||
dx = radius * Math.cos(rad)
|
||||
dy = radius * Math.sin(rad)
|
||||
const vertex = measurer.locate({
|
||||
'x': center[0],
|
||||
'y': center[1]
|
||||
}, dx, dy)
|
||||
points.push([vertex['x'], vertex['y']])
|
||||
}
|
||||
return points
|
||||
}
|
||||
|
||||
export {
|
||||
getCurvePoints
|
||||
getMiddlePoint,
|
||||
getAzimuth,
|
||||
mathDistance,
|
||||
wholeDistance,
|
||||
getBaseLength,
|
||||
getArcPoints,
|
||||
getThirdPoint,
|
||||
mathBaseDistance
|
||||
}
|
||||
|
||||
@ -134,19 +134,6 @@ export const isClockWise = (pnt1, pnt2, pnt3) => {
|
||||
return ((pnt3[1] - pnt1[1]) * (pnt2[0] - pnt1[0]) > (pnt2[1] - pnt1[1]) * (pnt3[0] - pnt1[0]))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取线上的点
|
||||
* @param t
|
||||
* @param startPnt
|
||||
* @param endPnt
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
export const getPointOnLine = (t, startPnt, endPnt) => {
|
||||
let x = startPnt[0] + (t * (endPnt[0] - startPnt[0]))
|
||||
let y = startPnt[1] + (t * (endPnt[1] - startPnt[1]))
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取立方值
|
||||
* @param t
|
||||
@ -169,7 +156,6 @@ export const getCubicValue = (t, startPnt, cPnt1, cPnt2, endPnt) => {
|
||||
|
||||
/**
|
||||
* 根据起止点和旋转方向求取第三个点
|
||||
* @param measurer
|
||||
* @param startPnt
|
||||
* @param endPnt
|
||||
* @param angle
|
||||
@ -177,40 +163,30 @@ export const getCubicValue = (t, startPnt, cPnt1, cPnt2, endPnt) => {
|
||||
* @param clockWise
|
||||
* @returns {[*,*]}
|
||||
*/
|
||||
export const getThirdPoint = (measurer, startPnt, endPnt, angle, distance, clockWise) => {
|
||||
export const getThirdPoint = (startPnt, endPnt, angle, distance, clockWise) => {
|
||||
let azimuth = getAzimuth(startPnt, endPnt)
|
||||
let alpha = clockWise ? (azimuth + angle) : (azimuth - angle)
|
||||
let dx = distance * Math.cos(alpha)
|
||||
let dy = distance * Math.sin(alpha)
|
||||
const vertex = measurer.locate({
|
||||
'x': endPnt[0],
|
||||
'y': endPnt[1]
|
||||
}, dx, dy)
|
||||
return [vertex['x'], vertex['y']]
|
||||
return ([endPnt[0] + dx, endPnt[1] + dy])
|
||||
}
|
||||
|
||||
/**
|
||||
* 插值弓形线段点
|
||||
* @param measurer
|
||||
* @param center
|
||||
* @param radius
|
||||
* @param startAngle
|
||||
* @param endAngle
|
||||
* @param numberOfPoints
|
||||
* @returns {null}
|
||||
*/
|
||||
export const getArcPoints = (measurer, center, radius, startAngle, endAngle, numberOfPoints = 100) => {
|
||||
let [dx, dy, points, angleDiff] = [null, null, [], (endAngle - startAngle)]
|
||||
export const getArcPoints = (center, radius, startAngle, endAngle) => {
|
||||
let [x, y, points, angleDiff] = [null, null, [], (endAngle - startAngle)]
|
||||
angleDiff = ((angleDiff < 0) ? (angleDiff + (Math.PI * 2)) : angleDiff)
|
||||
for (let i = 0; i < numberOfPoints; i++) {
|
||||
const rad = angleDiff * i / numberOfPoints + startAngle
|
||||
dx = radius * Math.cos(rad)
|
||||
dy = radius * Math.sin(rad)
|
||||
const vertex = measurer.locate({
|
||||
'x': center[0],
|
||||
'y': center[1]
|
||||
}, dx, dy)
|
||||
points.push([vertex['x'], vertex['y']])
|
||||
for (let i = 0; i < 200; i++) {
|
||||
const angle = startAngle + angleDiff * i / 200
|
||||
x = center[0] + radius * Math.cos(angle)
|
||||
y = center[1] + radius * Math.sin(angle)
|
||||
points.push([x, y])
|
||||
}
|
||||
return points
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @desc 标绘图形构造类
|
||||
*/
|
||||
import * as maptalks from 'maptalks'
|
||||
|
||||
import PlotPoint from './Point/Point'
|
||||
import Arc from './Polyline/Arc'
|
||||
import Curve from './Polyline/Curve'
|
||||
import Polyline from './Polyline/Polyline'
|
||||
@ -40,15 +40,15 @@ RegisterModes[PlotTypes.POINT] = {
|
||||
'limitClickCount': 1,
|
||||
'action': ['click'],
|
||||
'create': function (path) {
|
||||
return new maptalks.Marker(path[0])
|
||||
return new PlotPoint(path[0])
|
||||
},
|
||||
'update': function (path, geometry) {
|
||||
geometry.setPoints(path)
|
||||
},
|
||||
'generate': function (geometry) {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.ARC] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
@ -63,7 +63,6 @@ RegisterModes[PlotTypes.ARC] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.CURVE] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
@ -77,7 +76,6 @@ RegisterModes[PlotTypes.CURVE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.POLYLINE] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
@ -91,7 +89,6 @@ RegisterModes[PlotTypes.POLYLINE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.FREE_LINE] = {
|
||||
'freehand': true,
|
||||
'action': ['mousedown', 'drag', 'mouseup'],
|
||||
@ -118,7 +115,6 @@ RegisterModes[PlotTypes.ATTACK_ARROW] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.DOUBLE_ARROW] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 4,
|
||||
@ -133,7 +129,6 @@ RegisterModes[PlotTypes.DOUBLE_ARROW] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.FINE_ARROW] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -148,7 +143,6 @@ RegisterModes[PlotTypes.FINE_ARROW] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.ASSAULT_DIRECTION] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -163,7 +157,6 @@ RegisterModes[PlotTypes.ASSAULT_DIRECTION] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// fixme error
|
||||
RegisterModes[PlotTypes.SQUAD_COMBAT] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
@ -204,7 +197,6 @@ RegisterModes[PlotTypes.TAILED_SQUAD_COMBAT] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.STRAIGHT_ARROW] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -219,7 +211,6 @@ RegisterModes[PlotTypes.STRAIGHT_ARROW] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok -2
|
||||
RegisterModes[PlotTypes.CLOSED_CURVE] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
@ -233,7 +224,6 @@ RegisterModes[PlotTypes.CLOSED_CURVE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.LUNE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
@ -248,7 +238,6 @@ RegisterModes[PlotTypes.LUNE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.SECTOR] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
@ -263,7 +252,6 @@ RegisterModes[PlotTypes.SECTOR] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.POLYGON] = {
|
||||
'freehand': false,
|
||||
'action': ['click', 'mousemove', 'dblclick'],
|
||||
@ -277,7 +265,6 @@ RegisterModes[PlotTypes.POLYGON] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.RECTANGLE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -292,7 +279,6 @@ RegisterModes[PlotTypes.RECTANGLE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.FREE_POLYGON] = {
|
||||
'freehand': true,
|
||||
'action': ['mousedown', 'drag', 'mouseup'],
|
||||
@ -306,7 +292,6 @@ RegisterModes[PlotTypes.FREE_POLYGON] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.GATHERING_PLACE] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 3,
|
||||
@ -321,7 +306,6 @@ RegisterModes[PlotTypes.GATHERING_PLACE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.CURVEFLAG] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -336,7 +320,6 @@ RegisterModes[PlotTypes.CURVEFLAG] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.RECTFLAG] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -351,7 +334,6 @@ RegisterModes[PlotTypes.RECTFLAG] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// ok
|
||||
RegisterModes[PlotTypes.TRIANGLEFLAG] = {
|
||||
'freehand': false,
|
||||
'limitClickCount': 2,
|
||||
@ -366,7 +348,6 @@ RegisterModes[PlotTypes.TRIANGLEFLAG] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// 圆
|
||||
RegisterModes[PlotTypes.CIRCLE] = {
|
||||
'freehand': true,
|
||||
'action': ['mousedown', 'drag', 'mouseup'],
|
||||
@ -382,7 +363,6 @@ RegisterModes[PlotTypes.CIRCLE] = {
|
||||
return geometry
|
||||
}
|
||||
}
|
||||
// 椭圆
|
||||
RegisterModes[PlotTypes.ELLIPSE] = {
|
||||
'freehand': true,
|
||||
'action': ['mousedown', 'drag', 'mouseup'],
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
const copyProperties = (target, source) => {
|
||||
for (let key of Reflect.ownKeys(source)) {
|
||||
if (!key.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)) {
|
||||
let desc = Object.getOwnPropertyDescriptor(source, key)
|
||||
Object.defineProperty(target, key, desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mixin = (...mixins) => {
|
||||
class Mix {}
|
||||
// 以编程方式给Mix类添加mixin的所有方法
|
||||
for (let key in mixins) {
|
||||
let mixin = mixins[key]
|
||||
copyProperties(Mix, mixin)
|
||||
copyProperties(Mix.prototype, mixin.prototype)
|
||||
}
|
||||
return Mix
|
||||
}
|
||||
|
||||
export default mixin
|
||||
Loading…
x
Reference in New Issue
Block a user