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, } }