Path point handling changes

- Store path points as {x,y,z} objects instead of separate arrays
- Project point objects right before layer creation
- A bit slower overall but matches the format of Pl3xmap path points.
This commit is contained in:
James Lyne 2021-07-28 01:56:41 +01:00
parent c69aeb8f5f
commit 9517de0760
11 changed files with 152 additions and 160 deletions

View File

@ -19,7 +19,6 @@ import {defineComponent, computed, onMounted, onUnmounted, watch} from "@vue/run
import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {createArea, updateArea} from "@/util/areas";
import {getPointConverter} from '@/util';
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
@ -50,7 +49,7 @@ export default defineComponent({
layers = Object.freeze(new Map()) as Map<string, LiveAtlasPolygon | LiveAtlasPolyline>,
createAreas = () => {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(currentMap.value);
props.set.areas.forEach((area: LiveAtlasArea, id: string) => {
const layer = createArea(area, converter);
@ -72,18 +71,17 @@ export default defineComponent({
},
handlePendingUpdates = async () => {
const updates = await useStore().dispatch(ActionTypes.POP_AREA_UPDATES, {
const updates = await store.dispatch(ActionTypes.POP_AREA_UPDATES, {
markerSet: props.set.id,
amount: 10,
});
const converter = getPointConverter();
}),
converter = currentMap.value!.locationToLatLng.bind(currentMap.value);
for(const update of updates) {
if(update.removed) {
deleteArea(update.id);
} else {
const layer = updateArea(layers.get(update.id), update.payload as LiveAtlasArea, converter)
const layer = updateArea(layers.get(update.id), update.payload as LiveAtlasArea, converter);
if(!layers.has(update.id)) {
props.layerGroup.addLayer(layer);
@ -103,7 +101,7 @@ export default defineComponent({
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = getPointConverter();
const converter = newValue.locationToLatLng.bind(newValue);
for (const [id, area] of props.set.areas) {
updateArea(layers.get(id), area, converter);

View File

@ -19,7 +19,6 @@ import {defineComponent, computed, onMounted, onUnmounted, watch} from "@vue/run
import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {createCircle, updateCircle} from "@/util/circles";
import {getPointConverter} from '@/util';
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
@ -50,7 +49,7 @@ export default defineComponent({
layers = Object.freeze(new Map<string, LiveAtlasPolyline | LiveAtlasPolygon>()),
createCircles = () => {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
props.set.circles.forEach((circle: LiveAtlasCircle, id: string) => {
const layer = createCircle(circle, converter);
@ -75,9 +74,8 @@ export default defineComponent({
const updates = await useStore().dispatch(ActionTypes.POP_CIRCLE_UPDATES, {
markerSet: props.set.id,
amount: 10,
});
const converter = getPointConverter();
}),
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for(const update of updates) {
if(update.removed) {
@ -103,7 +101,7 @@ export default defineComponent({
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for (const [id, circle] of props.set.circles) {
updateCircle(layers.get(id), circle, converter);

View File

@ -19,7 +19,6 @@ import {defineComponent, computed, onMounted, onUnmounted, watch} from "@vue/run
import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {createLine, updateLine} from "@/util/lines";
import {getPointConverter} from '@/util';
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasLine, LiveAtlasMarkerSet} from "@/index";
@ -49,7 +48,7 @@ export default defineComponent({
layers = Object.freeze(new Map<string, LiveAtlasPolyline>()),
createLines = () => {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
props.set.lines.forEach((line: LiveAtlasLine, id: string) => {
const layer = createLine(line, converter);
@ -74,9 +73,8 @@ export default defineComponent({
const updates = await useStore().dispatch(ActionTypes.POP_LINE_UPDATES, {
markerSet: props.set.id,
amount: 10,
});
const converter = getPointConverter();
}),
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for(const update of updates) {
if(update.removed) {
@ -102,7 +100,7 @@ export default defineComponent({
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for (const [id, line] of props.set.lines) {
updateLine(layers.get(id), line, converter);

View File

@ -21,7 +21,6 @@ import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {createMarker, updateMarker} from "@/util/markers";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {getPointConverter} from "@/util";
import {LiveAtlasMarker, LiveAtlasMarkerSet} from "@/index";
export default defineComponent({
@ -49,7 +48,7 @@ export default defineComponent({
layers = Object.freeze(new Map()) as Map<string, Marker>,
createMarkers = () => {
const converter = getPointConverter();
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
props.set.markers.forEach((marker: LiveAtlasMarker, id: string) => {
const layer = createMarker(marker, converter);
@ -74,9 +73,8 @@ export default defineComponent({
const updates = await useStore().dispatch(ActionTypes.POP_MARKER_UPDATES, {
markerSet: props.set.id,
amount: 10,
});
const converter = getPointConverter();
}),
converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for(const update of updates) {
if(update.removed) {
@ -102,8 +100,10 @@ export default defineComponent({
watch(currentMap, (newValue, oldValue) => {
if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap);
for (const [id, marker] of props.set.markers) {
updateMarker(layers.get(id), marker, getPointConverter());
updateMarker(layers.get(id), marker, converter);
}
}
});

45
src/index.d.ts vendored
View File

@ -203,33 +203,7 @@ interface LiveAtlasMarker {
popupContent?: string;
}
interface LiveAtlasArea {
style: PolylineOptions;
label: string;
isHTML: boolean;
x: Array<number>;
y: PointTuple;
z: Array<number>;
minZoom?: number;
maxZoom?: number;
popupContent?: string;
}
interface LiveAtlasLine {
x: Array<number>;
y: Array<number>;
z: Array<number>;
style: PolylineOptions;
label: string;
isHTML: boolean;
minZoom?: number;
maxZoom?: number;
popupContent?: string;
}
interface LiveAtlasCircle {
location: Coordinate;
radius: PointTuple;
interface LiveAtlasPath {
style: PathOptions;
label: string;
isHTML: boolean;
@ -238,6 +212,23 @@ interface LiveAtlasCircle {
popupContent?: string;
}
interface LiveAtlasArea extends LiveAtlasPath {
style: PolylineOptions;
outline: boolean;
points: Coordinate[] | Coordinate[][] | Coordinate[][][]
}
interface LiveAtlasLine extends LiveAtlasPath {
points: Coordinate[];
style: PolylineOptions;
}
interface LiveAtlasCircle extends LiveAtlasPath {
location: Coordinate;
radius: PointTuple;
style: PathOptions;
}
interface HeadQueueEntry {
cacheKey: string;
name: string;

View File

@ -37,6 +37,8 @@ import {MutationTypes} from "@/store/mutation-types";
import MapProvider from "@/providers/MapProvider";
import {ActionTypes} from "@/store/action-types";
import {endWorldNameRegex, netherWorldNameRegex, titleColoursRegex} from "@/util";
import {getPoints} from "@/util/areas";
import {getLinePoints} from "@/util/lines";
export default class DynmapMapProvider extends MapProvider {
private configurationAbort?: AbortController = undefined;
@ -307,6 +309,11 @@ export default class DynmapMapProvider extends MapProvider {
}
private static buildArea(area: any): LiveAtlasArea {
const opacity = area.fillopacity || 0,
x = area.x || [0, 0],
y: [number, number] = [area.ybottom || 0, area.ytop || 0],
z = area.z || [0, 0];
return {
style: {
color: area.color || '#ff0000',
@ -315,11 +322,10 @@ export default class DynmapMapProvider extends MapProvider {
fillColor: area.fillcolor || '#ff0000',
fillOpacity: area.fillopacity || 0,
},
outline: !opacity,
label: area.label || '',
isHTML: area.markup || false,
x: area.x || [0, 0],
y: [area.ybottom || 0, area.ytop || 0],
z: area.z || [0, 0],
points: getPoints(x, y, z, !opacity),
minZoom: typeof area.minzoom !== 'undefined' && area.minzoom > -1 ? area.minzoom : undefined,
maxZoom: typeof area.maxzoom !== 'undefined' && area.maxzoom > -1 ? area.maxzoom : undefined,
popupContent: area.desc || undefined,
@ -342,9 +348,6 @@ export default class DynmapMapProvider extends MapProvider {
private static buildLine(line: any): LiveAtlasLine {
return {
x: line.x || [0, 0],
y: line.y || [0, 0],
z: line.z || [0, 0],
style: {
color: line.color || '#ff0000',
opacity: line.opacity || 1,
@ -352,6 +355,7 @@ export default class DynmapMapProvider extends MapProvider {
},
label: line.label || '',
isHTML: line.markup || false,
points: getLinePoints(line.x || [0, 0], line.y || [0, 0], line.z || [0, 0]),
minZoom: typeof line.minzoom !== 'undefined' && line.minzoom > -1 ? line.minzoom : undefined,
maxZoom: typeof line.maxzoom !== 'undefined' && line.maxzoom > -1 ? line.maxzoom : undefined,
popupContent: line.desc || undefined,

View File

@ -103,20 +103,6 @@ const tickHeadQueue = () => {
tickHeadQueue();
}
export const getPointConverter = () => {
const map = useStore().state.currentMap;
if(map) {
return (x: number, y: number, z: number) => {
return map.locationToLatLng({x, y, z});
};
} else {
return (x: number, y: number, z: number) => {
return LiveAtlasMapDefinition.defaultProjection.locationToLatLng({x, y, z});
};
}
}
export const parseUrl = () => {
const query = new URLSearchParams(window.location.search),
hash = window.location.hash.replace('#', '');

View File

@ -20,11 +20,11 @@
import {LatLngExpression} from "leaflet";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import {LiveAtlasArea} from "@/index";
import {Coordinate, LiveAtlasArea} from "@/index";
export const createArea = (options: LiveAtlasArea, converter: Function): LiveAtlasPolyline | LiveAtlasPolygon => {
const outline = !options.style.fillOpacity || (options.style.fillOpacity <= 0),
points = getPoints(options, converter, outline),
points = options.points.map(projectPointsMapCallback, converter) as LatLngExpression[] | LatLngExpression[][],
area = outline ? new LiveAtlasPolyline(points, {
...options.style,
minZoom: options.minZoom,
@ -43,14 +43,13 @@ export const createArea = (options: LiveAtlasArea, converter: Function): LiveAtl
};
export const updateArea = (area: LiveAtlasPolyline | LiveAtlasPolygon | undefined, options: LiveAtlasArea, converter: Function): LiveAtlasPolyline | LiveAtlasPolygon => {
const outline = !options.style || !options.style.fillOpacity || (options.style.fillOpacity <= 0) as boolean,
points = getPoints(options, converter, outline);
if (!area) {
return createArea(options, converter);
}
const oldPoints = area.getLatLngs();
const points = options.points.map(projectPointsMapCallback, converter) as LatLngExpression[] | LatLngExpression[][],
oldPoints = area.getLatLngs();
let dirty = false;
//Avoid pointless setStyle() redrawing by checking if styles have actually changed
@ -104,120 +103,129 @@ export const createPopup = (options: LiveAtlasArea): HTMLElement => {
return popup;
};
export const getPoints = (options: LiveAtlasArea, converter: Function, outline: boolean): LatLngExpression[] | LatLngExpression[][] => {
if (options.x.length === 2) { /* Only 2 points */
if (options.y[0] === options.y[1]) {
return get2DBoxPoints(options, converter, outline);
const projectPointsMapCallback = function(this: Function, point: Coordinate | Coordinate[] | Coordinate[][]): LatLngExpression | LatLngExpression[] {
if(Array.isArray(point)) {
return point.map(projectPointsMapCallback, this) as LatLngExpression[];
} else {
// @ts-ignore
return this(point);
}
};
export const getPoints = (x: number[], y: [number, number], z: number[], outline: boolean): Coordinate[] | Coordinate[][] => {
if (x.length === 2) { /* Only 2 points */
if (y[0] === y[1]) {
return get2DBoxPoints(x, y, z, outline);
} else {
return get3DBoxPoints(options, converter);
return get3DBoxPoints(x, y, z);
}
} else {
if (options.y[0] === options.y[1]) {
return get2DShapePoints(options, converter, outline);
if (y[0] === y[1]) {
return get2DShapePoints(x, y, z, outline);
} else {
return get3DShapePoints(options, converter);
return get3DShapePoints(x, y, z);
}
}
};
export const get3DBoxPoints = (options: LiveAtlasArea, converter: Function): LatLngExpression[][] => {
const maxX = options.x[0],
minX = options.x[1],
maxY = options.y[0],
minY = options.y[1],
maxZ = options.z[0],
minZ = options.z[1];
export const get3DBoxPoints = (x: number[], y: [number, number], z: number[]): Coordinate[][] => {
const maxX = x[0],
minX = x[1],
maxY = y[0],
minY = y[1],
maxZ = z[0],
minZ = z[1];
return [
[
converter(minX, minY, minZ),
converter(maxX, minY, minZ),
converter(maxX, minY, maxZ),
converter(minX, minY, maxZ)
{x: minX, y: minY, z: minZ},
{x: maxX, y: minY, z: minZ},
{x: maxX, y: minY, z: maxZ},
{x: minX, y: minY, z: maxZ}
], [
converter(minX, maxY, minZ),
converter(maxX, maxY, minZ),
converter(maxX, maxY, maxZ),
converter(minX, maxY, maxZ)
{x: minX, y: maxY, z: minZ},
{x: maxX, y: maxY, z: minZ},
{x: maxX, y: maxY, z: maxZ},
{x: minX, y: maxY, z: maxZ}
], [
converter(minX, minY, minZ),
converter(minX, maxY, minZ),
converter(maxX, maxY, minZ),
converter(maxX, minY, minZ)
{x: minX, y: minY, z: minZ},
{x: minX, y: maxY, z: minZ},
{x: maxX, y: maxY, z: minZ},
{x: maxX, y: minY, z: minZ}
], [
converter(maxX, minY, minZ),
converter(maxX, maxY, minZ),
converter(maxX, maxY, maxZ),
converter(maxX, minY, maxZ)
{x: maxX, y: minY, z: minZ},
{x: maxX, y: maxY, z: minZ},
{x: maxX, y: maxY, z: maxZ},
{x: maxX, y: minY, z: maxZ}
], [
converter(minX, minY, maxZ),
converter(minX, maxY, maxZ),
converter(maxX, maxY, maxZ),
converter(maxX, minY, maxZ)
{x: minX, y: minY, z: maxZ},
{x: minX, y: maxY, z: maxZ},
{x: maxX, y: maxY, z: maxZ},
{x: maxX, y: minY, z: maxZ}
], [
converter(minX, minY, minZ),
converter(minX, maxY, minZ),
converter(minX, maxY, maxZ),
converter(minX, minY, maxZ)
{x: minX, y: minY, z: minZ},
{x: minX, y: maxY, z: minZ},
{x: minX, y: maxY, z: maxZ},
{x: minX, y: minY, z: maxZ}
]
];
};
export const get2DBoxPoints = (options: LiveAtlasArea, converter: Function, outline: boolean): LatLngExpression[] => {
const maxX = options.x[0],
minX = options.x[1],
minY = options.y[1],
maxZ = options.z[0],
minZ = options.z[1];
export const get2DBoxPoints = (x: number[], y: [number, number], z: number[], outline: boolean): Coordinate[] => {
const maxX = x[0],
minX = x[1],
minY = y[1],
maxZ = z[0],
minZ = z[1];
if (outline) {
return [
converter(minX, minY, minZ),
converter(maxX, minY, minZ),
converter(maxX, minY, maxZ),
converter(minX, minY, maxZ),
converter(minX, minY, minZ)
{x: minX, y: minY, z: minZ},
{x: maxX, y: minY, z: minZ},
{x: maxX, y: minY, z: maxZ},
{x: minX, y: minY, z: maxZ},
{x: minX, y: minY, z: minZ}
];
} else {
return [
converter(minX, minY, minZ),
converter(maxX, minY, minZ),
converter(maxX, minY, maxZ),
converter(minX, minY, maxZ)
{x: minX, y: minY, z: minZ},
{x: maxX, y: minY, z: minZ},
{x: maxX, y: minY, z: maxZ},
{x: minX, y: minY, z: maxZ}
];
}
};
export const get3DShapePoints = (options: LiveAtlasArea, converter: Function): LatLngExpression[][] => {
export const get3DShapePoints = (x: number[], y: [number, number], z: number[]): Coordinate[][] => {
const toplist = [],
botlist = [],
polylist = [];
for (let i = 0; i < options.x.length; i++) {
toplist[i] = converter(options.x[i], options.y[0], options.z[i]);
botlist[i] = converter(options.x[i], options.y[1], options.z[i]);
for (let i = 0; i < x.length; i++) {
toplist[i] = {x: x[i], y: y[0], z: z[i]};
botlist[i] = {x: x[i], y: y[1], z: z[i]};
}
for (let i = 0; i < options.x.length; i++) {
const sidelist = [];
sidelist[0] = toplist[i];
sidelist[1] = botlist[i];
sidelist[2] = botlist[(i + 1) % options.x.length];
sidelist[3] = toplist[(i + 1) % options.x.length];
polylist[i] = sidelist;
for (let i = 0; i < x.length; i++) {
polylist[i] = [
toplist[i],
botlist[i],
botlist[(i + 1) % x.length],
toplist[(i + 1) % x.length],
];
}
polylist[options.x.length] = botlist;
polylist[options.x.length + 1] = toplist;
polylist[x.length] = botlist;
polylist[x.length + 1] = toplist;
return polylist;
};
export const get2DShapePoints = (options: LiveAtlasArea, converter: Function, outline: boolean): LatLngExpression[] => {
export const get2DShapePoints = (x: number[], y: [number, number], z: number[], outline: boolean): Coordinate[] => {
const points = [];
for (let i = 0; i < options.x.length; i++) {
points[i] = converter(options.x[i], options.y[1], options.z[i]);
for (let i = 0; i < x.length; i++) {
points[i] = {x: x[i], y: y[1], z: z[i]};
}
if (outline) {
@ -225,4 +233,4 @@ export const get2DShapePoints = (options: LiveAtlasArea, converter: Function, ou
}
return points;
}
};

View File

@ -84,7 +84,7 @@ export const getCirclePoints = (options: LiveAtlasCircle, converter: Function, o
x = options.radius[0] * Math.sin(rad) + options.location.x,
z = options.radius[1] * Math.cos(rad) + options.location.z;
points.push(converter(x, options.location.y, z));
points.push(converter({x, y:options.location.y, z}));
}
if(outline && points.length) {

View File

@ -17,12 +17,12 @@
* limitations under the License.
*/
import {LatLngExpression} from "leaflet";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import {LiveAtlasLine} from "@/index";
import {Coordinate, LiveAtlasLine} from "@/index";
import {LatLngExpression} from "leaflet";
export const createLine = (options: LiveAtlasLine, converter: Function): LiveAtlasPolyline => {
const points = getLinePoints(options, converter),
const points = options.points.map(projectPointsMapCallback, converter) as LatLngExpression[],
line = new LiveAtlasPolyline(points, {
...options.style,
minZoom: options.minZoom,
@ -37,7 +37,7 @@ export const createLine = (options: LiveAtlasLine, converter: Function): LiveAtl
};
export const updateLine = (line: LiveAtlasPolyline | undefined, options: LiveAtlasLine, converter: Function): LiveAtlasPolyline => {
const points = getLinePoints(options, converter);
const points = options.points.map(projectPointsMapCallback, converter);
if (!line) {
return createLine(options, converter);
@ -53,6 +53,15 @@ export const updateLine = (line: LiveAtlasPolyline | undefined, options: LiveAtl
return line;
}
const projectPointsMapCallback = function(point: Coordinate): LatLngExpression {
if(Array.isArray(point)) {
return projectPointsMapCallback(point);
} else {
// @ts-ignore
return this(point);
}
};
export const createPopup = (options: LiveAtlasLine) => {
const popup = document.createElement('span');
@ -69,11 +78,11 @@ export const createPopup = (options: LiveAtlasLine) => {
return popup;
}
export const getLinePoints = (options: LiveAtlasLine, converter: Function): LatLngExpression[] => {
export const getLinePoints = (x: number[], y: number[], z: number[]): Coordinate[] => {
const points = [];
for(let i = 0; i < options.x.length; i++) {
points.push(converter(options.x[i], options.y[i], options.z[i]));
for(let i = 0; i < x.length; i++) {
points.push({x: x[i], y: y[i], z: z[i]});
}
return points;

View File

@ -23,7 +23,7 @@ import {GenericMarker} from "@/leaflet/marker/GenericMarker";
import {LiveAtlasMarker} from "@/index";
export const createMarker = (options: LiveAtlasMarker, converter: Function): Marker => {
const marker = new GenericMarker(converter(options.location.x, options.location.y, options.location.z), {
const marker = new GenericMarker(converter(options.location), {
icon: new GenericIcon({
icon: options.icon,
label: options.label,
@ -51,7 +51,7 @@ export const updateMarker = (marker: Marker | undefined, options: LiveAtlasMarke
}
const oldLocation = marker.getLatLng(),
newLocation = converter(options.location.x, options.location.y, options.location.z);
newLocation = converter(options.location);
if(!oldLocation.equals(newLocation)) {
marker.setLatLng(newLocation);