import { CylinderGeometry, EdgesGeometry, Geometry, LineSegments, Matrix4, Mesh, MeshBasicMaterial, Shape, Vector2, Vector3 } from 'three'; import { boardUVGenerator2, ExtrudeSolid, Polyline } from 'webcad_ue4_api'; import { ColorMaterial } from './ColorPalette'; import { polar } from './GeUtils'; import { edgeMaterial } from './Material'; //解析二维圆弧类. export class Arc2d { m_StartAn: number; m_EndAn: number; m_StartPoint: Vector2; m_EndPoint: Vector2; m_Center: Vector2; m_Radius: number; constructor(p1: Vector2, p2: Vector2, bul: number) { this.m_StartPoint = p1.clone(); this.m_EndPoint = p2.clone(); let vec: Vector2 = p2.clone().sub(p1); let len = vec.length(); let an = vec.angle(); this.m_Radius = len / Math.sin(2 * Math.atan(bul)) / 2; let allAngle = Math.atan(bul) * 4; let delDis = bul * len / 2; let toDis = this.m_Radius - delDis; an += Math.PI * 0.5; this.m_Center = p1.clone().add(p2); this.m_Center.multiplyScalar(0.5); polar(this.m_Center, an, toDis); this.m_StartAn = p1.clone().sub(this.m_Center).angle(); this.m_EndAn = p2.clone().sub(this.m_Center).angle(); if (bul < 0) { //一个神奇的特性 它需要这么做 this.m_StartAn -= Math.PI; this.m_EndAn -= Math.PI; } } } //创建轮廓 通过点表和凸度 export function createPath(pts: Vector2[], buls: number[], shapeOut?: Shape): Shape { let shape = shapeOut || new Shape(); if (pts.length === 0) return shape; let firstPt = pts[0]; shape.moveTo(firstPt.x, firstPt.y); for (let i = 0; i < pts.length - 1; i++) { let nextPt = pts[i + 1]; if (buls[i] == 0) { shape.lineTo(nextPt.x, nextPt.y); } else { let pt = pts[i]; //参考 //http://www.dorodnic.com/blog/tag/three-js/ 绘制一个齿轮 //https://www.kirupa.com/html5/drawing_circles_canvas.htm //html5 let arc2 = new Arc2d(pt, nextPt, buls[i]); let cen = arc2.m_Center; shape.absarc(cen.x, cen.y, arc2.m_Radius, arc2.m_StartAn, arc2.m_EndAn, buls[i] < 0); } } return shape; } export function getVec(data: object): Vector3 { return new Vector3(data["x"], data["y"], data["z"]); } function Conver2Ext(boardData: object): ExtrudeSolid { let pts: Vector2[] = []; let buls: number[] = []; let boardPts = boardData["Pts"]; let boardBuls = boardData["Buls"]; let boardHeight = boardData["H"]; let boardMat = new Matrix4(); let matInv: Matrix4 = new Matrix4(); //InitBoardMat let xD = getVec(boardData["XVec"]); let yD = getVec(boardData["YVec"]); let ZD = getVec(boardData["ZVec"]); let pBase = getVec(boardData["BasePoint"]); pBase.add(ZD.clone().multiplyScalar(-boardHeight)); boardMat.makeBasis(xD, yD, ZD); boardMat.setPosition(pBase); matInv.getInverse(boardMat); if (boardPts && boardPts.length !== 0) for (let i = 0; i < boardPts.length; i++) { let pt = getVec(boardPts[i]); if (boardPts[i].z !== undefined) pt.applyMatrix4(matInv); pts.push(new Vector2(pt.x, pt.y)); buls.push(boardBuls[i]); } else { let length = boardData["L"]; let width = boardData["W"]; pts.push(new Vector2(0, 0), new Vector2(width, 0), new Vector2(width, length), new Vector2(0, length), new Vector2(0, 0) ); buls.push(0, 0, 0, 0, 0); } let ext = new ExtrudeSolid(); ext.OCSNoClone.copy(boardMat); let pl = new Polyline(pts.map((p, i) => { return { pt: p, bul: buls[i] }; })); ext.Thickness = boardHeight; ext.ContourCurve = pl; if (checkObjectArray(boardData, "SubBoardLocal")) ext.Grooves.push(...boardData["SubBoardLocal"].map(Conver2Ext)); return ext; } //创建板件 暂时这么写 export function createBoard(boardData: object, boardMaterial: MeshBasicMaterial) { let ext = Conver2Ext(boardData); if (boardData["BoardName"] === "地脚线") Object.defineProperty(ext, "UCGenerator", { get: function () { return boardUVGenerator2; }, }); //板件被镜像时. // if (!equalv3(xD.clone().cross(yD), ZD)) // { // for (let f of ext.faces) // [f.a, f.c] = [f.c, f.a]; // } //边 let edges: (LineSegments | Mesh)[] = [new LineSegments(ext.EdgeGeometry, edgeMaterial)]; edges[0].applyMatrix4(ext.OCSNoClone); if (checkObjectArray(boardData, "Drillings")) { let dris = boardData["Drillings"]; for (let dri of dris) { let geo = new CylinderGeometry(dri.r, dri.r, dri.h, 8); geo.rotateX(Math.PI * 0.5); if (dri.f === 0) //0正 geo.translate(dri.x, dri.y, -dri.h * 0.5 + boardData["H"]); else //1反 geo.translate(dri.x, dri.y, dri.h * 0.5); geo.applyMatrix4(ext.OCSNoClone); let mesh = new Mesh(geo, ColorMaterial.GetBasicMaterial(1)); edges.push(mesh); } } let mesh = new Mesh(ext.MeshGeometry, boardMaterial); mesh.userData = ext.Normal; edges.forEach(e => e.userData = ext.Normal); mesh.applyMatrix4(ext.OCSNoClone); mesh.updateWorldMatrix(false, true); return { mesh, edges }; } function checkObjectArray(obj: any, key: string) { return obj[key] && obj[key].length > 0; } export function createTemplateBoard(brDataList: any[], material: MeshBasicMaterial) { let meshs = []; let edgesa = []; let relations = { blockMeshMap: new Map(), meshBlockMap: new Map() }; for (let d of brDataList) { let { mesh, edges } = createBoard(d, material); meshs.push(mesh); edgesa.push(...edges); if (d['DataID']) { relations.blockMeshMap.set(d['DataID'], mesh.id); relations.meshBlockMap.set(mesh.id, d['DataID']); } } return { meshs, edgesa, relations }; } export function createEdge(geo: Geometry): LineSegments { let edge = new EdgesGeometry(geo, 1); return new LineSegments(edge, edgeMaterial); }