From 4f9e8c13fcb5b71650d9bad9e67ae1ed15883ee3 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Mon, 14 Jul 2025 15:11:10 +0800 Subject: [PATCH 1/7] Circle/Ellipse/Sector support ignoreProjection --- packages/maptalks/src/core/util/path.ts | 12 +++++ packages/maptalks/src/geometry/Circle.ts | 30 ++++++++++++- packages/maptalks/src/geometry/Ellipse.ts | 44 ++++++++++++++++++- packages/maptalks/src/geometry/Sector.ts | 24 ++++++++++ .../src/renderer/geometry/VectorRenderer.ts | 3 ++ 5 files changed, 109 insertions(+), 4 deletions(-) diff --git a/packages/maptalks/src/core/util/path.ts b/packages/maptalks/src/core/util/path.ts index d90ca1b857..f551c438bd 100644 --- a/packages/maptalks/src/core/util/path.ts +++ b/packages/maptalks/src/core/util/path.ts @@ -301,3 +301,15 @@ export function getMinMaxAltitude(altitude: number | number[] | number[][]): [nu return [min, max]; } +export function pointsToCoordinates(map, points: Point[], glRes: number, altitude: number): Coordinate[] { + const ring = []; + for (let i = 0, len = points.length; i < len; i++) { + const pt = points[i]; + const c = map.pointAtResToCoordinate(pt, glRes); + c.z = altitude; + ring[i] = c; + } + // ring.push(ring[0].copy()); + return ring; +} + diff --git a/packages/maptalks/src/geometry/Circle.ts b/packages/maptalks/src/geometry/Circle.ts index 1dc46dceb2..ca70cfc51d 100644 --- a/packages/maptalks/src/geometry/Circle.ts +++ b/packages/maptalks/src/geometry/Circle.ts @@ -1,5 +1,5 @@ import { extend, isNil } from '../core/util'; -import { withInEllipse } from '../core/util/path'; +import { pointsToCoordinates, withInEllipse } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; @@ -14,7 +14,8 @@ import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from ' * @instance */ const options: CircleOptionsType = { - 'numberOfShellPoints': 60 + 'numberOfShellPoints': 60, + 'ignoreProjection': false }; /** @@ -93,6 +94,10 @@ export class Circle extends CenterMixin(Polygon) { radius = this.getRadius(); const shell = []; let rad, dx, dy; + const options = this.options as CircleOptionsType; + const ignoreProjection = options.ignoreProjection; + const map = this.getMap(); + for (let i = 0, len = numberOfPoints - 1; i < len; i++) { rad = (360 * i / len) * Math.PI / 180; dx = radius * Math.cos(rad); @@ -100,6 +105,26 @@ export class Circle extends CenterMixin(Polygon) { const vertex = measurer.locate(center, dx, dy); vertex.z = center.z; shell.push(vertex); + if (ignoreProjection) { + break; + } + } + if (ignoreProjection && map) { + const glRes = map.getGLRes(); + const pt = map.coordToPointAtRes(center, glRes); + const p1 = map.coordToPointAtRes(shell[0], glRes); + const r = pt.distanceTo(p1); + const pts: Point[] = []; + for (let i = 0, len = numberOfPoints - 1; i < len; i++) { + rad = (360 * i / len) * Math.PI / 180; + const x = Math.cos(rad) * r + pt.x; + const y = Math.sin(rad) * r + pt.y; + const p = new Point(x, y); + pts[i] = p; + } + const ring = pointsToCoordinates(map, pts, glRes, center.z); + ring.push(ring[0].copy()); + return ring; } shell.push(shell[0]); return shell; @@ -221,4 +246,5 @@ export default Circle; export type CircleOptionsType = PolygonOptionsType & { numberOfShellPoints?: number; + ignoreProjection?: boolean; } diff --git a/packages/maptalks/src/geometry/Ellipse.ts b/packages/maptalks/src/geometry/Ellipse.ts index 9274ddca7e..f09cb938b1 100644 --- a/packages/maptalks/src/geometry/Ellipse.ts +++ b/packages/maptalks/src/geometry/Ellipse.ts @@ -1,5 +1,5 @@ import { extend, isNil, pushIn } from '../core/util'; -import { withInEllipse } from '../core/util/path'; +import { pointsToCoordinates, withInEllipse } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import CenterMixin from './CenterMixin'; import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from './Polygon'; @@ -44,7 +44,8 @@ function angleT(numberOfShellPoints: number) { * @instance */ const options: EllipseOptionsType = { - 'numberOfShellPoints': 81 + 'numberOfShellPoints': 81, + 'ignoreProjection': false }; /** @@ -182,6 +183,44 @@ export class Ellipse extends CenterMixin(Polygon) { } let deg, rad, dx, dy; + const options = this.options as EllipseOptionsType; + const ignoreProjection = options.ignoreProjection; + const map = this.getMap(); + if (ignoreProjection && map) { + const glRes = map.getGLRes(); + const pt = map.coordToPointAtRes(center, glRes); + const c1 = measurer.locate(center, width / 2, 0); + + const p1 = map.coordToPointAtRes(c1, glRes); + //gl width + const w = p1.distanceTo(pt) * 2; + //gl width 高度计算直接利用和宽度的比即可,不用去measurer计算,因为相同的长度,由于投影的影响横轴和纵轴计算结果是不同的 + const h = w * height / width; + const s = Math.pow(w / 2, 2) * Math.pow(h / 2, 2), + sx = Math.pow(w / 2, 2), + sy = Math.pow(h / 2, 2); + const pts: Point[] = []; + for (let i = 0; i < angles.length; i++) { + deg = angles[i]; + rad = deg * Math.PI / 180; + dx = Math.sqrt(s / (sx * Math.pow(Math.tan(rad), 2) + sy)); + dy = Math.sqrt(s / (sy * Math.pow(1 / Math.tan(rad), 2) + sx)); + if (deg > 90 && deg < 270) { + dx *= -1; + } + if (deg > 180 && deg < 360) { + dy *= -1; + } + const p = pt.copy(); + p.x += dx; + p.y += dy; + pts[i] = p; + } + const ring = pointsToCoordinates(map, pts, glRes, center.z); + ring.push(ring[0].copy()); + return ring; + } + for (let i = 0; i < angles.length; i++) { deg = angles[i]; rad = deg * Math.PI / 180; @@ -319,4 +358,5 @@ export default Ellipse; export type EllipseOptionsType = PolygonOptionsType & { numberOfShellPoints?: number; debug?: boolean; + ignoreProjection?: boolean; } diff --git a/packages/maptalks/src/geometry/Sector.ts b/packages/maptalks/src/geometry/Sector.ts index 16a7f754c1..6aade2d827 100644 --- a/packages/maptalks/src/geometry/Sector.ts +++ b/packages/maptalks/src/geometry/Sector.ts @@ -1,4 +1,5 @@ import { extend, isNil } from '../core/util'; +import { pointsToCoordinates } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; @@ -135,6 +136,29 @@ export class Sector extends Circle { // startAngle = this.getStartAngle(), angle = endAngle - startAngle; let rad, dx, dy; + const options = this.options as SectorOptionsType; + const ignoreProjection = options.ignoreProjection; + const map = this.getMap(); + if (ignoreProjection && map) { + const glRes = map.getGLRes(); + const pt = map.coordToPointAtRes(center, glRes); + const c1 = measurer.locate(center, radius, 0); + const p1 = map.coordToPointAtRes(c1, glRes); + const r = pt.distanceTo(p1); + const pts: Point[] = []; + for (let i = 0; i < numberOfPoints; i++) { + rad = (angle * i / (numberOfPoints - 1) + startAngle) * Math.PI / 180; + dx = radius * Math.cos(rad); + dy = radius * Math.sin(rad); + const x = Math.cos(rad) * r + pt.x; + const y = Math.sin(rad) * r + pt.y; + const p = new Point(x, y); + pts[i] = p; + } + const ring = pointsToCoordinates(map, pts, glRes, center.z); + ring.push(center.copy()); + return ring; + } for (let i = 0; i < numberOfPoints; i++) { rad = (angle * i / (numberOfPoints - 1) + startAngle) * Math.PI / 180; dx = radius * Math.cos(rad); diff --git a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts index f5e88b626f..0c97dd7be1 100644 --- a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts +++ b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts @@ -110,6 +110,9 @@ const el = { } const map = this.getMap(); const altitude = this._getAltitude(); + if (this instanceof Ellipse || this instanceof Circle) { + return true; + } // when map is tilting, draw the circle/ellipse as a polygon by vertexes. return altitude > 0 || map.getPitch() || ((this instanceof Ellipse) && map.getBearing()); }, From 10207597110d2e429f9ee3f372032e7e7b088fb0 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 15 Jul 2025 09:56:42 +0800 Subject: [PATCH 2/7] tweaks --- packages/maptalks/src/core/util/path.ts | 14 ++++++++++ packages/maptalks/src/geometry/Circle.ts | 31 ++++++++++------------- packages/maptalks/src/geometry/Ellipse.ts | 15 +++++------ packages/maptalks/src/geometry/Sector.ts | 12 ++++----- 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/packages/maptalks/src/core/util/path.ts b/packages/maptalks/src/core/util/path.ts index f551c438bd..4a78bc0cd1 100644 --- a/packages/maptalks/src/core/util/path.ts +++ b/packages/maptalks/src/core/util/path.ts @@ -313,3 +313,17 @@ export function pointsToCoordinates(map, points: Point[], glRes: number, altitud return ring; } +export function getEllipseGLSize(center: Coordinate, measurer, map, halfWidth: number, halfHeight: number) { + const glRes = map.getGLRes(); + const c1 = measurer.locate(center, halfWidth, 0); + const c2 = measurer.locate(center, 0, halfHeight); + const pt = map.coordToPointAtRes(center, glRes); + const p1 = map.coordToPointAtRes(c1, glRes); + const p2 = map.coordToPointAtRes(c2, glRes); + return { + glWidth: pt.distanceTo(p1), + glHeight: pt.distanceTo(p2), + glCenter: pt + } +} + diff --git a/packages/maptalks/src/geometry/Circle.ts b/packages/maptalks/src/geometry/Circle.ts index ca70cfc51d..418fcacc00 100644 --- a/packages/maptalks/src/geometry/Circle.ts +++ b/packages/maptalks/src/geometry/Circle.ts @@ -1,5 +1,5 @@ import { extend, isNil } from '../core/util'; -import { pointsToCoordinates, withInEllipse } from '../core/util/path'; +import { getEllipseGLSize, pointsToCoordinates, withInEllipse } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; @@ -98,27 +98,15 @@ export class Circle extends CenterMixin(Polygon) { const ignoreProjection = options.ignoreProjection; const map = this.getMap(); - for (let i = 0, len = numberOfPoints - 1; i < len; i++) { - rad = (360 * i / len) * Math.PI / 180; - dx = radius * Math.cos(rad); - dy = radius * Math.sin(rad); - const vertex = measurer.locate(center, dx, dy); - vertex.z = center.z; - shell.push(vertex); - if (ignoreProjection) { - break; - } - } if (ignoreProjection && map) { const glRes = map.getGLRes(); - const pt = map.coordToPointAtRes(center, glRes); - const p1 = map.coordToPointAtRes(shell[0], glRes); - const r = pt.distanceTo(p1); + const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, radius, radius); + const r = Math.max(glWidth, glHeight); const pts: Point[] = []; for (let i = 0, len = numberOfPoints - 1; i < len; i++) { rad = (360 * i / len) * Math.PI / 180; - const x = Math.cos(rad) * r + pt.x; - const y = Math.sin(rad) * r + pt.y; + const x = Math.cos(rad) * r + glCenter.x; + const y = Math.sin(rad) * r + glCenter.y; const p = new Point(x, y); pts[i] = p; } @@ -126,6 +114,15 @@ export class Circle extends CenterMixin(Polygon) { ring.push(ring[0].copy()); return ring; } + for (let i = 0, len = numberOfPoints - 1; i < len; i++) { + rad = (360 * i / len) * Math.PI / 180; + dx = radius * Math.cos(rad); + dy = radius * Math.sin(rad); + const vertex = measurer.locate(center, dx, dy); + vertex.z = center.z; + shell.push(vertex); + } + shell.push(shell[0]); return shell; } diff --git a/packages/maptalks/src/geometry/Ellipse.ts b/packages/maptalks/src/geometry/Ellipse.ts index f09cb938b1..47c1f90cf7 100644 --- a/packages/maptalks/src/geometry/Ellipse.ts +++ b/packages/maptalks/src/geometry/Ellipse.ts @@ -1,5 +1,5 @@ import { extend, isNil, pushIn } from '../core/util'; -import { pointsToCoordinates, withInEllipse } from '../core/util/path'; +import { getEllipseGLSize, pointsToCoordinates, withInEllipse } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import CenterMixin from './CenterMixin'; import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from './Polygon'; @@ -188,14 +188,11 @@ export class Ellipse extends CenterMixin(Polygon) { const map = this.getMap(); if (ignoreProjection && map) { const glRes = map.getGLRes(); - const pt = map.coordToPointAtRes(center, glRes); - const c1 = measurer.locate(center, width / 2, 0); - - const p1 = map.coordToPointAtRes(c1, glRes); + const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, width / 2, height / 2); //gl width - const w = p1.distanceTo(pt) * 2; - //gl width 高度计算直接利用和宽度的比即可,不用去measurer计算,因为相同的长度,由于投影的影响横轴和纵轴计算结果是不同的 - const h = w * height / width; + const w = glWidth * 2; + //gl width + const h = glHeight * 2; const s = Math.pow(w / 2, 2) * Math.pow(h / 2, 2), sx = Math.pow(w / 2, 2), sy = Math.pow(h / 2, 2); @@ -211,7 +208,7 @@ export class Ellipse extends CenterMixin(Polygon) { if (deg > 180 && deg < 360) { dy *= -1; } - const p = pt.copy(); + const p = glCenter.copy(); p.x += dx; p.y += dy; pts[i] = p; diff --git a/packages/maptalks/src/geometry/Sector.ts b/packages/maptalks/src/geometry/Sector.ts index 6aade2d827..231b479d58 100644 --- a/packages/maptalks/src/geometry/Sector.ts +++ b/packages/maptalks/src/geometry/Sector.ts @@ -1,5 +1,5 @@ import { extend, isNil } from '../core/util'; -import { pointsToCoordinates } from '../core/util/path'; +import { getEllipseGLSize, pointsToCoordinates } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; @@ -141,17 +141,15 @@ export class Sector extends Circle { const map = this.getMap(); if (ignoreProjection && map) { const glRes = map.getGLRes(); - const pt = map.coordToPointAtRes(center, glRes); - const c1 = measurer.locate(center, radius, 0); - const p1 = map.coordToPointAtRes(c1, glRes); - const r = pt.distanceTo(p1); + const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, radius, radius); + const r = Math.max(glWidth, glHeight); const pts: Point[] = []; for (let i = 0; i < numberOfPoints; i++) { rad = (angle * i / (numberOfPoints - 1) + startAngle) * Math.PI / 180; dx = radius * Math.cos(rad); dy = radius * Math.sin(rad); - const x = Math.cos(rad) * r + pt.x; - const y = Math.sin(rad) * r + pt.y; + const x = Math.cos(rad) * r + glCenter.x; + const y = Math.sin(rad) * r + glCenter.y; const p = new Point(x, y); pts[i] = p; } From 32a8aa24ac3bcb50a4e39d03fc11c3fdf10a27de Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 11 Nov 2025 14:43:29 +0800 Subject: [PATCH 3/7] Rectangle support --- packages/maptalks/src/core/util/path.ts | 20 +++++++++++++------- packages/maptalks/src/geometry/Circle.ts | 9 ++++++--- packages/maptalks/src/geometry/Ellipse.ts | 8 ++++---- packages/maptalks/src/geometry/Rectangle.ts | 18 +++++++++++++++++- packages/maptalks/src/geometry/Sector.ts | 2 +- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/maptalks/src/core/util/path.ts b/packages/maptalks/src/core/util/path.ts index f65ebee404..94dd3c4c50 100644 --- a/packages/maptalks/src/core/util/path.ts +++ b/packages/maptalks/src/core/util/path.ts @@ -313,17 +313,23 @@ export function pointsToCoordinates(map, points: Point[], glRes: number, altitud return ring; } +const WORLD_CENTER = new Coordinate(0, 0); + export function getEllipseGLSize(center: Coordinate, measurer, map, halfWidth: number, halfHeight: number) { const glRes = map.getGLRes(); - const c1 = measurer.locate(center, halfWidth, 0); - const c2 = measurer.locate(center, 0, halfHeight); - const pt = map.coordToPointAtRes(center, glRes); + const c1 = measurer.locate(WORLD_CENTER, 1, 0); + // const c2 = measurer.locate(CENTER, 0, halfHeight); + const glCenter = map.coordToPointAtRes(center, glRes); + const p0 = map.coordToPointAtRes(WORLD_CENTER, glRes); const p1 = map.coordToPointAtRes(c1, glRes); - const p2 = map.coordToPointAtRes(c2, glRes); + // const p2 = map.coordToPointAtRes(c2, glRes); + const glWidth = p0.distanceTo(p1) * halfWidth; + const glHeight = glWidth * halfHeight / halfWidth; + return { - glWidth: pt.distanceTo(p1), - glHeight: pt.distanceTo(p2), - glCenter: pt + glWidth, + glHeight, + glCenter } } diff --git a/packages/maptalks/src/geometry/Circle.ts b/packages/maptalks/src/geometry/Circle.ts index 418fcacc00..c135749fae 100644 --- a/packages/maptalks/src/geometry/Circle.ts +++ b/packages/maptalks/src/geometry/Circle.ts @@ -101,12 +101,12 @@ export class Circle extends CenterMixin(Polygon) { if (ignoreProjection && map) { const glRes = map.getGLRes(); const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, radius, radius); - const r = Math.max(glWidth, glHeight); + const R = Math.max(glWidth, glHeight); const pts: Point[] = []; for (let i = 0, len = numberOfPoints - 1; i < len; i++) { rad = (360 * i / len) * Math.PI / 180; - const x = Math.cos(rad) * r + glCenter.x; - const y = Math.sin(rad) * r + glCenter.y; + const x = Math.cos(rad) * R + glCenter.x; + const y = Math.sin(rad) * R + glCenter.y; const p = new Point(x, y); pts[i] = p; } @@ -243,5 +243,8 @@ export default Circle; export type CircleOptionsType = PolygonOptionsType & { numberOfShellPoints?: number; +} & SpecialGeometryOptionsType; + +export type SpecialGeometryOptionsType = { ignoreProjection?: boolean; } diff --git a/packages/maptalks/src/geometry/Ellipse.ts b/packages/maptalks/src/geometry/Ellipse.ts index 47c1f90cf7..7d61ed73de 100644 --- a/packages/maptalks/src/geometry/Ellipse.ts +++ b/packages/maptalks/src/geometry/Ellipse.ts @@ -3,7 +3,7 @@ import { getEllipseGLSize, pointsToCoordinates, withInEllipse } from '../core/ut import Coordinate from '../geo/Coordinate'; import CenterMixin from './CenterMixin'; import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from './Polygon'; -import Circle from './Circle'; +import Circle, { SpecialGeometryOptionsType } from './Circle'; import Point from '../geo/Point'; import Extent from '../geo/Extent'; @@ -191,8 +191,9 @@ export class Ellipse extends CenterMixin(Polygon) { const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, width / 2, height / 2); //gl width const w = glWidth * 2; - //gl width + //gl height const h = glHeight * 2; + const s = Math.pow(w / 2, 2) * Math.pow(h / 2, 2), sx = Math.pow(w / 2, 2), sy = Math.pow(h / 2, 2); @@ -355,5 +356,4 @@ export default Ellipse; export type EllipseOptionsType = PolygonOptionsType & { numberOfShellPoints?: number; debug?: boolean; - ignoreProjection?: boolean; -} +} & SpecialGeometryOptionsType; diff --git a/packages/maptalks/src/geometry/Rectangle.ts b/packages/maptalks/src/geometry/Rectangle.ts index 7d8ac23c7f..754e675577 100644 --- a/packages/maptalks/src/geometry/Rectangle.ts +++ b/packages/maptalks/src/geometry/Rectangle.ts @@ -1,8 +1,10 @@ import { extend, isNil } from '../core/util'; +import { getEllipseGLSize, pointsToCoordinates } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; import { CommonProjectionType } from '../geo/projection'; +import { SpecialGeometryOptionsType } from './Circle'; import Polygon, { PolygonOptionsType, RingCoordinates, RingsCoordinates } from './Polygon'; /** @@ -144,6 +146,20 @@ export class Rectangle extends Polygon { sy = 1; } } + const options = this.options as RectangleOptionsType; + const ignoreProjection = options.ignoreProjection; + if (map && ignoreProjection) { + const center = nw, width = this._width, height = this._height; + const { glWidth, glHeight, glCenter } = getEllipseGLSize(center, measurer, map, width, height); + const p1 = glCenter.add(glWidth * sx, 0); + const p2 = glCenter.add(glWidth * sx, glHeight * sy); + const p3 = glCenter.add(0, glHeight * sy); + const glRes = map.getGLRes(); + + const coordinates = pointsToCoordinates(map, [glCenter, p1, p2, p3] as Point[], glRes, center.z); + return coordinates; + } + const points = []; points.push(nw); const p0 = measurer.locate(nw, sx * this._width, 0); @@ -348,4 +364,4 @@ Rectangle.registerJSONType('Rectangle'); export default Rectangle; -export type RectangleOptionsType = PolygonOptionsType; +export type RectangleOptionsType = PolygonOptionsType & SpecialGeometryOptionsType; diff --git a/packages/maptalks/src/geometry/Sector.ts b/packages/maptalks/src/geometry/Sector.ts index 74cf82528c..cfa3a01673 100644 --- a/packages/maptalks/src/geometry/Sector.ts +++ b/packages/maptalks/src/geometry/Sector.ts @@ -268,5 +268,5 @@ Sector.registerJSONType('Sector'); export default Sector; export type SectorOptionsType = CircleOptionsType & { - numberOfShellPoints?: number; + } From 3f20518fb586eda7351bf23a2d3924cfdc42063c Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 11 Nov 2025 14:44:46 +0800 Subject: [PATCH 4/7] updates --- packages/maptalks/src/renderer/geometry/VectorRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts index 0c97dd7be1..7733b03d16 100644 --- a/packages/maptalks/src/renderer/geometry/VectorRenderer.ts +++ b/packages/maptalks/src/renderer/geometry/VectorRenderer.ts @@ -110,7 +110,7 @@ const el = { } const map = this.getMap(); const altitude = this._getAltitude(); - if (this instanceof Ellipse || this instanceof Circle) { + if ((this instanceof Ellipse || this instanceof Circle || this instanceof Rectangle) && this.options.ignoreProjection) { return true; } // when map is tilting, draw the circle/ellipse as a polygon by vertexes. From eeb5f2f67d03b5c70b51eb7492c9fb160b244886 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 11 Nov 2025 14:49:01 +0800 Subject: [PATCH 5/7] fix lint --- packages/maptalks/src/geometry/Sector.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/maptalks/src/geometry/Sector.ts b/packages/maptalks/src/geometry/Sector.ts index cfa3a01673..0d11b9e82c 100644 --- a/packages/maptalks/src/geometry/Sector.ts +++ b/packages/maptalks/src/geometry/Sector.ts @@ -267,6 +267,4 @@ Sector.registerJSONType('Sector'); export default Sector; -export type SectorOptionsType = CircleOptionsType & { - -} +export type SectorOptionsType = CircleOptionsType; From b47b4f47783380ef1b0c6b2c96b3b86b67caeba1 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 11 Nov 2025 16:16:09 +0800 Subject: [PATCH 6/7] updates --- packages/maptalks/src/core/util/path.ts | 33 +++ packages/maptalks/src/geometry/CenterMixin.ts | 207 +++++++++--------- packages/maptalks/src/geometry/Rectangle.ts | 6 +- 3 files changed, 145 insertions(+), 101 deletions(-) diff --git a/packages/maptalks/src/core/util/path.ts b/packages/maptalks/src/core/util/path.ts index 94dd3c4c50..20eba7ae3c 100644 --- a/packages/maptalks/src/core/util/path.ts +++ b/packages/maptalks/src/core/util/path.ts @@ -333,6 +333,39 @@ export function getEllipseGLSize(center: Coordinate, measurer, map, halfWidth: n } } +export function getIgnoreProjectionGeometryCenter(geo) { + const ignoreProjection = geo.options.ignoreProjection; + if (ignoreProjection) { + const ring = geo.getShell ? geo.getShell() : null; + if (ring && ring.length) { + const map = geo.getMap(); + if (!map) { + return; + } + const glRes = map.getGLRes(); + const points = ring.map(c => { + return map.coordToPointAtRes(c, glRes); + }) + + let sumx = 0, + sumy = 0, + counter = 0; + const size = points.length; + for (let i = 0; i < size; i++) { + if (points[i]) { + if (isNumber(points[i].x) && isNumber(points[i].y)) { + sumx += points[i].x; + sumy += points[i].y; + counter++; + } + } + } + const p = new Point(sumx / counter, sumy / counter); + return map.pointAtResToCoordinate(p, glRes); + } + } +} + /** * point left segment * @param p diff --git a/packages/maptalks/src/geometry/CenterMixin.ts b/packages/maptalks/src/geometry/CenterMixin.ts index 54060a9ac8..8fcc249c37 100644 --- a/packages/maptalks/src/geometry/CenterMixin.ts +++ b/packages/maptalks/src/geometry/CenterMixin.ts @@ -1,4 +1,6 @@ import { MixinConstructor } from '../core/Mixin'; +import { isNumber } from '../core/util'; +import { getIgnoreProjectionGeometryCenter } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Point from '../geo/Point'; @@ -12,112 +14,117 @@ import type { Map } from '../map'; * @mixin CenterMixin */ export default function (Base: T) { - return class extends Base { - //@internal - _coordinates: Coordinate - //@internal - _pcenter: Coordinate - //@internal - _dirtyCoords: boolean - getMap?(): Map - //@internal - _getProjection?(): CommonProjectionType - onPositionChanged?(): void - //@internal - _verifyProjection?(): void - //@internal - _clearCache?(): void - //@internal - _translateRotatePivot?(coordinate: Coordinate): this; - /** - * 获取几何图形的中心点 - * @english - * Get geometry's center - * @return {Coordinate} - center of the geometry - * @function CenterMixin.getCoordinates - */ - getCoordinates(): Coordinate { - return this._coordinates; - } + return class extends Base { + //@internal + _coordinates: Coordinate + //@internal + _pcenter: Coordinate + //@internal + _dirtyCoords: boolean + getMap?(): Map + //@internal + _getProjection?(): CommonProjectionType + onPositionChanged?(): void + //@internal + _verifyProjection?(): void + //@internal + _clearCache?(): void + //@internal + _translateRotatePivot?(coordinate: Coordinate): this; + getShell?(); + /** + * 获取几何图形的中心点 + * @english + * Get geometry's center + * @return {Coordinate} - center of the geometry + * @function CenterMixin.getCoordinates + */ + getCoordinates(): Coordinate { + return this._coordinates; + } - /** - * 设置几何图形的中心点 - * @english - * Set a new center to the geometry - * @param {Coordinate|Number[]} coordinates - new center - * @return {Geometry} this - * @fires Geometry#positionchange - * @function CenterMixin.setCoordinates - */ - setCoordinates(coordinates: Coordinate | Array) { - const center = (coordinates instanceof Coordinate) ? coordinates : new Coordinate(coordinates as [number, number, number]); - this._translateRotatePivot(center); - this._coordinates = center; - if (!this.getMap()) { - //When not on a layer or when creating a new one, temporarily save the coordinates, - this._dirtyCoords = true; - this.onPositionChanged(); - return this; - } - const projection = this._getProjection(); - this._setPrjCoordinates(projection.project(this._coordinates)); - return this; - } + /** + * 设置几何图形的中心点 + * @english + * Set a new center to the geometry + * @param {Coordinate|Number[]} coordinates - new center + * @return {Geometry} this + * @fires Geometry#positionchange + * @function CenterMixin.setCoordinates + */ + setCoordinates(coordinates: Coordinate | Array) { + const center = (coordinates instanceof Coordinate) ? coordinates : new Coordinate(coordinates as [number, number, number]); + this._translateRotatePivot(center); + this._coordinates = center; + if (!this.getMap()) { + //When not on a layer or when creating a new one, temporarily save the coordinates, + this._dirtyCoords = true; + this.onPositionChanged(); + return this; + } + const projection = this._getProjection(); + this._setPrjCoordinates(projection.project(this._coordinates)); + return this; + } - //Gets view point of the geometry's center - //@internal - _getCenter2DPoint(res?: number): Point { - const map = this.getMap(); - if (!map) { - return null; - } - const pcenter = this._getPrjCoordinates(); - if (!pcenter) { return null; } - if (!res) { - res = map._getResolution(); - } - return map._prjToPointAtRes(pcenter, res); - } + //Gets view point of the geometry's center + //@internal + _getCenter2DPoint(res?: number): Point { + const map = this.getMap(); + if (!map) { + return null; + } + const pcenter = this._getPrjCoordinates(); + if (!pcenter) { return null; } + if (!res) { + res = map._getResolution(); + } + return map._prjToPointAtRes(pcenter, res); + } - //@internal - _getPrjCoordinates(): Coordinate { - const projection = this._getProjection(); - this._verifyProjection(); - if (!this._pcenter && projection) { - if (this._coordinates) { - this._pcenter = projection.project(this._coordinates); - } - } - return this._pcenter; + //@internal + _getPrjCoordinates(): Coordinate { + const projection = this._getProjection(); + this._verifyProjection(); + if (!this._pcenter && projection) { + if (this._coordinates) { + this._pcenter = projection.project(this._coordinates); } + } + return this._pcenter; + } - //Set center by projected coordinates - //@internal - _setPrjCoordinates(pcenter: Coordinate): void { - this._pcenter = pcenter; - this.onPositionChanged(); - } + //Set center by projected coordinates + //@internal + _setPrjCoordinates(pcenter: Coordinate): void { + this._pcenter = pcenter; + this.onPositionChanged(); + } - //update cached const iables if geometry is updated. - //@internal - _updateCache(): void { - this._clearCache(); - const projection = this._getProjection(); - if (this._pcenter && projection) { - this._coordinates = projection.unproject(this._pcenter); - } - } + //update cached const iables if geometry is updated. + //@internal + _updateCache(): void { + this._clearCache(); + const projection = this._getProjection(); + if (this._pcenter && projection) { + this._coordinates = projection.unproject(this._pcenter); + } + } - //@internal - _clearProjection(): void { - this._pcenter = null; - // @ts-expect-error todo - super._clearProjection(); - } + //@internal + _clearProjection(): void { + this._pcenter = null; + // @ts-expect-error todo + super._clearProjection(); + } - //@internal - _computeCenter(): Coordinate | null { - return this._coordinates ? this._coordinates.copy() : null; - } - }; + //@internal + _computeCenter(): Coordinate | null { + const center = getIgnoreProjectionGeometryCenter(this); + if (center) { + return center; + } + return this._coordinates ? this._coordinates.copy() : null; + } + }; } diff --git a/packages/maptalks/src/geometry/Rectangle.ts b/packages/maptalks/src/geometry/Rectangle.ts index 754e675577..40c1aa6577 100644 --- a/packages/maptalks/src/geometry/Rectangle.ts +++ b/packages/maptalks/src/geometry/Rectangle.ts @@ -1,5 +1,5 @@ import { extend, isNil } from '../core/util'; -import { getEllipseGLSize, pointsToCoordinates } from '../core/util/path'; +import { getEllipseGLSize, getIgnoreProjectionGeometryCenter, pointsToCoordinates } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Extent from '../geo/Extent'; import Point from '../geo/Point'; @@ -252,6 +252,10 @@ export class Rectangle extends Polygon { //@internal _computeCenter(measurer?: any): Coordinate { + const center = getIgnoreProjectionGeometryCenter(this); + if (center) { + return center; + } return measurer.locate(this._coordinates, this._width / 2, -this._height / 2); } From ba3954451ac20be07f5b3c93ccff9754e1d3d472 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Tue, 11 Nov 2025 16:29:59 +0800 Subject: [PATCH 7/7] updates --- packages/maptalks/src/geometry/CenterMixin.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/maptalks/src/geometry/CenterMixin.ts b/packages/maptalks/src/geometry/CenterMixin.ts index 8fcc249c37..0ed354930f 100644 --- a/packages/maptalks/src/geometry/CenterMixin.ts +++ b/packages/maptalks/src/geometry/CenterMixin.ts @@ -1,6 +1,4 @@ import { MixinConstructor } from '../core/Mixin'; -import { isNumber } from '../core/util'; -import { getIgnoreProjectionGeometryCenter } from '../core/util/path'; import Coordinate from '../geo/Coordinate'; import Point from '../geo/Point'; @@ -120,10 +118,6 @@ export default function (Base: T) { //@internal _computeCenter(): Coordinate | null { - const center = getIgnoreProjectionGeometryCenter(this); - if (center) { - return center; - } return this._coordinates ? this._coordinates.copy() : null; } };