diff --git a/.travis.yml b/.travis.yml index 62fef0c..a343dca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/README.md b/README.md index 6631495..108f013 100644 --- a/README.md +++ b/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 +
+ + + +``` + + +## 截图示例 + +[](https://codepen.io/sakitam-fdd/pen/wpXxNW) + + +## Resources + +> [maptalks](https://github.com/maptalks/maptalks.js) diff --git a/assets/images/plot.jpg b/assets/images/plot.jpg new file mode 100644 index 0000000..4b6f5bc Binary files /dev/null and b/assets/images/plot.jpg differ diff --git a/examples/index.html b/examples/index.html index b8a88e0..deb8f2c 100644 --- a/examples/index.html +++ b/examples/index.html @@ -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', diff --git a/examples/static/images/5.png b/examples/static/images/5.png new file mode 100644 index 0000000..5dc9395 Binary files /dev/null and b/examples/static/images/5.png differ diff --git a/src/core/PlotDraw.js b/src/core/PlotDraw.js index 76ad8b9..441dfd9 100644 --- a/src/core/PlotDraw.js +++ b/src/core/PlotDraw.js @@ -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) + } } /** diff --git a/src/geometry/Arrow/AttackArrow.js b/src/geometry/Arrow/AttackArrow.js index 1bbf8ba..09dfe3f 100644 --- a/src/geometry/Arrow/AttackArrow.js +++ b/src/geometry/Arrow/AttackArrow.js @@ -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) diff --git a/src/geometry/Point/Point.js b/src/geometry/Point/Point.js new file mode 100644 index 0000000..5bb7a7c --- /dev/null +++ b/src/geometry/Point/Point.js @@ -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 diff --git a/src/geometry/Polygon/GatheringPlace.js b/src/geometry/Polygon/GatheringPlace.js index fe9d335..26d4b09 100644 --- a/src/geometry/Polygon/GatheringPlace.js +++ b/src/geometry/Polygon/GatheringPlace.js @@ -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++) { diff --git a/src/geometry/Polygon/Lune.js b/src/geometry/Polygon/Lune.js index 615070f..751937f 100644 --- a/src/geometry/Polygon/Lune.js +++ b/src/geometry/Polygon/Lune.js @@ -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)) { diff --git a/src/geometry/Polygon/Sector.js b/src/geometry/Polygon/Sector.js index 64ff143..4162d69 100644 --- a/src/geometry/Polygon/Sector.js +++ b/src/geometry/Polygon/Sector.js @@ -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) diff --git a/src/geometry/helper/common.js b/src/geometry/helper/common.js index 9bae64c..49f379b 100644 --- a/src/geometry/helper/common.js +++ b/src/geometry/helper/common.js @@ -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 } diff --git a/src/geometry/helper/index.js b/src/geometry/helper/index.js index 490b58e..5ed8aa7 100644 --- a/src/geometry/helper/index.js +++ b/src/geometry/helper/index.js @@ -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 } diff --git a/src/geometry/index.js b/src/geometry/index.js index e24b4ac..db03166 100644 --- a/src/geometry/index.js +++ b/src/geometry/index.js @@ -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'], diff --git a/src/utils/mixin.js b/src/utils/mixin.js deleted file mode 100644 index 7cc72b9..0000000 --- a/src/utils/mixin.js +++ /dev/null @@ -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