195 lines
6.6 KiB
TypeScript
195 lines
6.6 KiB
TypeScript
import { BottomBase, CanvasW, GroundBase, PillarRatio, RoofTop, RoofTopFar, SideRoomSize, ViewCenter } from "./consts";
|
|
|
|
export type XY = {
|
|
x: number;
|
|
y: number;
|
|
}
|
|
|
|
export type XYWH = {
|
|
x: number;
|
|
y: number;
|
|
w: number;
|
|
h: number;
|
|
}
|
|
|
|
export function intersection(pt1: XY, pt2: XY, result: { x?: number, y?: number }): XY {
|
|
const invalid: XY = { x: result.x || 0, y: result.y || 0 };
|
|
if (typeof result.x === typeof result.y) {
|
|
return invalid;
|
|
}
|
|
|
|
const x1 = pt1.x, y1 = pt1.y, x2 = pt2.x, y2 = pt2.y;
|
|
|
|
if (typeof result.x === 'number') {
|
|
const x3 = result.x;
|
|
|
|
if (x2 === x1) {
|
|
return invalid;
|
|
}
|
|
|
|
result.y = (y2 - y1) * (x3 - x1) / (x2 - x1) + y1;
|
|
} else {
|
|
const y3 = result.y!;
|
|
|
|
if (y2 === y1) {
|
|
return invalid;
|
|
}
|
|
|
|
result.x = (x2 - x1) * (y3 - y1) / (y2 - y1) + x1;
|
|
}
|
|
|
|
return result as any;
|
|
}
|
|
|
|
export function interpolate(pt1: XY, pt2: XY, ratio: number): XY {
|
|
return {
|
|
x: pt1.x + (pt2.x - pt1.x) * ratio,
|
|
y: pt1.y + (pt2.y - pt1.y) * ratio,
|
|
}
|
|
}
|
|
|
|
export function mirror(pt: XY): XY {
|
|
return {
|
|
x: CanvasW - pt.x,
|
|
y: pt.y,
|
|
}
|
|
}
|
|
|
|
export type ControlPts = {
|
|
C1: XY;
|
|
L1: XY;
|
|
B1: XY;
|
|
C2: XY;
|
|
L2: XY;
|
|
B2: XY;
|
|
A1: XY;
|
|
A2: XY;
|
|
B3: XY;
|
|
RoomLT: XY;
|
|
RoomRT: XY;
|
|
RoomRB: XY;
|
|
RoomLB: XY;
|
|
RoomRTFar: XY;
|
|
RoomRBFar: XY;
|
|
RoomLBFar: XY;
|
|
TopRectLB: XY;
|
|
TopRectRB: XY;
|
|
SepsLTLBRBRT: XY[][];
|
|
SepsFront: XYWH[];
|
|
SepsFront1: XYWH[];
|
|
ZmArea: {
|
|
lt0: XY; lt1: XY; lt2: XY; lt3: XY;
|
|
lb0: XY; lb1: XY; lb2: XY; lb3: XY;
|
|
rt0: XY; rt1: XY; rt2: XY; rt3: XY;
|
|
rb0: XY; rb1: XY; rb2: XY; rb3: XY;
|
|
|
|
}[];
|
|
}
|
|
|
|
|
|
|
|
|
|
export function contextCoordinates(unitWidth: number, hole: number): ControlPts {
|
|
const C1 = { x: unitWidth * 0.6, y: GroundBase };
|
|
const L1 = { x: unitWidth* 1, y: GroundBase };
|
|
const B1 = { x: unitWidth , y: BottomBase }
|
|
|
|
const C2 = intersection(ViewCenter, C1, { x: 0, y: undefined });
|
|
const L2 = intersection(ViewCenter, L1, { x: 0, y: undefined });
|
|
const B2 = intersection(ViewCenter, B1, { x: 0, y: undefined });
|
|
|
|
const A1 = { x: L1.x, y: RoofTop };
|
|
const A2 = intersection(ViewCenter, A1, { x: undefined, y: RoofTopFar });
|
|
|
|
const B3 = intersection(ViewCenter, B2, { x: A2.x, y: undefined })
|
|
|
|
const RoomLT = { x: (C1.x + L1.x) * 0.5 - SideRoomSize * 0.5, y: RoofTop - SideRoomSize }
|
|
const RoomRT = { x: (C1.x + L1.x) * 0.5 + SideRoomSize * 0.5, y: RoofTop - SideRoomSize }
|
|
const RoomRB = { x: (C1.x + L1.x) * 0.5 + SideRoomSize * 0.5, y: RoofTop }
|
|
const RoomLB = { x: (C1.x + L1.x) * 0.5 - SideRoomSize * 0.5, y: RoofTop }
|
|
const RoomRBFar = intersection(ViewCenter, RoomRB, { x: undefined, y: RoofTopFar });
|
|
const RoomRTFar = intersection(ViewCenter, RoomRT, { x: RoomRBFar.x, y: undefined });
|
|
const RoomLBFar = { x: RoomRBFar.x! - SideRoomSize, y: RoomRBFar.y };
|
|
|
|
|
|
const TopRectLB = interpolate(RoomRB, RoomRBFar, 0.05);
|
|
const TopRectRB = mirror(TopRectLB);
|
|
|
|
const TopHoleLT = intersection(A1, ViewCenter, { x: undefined, y: TopRectLB.y });
|
|
const TopHoleRT = mirror(TopHoleLT);
|
|
const HolesWidth = TopHoleRT.x - TopHoleLT.x;
|
|
const PillarWidth = (HolesWidth / hole) * PillarRatio;
|
|
const HoleWidth = (HolesWidth - PillarWidth * (hole - 1)) / hole;
|
|
|
|
const SepsLTLBRBRT: XY[][] = [];
|
|
const SepsFront: XYWH[] = [];
|
|
const SepsFront1: XYWH[] = [];
|
|
const ZmArea = [];
|
|
for (let i = 0; i < hole; i++) {
|
|
const TopBase = TopHoleLT.y;
|
|
// 隔断
|
|
if (i > 0) {
|
|
const frontRight1 = TopHoleLT.x + (PillarWidth + HoleWidth) * i;
|
|
const frontRight = i == 1 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i + 21 :
|
|
i == 2 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i + 18 :
|
|
i == 3 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i + 12 :
|
|
i == 4 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i + 6 :
|
|
i == 5 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i + 1 :
|
|
i == 6 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i - 5:
|
|
i == 7 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i - 12 :
|
|
i == 9 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i - 22 :
|
|
i == 8 ? TopHoleLT.x + (PillarWidth + HoleWidth) * i - 15 :
|
|
TopHoleLT.x + (PillarWidth + HoleWidth) * i
|
|
|
|
const frontLeft = frontRight - PillarWidth;
|
|
const frontLeft1 = frontRight1 - PillarWidth;
|
|
SepsFront.push({ x: frontLeft, y: TopBase, w: PillarWidth, h: BottomBase - TopBase });
|
|
SepsFront1.push({ x: frontLeft1, y: TopBase, w: PillarWidth, h: BottomBase - TopBase });
|
|
if (i < hole / 2) {
|
|
// 右侧面
|
|
const p1 = { x: frontRight, y: TopBase };
|
|
const p2 = { x: frontRight, y: BottomBase };
|
|
const p4 = intersection(p1, ViewCenter, { x: undefined, y: RoofTopFar });
|
|
const p3 = intersection(p2, ViewCenter, { x: p4.x, y: undefined });
|
|
SepsLTLBRBRT.push([p1, p2, p3, p4]);
|
|
} else if (i > hole / 2) {
|
|
// 左侧面
|
|
const p1 = { x: frontLeft, y: TopBase };
|
|
const p2 = { x: frontLeft, y: BottomBase };
|
|
const p4 = intersection(p1, ViewCenter, { x: undefined, y: RoofTopFar });
|
|
const p3 = intersection(p2, ViewCenter, { x: p4.x, y: undefined });
|
|
SepsLTLBRBRT.push([p1, p2, p3, p4]);
|
|
}
|
|
}
|
|
|
|
// 闸门面
|
|
{
|
|
const ZmTopBaseFront = TopBase + 6;
|
|
const ZmTopBaseBack = ZmTopBaseFront + 10;
|
|
const lt0 = { x: TopHoleLT.x + (PillarWidth + HoleWidth) * i, y: TopBase };
|
|
const lb0 = { x: lt0.x, y: BottomBase };
|
|
const rb0 = { x: lt0.x + HoleWidth, y: BottomBase };
|
|
const lt1 = intersection(ViewCenter, lt0, { x: undefined, y: ZmTopBaseFront });
|
|
const lt2 = intersection(ViewCenter, lt0, { x: undefined, y: ZmTopBaseBack });
|
|
const lt3 = intersection(ViewCenter, lt0, { x: undefined, y: RoofTopFar });
|
|
const lb1 = intersection(ViewCenter, lb0, { x: lt1.x, y: undefined });
|
|
const lb2 = intersection(ViewCenter, lb0, { x: lt2.x, y: undefined });
|
|
const lb3 = intersection(ViewCenter, lb0, { x: lt3.x, y: undefined });
|
|
const rb1 = intersection(ViewCenter, rb0, { x: undefined, y: lb1.y });
|
|
const rb2 = intersection(ViewCenter, rb0, { x: undefined, y: lb2.y });
|
|
const rb3 = intersection(ViewCenter, rb0, { x: undefined, y: lb3.y });
|
|
const rt0 = { x: rb0.x, y: lt0.y };
|
|
const rt1 = { x: rb1.x, y: lt1.y };
|
|
const rt2 = { x: rb2.x, y: lt2.y };
|
|
const rt3 = { x: rb3.x, y: lt3.y };
|
|
ZmArea.push({ lt0, lb0, rb0, rt0, lt1, rt1, lb1, rb1, lt2, lb2, rt2, rb2, lt3, lb3, rt3, rb3 });
|
|
}
|
|
}
|
|
|
|
return {
|
|
C1, L1, B1, C2, L2, B2, A1, A2, B3,
|
|
RoomLT, RoomRT, RoomRB, RoomLB, RoomRTFar, RoomRBFar, RoomLBFar,
|
|
TopRectLB, TopRectRB,
|
|
SepsLTLBRBRT, SepsFront,SepsFront1, ZmArea,
|
|
}
|
|
} |