This commit is contained in:
FDD 2018-01-13 20:44:54 +08:00
parent 718ab779d6
commit 067ef80f14
15 changed files with 368 additions and 350 deletions

View File

@ -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
View File

@ -1 +1,122 @@
# maptalks.plot
> 对 `maptalks` 扩展的 `plot symbol` 的自定义绘制插件
[![Build Status](https://travis-ci.org/sakitam-fdd/maptalks.plot.svg?branch=master)](https://www.travis-ci.org/sakitam-fdd/maptalks.plot)
[![codecov](https://codecov.io/gh/sakitam-fdd/maptalks.plot/branch/master/graph/badge.svg)](https://codecov.io/gh/sakitam-fdd/maptalks.plot)
[![NPM downloads](https://img.shields.io/npm/dm/maptalks.plot.svg)](https://npmjs.org/package/maptalks.plot)
![JS gzip size](http://img.badgesize.io/https://unpkg.com/maptalks.plot/dist/maptalks.plot.js?compression=gzip&label=gzip%20size:%20JS)
[![Npm package](https://img.shields.io/npm/v/maptalks.plot.svg)](https://www.npmjs.org/package/maptalks.plot)
[![GitHub stars](https://img.shields.io/github/stars/sakitam-fdd/maptalks.plot.svg)](https://github.com/sakitam-fdd/maptalks.plot/stargazers)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](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>
```
## 截图示例
[![demo](https://raw.githubusercontent.com/sakitam-fdd/maptalks.plot/master/assets/images/plot.jpg)](https://codepen.io/sakitam-fdd/pen/wpXxNW)
## Resources
> [maptalks](https://github.com/maptalks/maptalks.js)

BIN
assets/images/plot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -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',

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -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)
}
}
/**

View File

@ -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)

View 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

View File

@ -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++) {

View File

@ -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)) {

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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'],

View File

@ -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