iobroker.roborock
Version:
125 lines (103 loc) • 3.69 kB
text/typescript
import type { B01MapData } from "../b01/types";
import type { Q10CreatorArea, Q10MapPixelPoint, Q10PixelPose } from "./types";
export const Q10_CANVAS_SCALE = 8;
const ROOM_TAG_REFERENCE_VIEW_WIDTH = 360;
const ROOM_TAG_REFERENCE_VIEW_HEIGHT = 780;
export function getOriginalQ10MapRate(width: number, height: number): number {
const maxSide = Math.max(width, height, 1);
return Math.max(1, Math.floor(2000 / maxSide));
}
export function getQ10ExportCanvasScale(width: number, height: number): number {
const originalScale = getOriginalQ10MapRate(width, height);
return Math.max(3, Math.ceil(originalScale / 3) * 3);
}
export interface Q10AreaPlacement {
centerX: number;
centerY: number;
width: number;
height: number;
angleRad: number;
angleDeg: number;
}
export class Q10MapGeometry {
public constructor(
private readonly data: B01MapData,
private readonly viewScale = 1,
private readonly canvasScale = Q10_CANVAS_SCALE
) {}
public mapPoint(point: Q10MapPixelPoint): Q10MapPixelPoint {
return {
x: point.x * this.canvasScale,
y: point.y * this.canvasScale
};
}
public mapPose(pose: Q10PixelPose | undefined): Q10PixelPose | undefined {
if (!pose) return undefined;
return {
x: pose.x * this.canvasScale,
y: pose.y * this.canvasScale,
phi: pose.phi
};
}
public mapLength(length: number): number {
return length * this.canvasScale;
}
public layoutLengthInMap(layoutUnits: number): number {
return this.layoutLength(layoutUnits) / this.canvasScale;
}
public layoutLength(layoutUnits: number): number {
return (layoutUnits * this.overlayExportScale()) / Math.max(this.viewScale, 0.001);
}
public imgRateLength(layoutUnits: number): number {
return layoutUnits * this.roomTagReferenceKImgRate() * this.overlayExportScale();
}
public quarterMeterTileLengthInMap(): number {
return 0.25 / Math.max(this.data.header.resolution, 0.01);
}
public quarterMeterTileLength(): number {
return this.quarterMeterTileLengthInMap() * this.canvasScale;
}
public mapCanvasSize(): { width: number; height: number } {
return {
width: Math.max(1, this.data.header.sizeX * this.canvasScale),
height: Math.max(1, this.data.header.sizeY * this.canvasScale)
};
}
public originalMapRate(): number {
return getOriginalQ10MapRate(this.data.header.sizeX, this.data.header.sizeY);
}
public exportCanvasScale(): number {
return getQ10ExportCanvasScale(this.data.header.sizeX, this.data.header.sizeY);
}
public canvasScaleValue(): number {
return this.canvasScale;
}
public areaPlacement(area: Q10CreatorArea, outputSpace: "map" | "canvas" = "map"): Q10AreaPlacement {
const scale = outputSpace === "canvas" ? this.canvasScale : 1;
const p0 = area.points[0]!;
const p1 = area.points[1]!;
const p3 = area.points[3]!;
const angleRad = Math.atan2(p1.y - p0.y, p1.x - p0.x);
return {
centerX: ((area.points[0]!.x + area.points[2]!.x) / 2) * scale,
centerY: ((area.points[0]!.y + area.points[2]!.y) / 2) * scale,
width: Math.hypot(p1.x - p0.x, p1.y - p0.y) * scale,
height: Math.hypot(p3.x - p0.x, p3.y - p0.y) * scale,
angleRad,
angleDeg: (angleRad * 180) / Math.PI
};
}
public roomTagReferenceKImgRate(): number {
const width = Math.max(1, this.data.header.sizeX);
const height = Math.max(1, this.data.header.sizeY);
const fitRateX = ROOM_TAG_REFERENCE_VIEW_WIDTH / width;
const fitRateY = ROOM_TAG_REFERENCE_VIEW_HEIGHT / height;
return Math.max(1, Math.min(fitRateX, fitRateY));
}
public overlayExportScale(): number {
return this.canvasScale / this.roomTagReferenceKImgRate();
}
public roomTagExportScale(): number {
return this.overlayExportScale();
}
}