Files
cut-abstractions/tests/dev1/dataHandle/common/LayoutEngine/BlockDataPlus.ts
2025-07-22 18:22:31 +08:00

1714 lines
54 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Production } from 'cadapi'
import { PolylineHelper } from '../../common/LayoutEngine/PolylineHelper.js'
import { ArrayExt } from '../../common/base/ArrayExt.js'
import { CADExt } from '../../common/base/CAD.js'
import { equal } from '../../common/base/MathComm.js'
import { getDis_PointLine, getDis2 } from '@/imes/common/base/MathComm.js'
// import { SideModel } from '../model/SideModel.js'
import { BlockHelper } from './BlockHelper.js'
import { SideModel, PlaceBlock, PlaceBlockDetail, FaceType, HoleType, BlockHole, BlockModelPoint, BlockSideModelPoint, SideFaceType, HoleArrange } from '../../confClass.js'
import { getDoFace } from './BlockDoFace.js'
import { ToolsHelper } from '../../tools/tool.js'
/**
* 小板原始数据的修改|计算
* 造型点阵,屏蔽一些不合理数据等
* 造型换刀铣
* 计算侧孔方向
* 计算异形板的封边
*/
/** 强制造型内往外铣 */
export function reverseModelPoints(bd: PlaceBlockDetail) {
// 默认:正面造型,外->内铣;反面造型,内->外铣;因此修改正面造型的点阵顺序
for (let model of bd.models) {
if (model.offsetList.length > 0)
continue // 2维刀路 不处理
if (model.depth > bd.thickness - 0.001)
continue // 挖穿的造型不算
if (model.pointList.length < 3)
continue
if (model.face != FaceType.FRONT)
continue // 正面
// 找出最外圈
let p0 = model.pointList[0]
let index = -1
for (let i = 1; i < model.pointList.length; i++) {
if (model.pointList[i].pointX == p0.pointX && model.pointList[i].pointY == p0.pointY) {
index = i
break
}
}
if (index == model.pointList.length - 1)
continue
if (index == -1)
continue // 找不到
// 最外圈
let ps_0 = model.pointList.splice(0, index + 1)
// 剩下倒序
model.pointList.reverse()
// 换 bul
for (let i = 0; i < model.pointList.length; i++) {
let j = i + 1
if (j < model.pointList.length) {
model.pointList[i].curve = -model.pointList[j].curve
model.pointList[i].radius = model.pointList[j].radius
}
else {
model.pointList[i].curve = 0
model.pointList[i].radius = 0
}
}
model.pointList = model.pointList.concat(ps_0)
// 最开始添加一点,避免cnc 当做槽处理
let pf = model.pointList[0].copy()
model.pointList.splice(0, 0, pf)
}
}
// /** 排钻转造型 */
// export function Hole2Model(bds: PlaceBlockDetail[], sysConfig: SysConfig)
// {
// let knifes = sysConfig.HoleToModelKnifes;
// knifes = knifes.filter(t => t.isUse && t.knifeId > 0);
// for (let knife of knifes)
// {
// let k = sysConfig.getKnifeById(knife.knifeId);
// if (k == null) continue;
// knife.knifeR = -1;
// if (k.AllowCut || k.AllowModel)
// {
// knife.knifeR = k.diameter / 2;
// }
// }
// knifes = knifes.filter(t => t.knifeR > 0);
// for (let bd of bds)
// {
// for (let i = bd.holes.length - 1; i >= 0; i--)
// {
// let hole = bd.holes[i];
// let k = knifes.find(t => t.minR <= hole.radius + 0.00001 && t.maxR > hole.radius + 0.0000001);
// if (k == null) continue;
// let model = toModel(bd.thickness, hole, k.knifeR);
// if (model == null) continue;
// bd.models.push(model);
// bd.holes.splice(i, 1);
// }
// }
// function toModel(t: number, hole: BlockHole, r: number)
// {
// let depth = hole.depth;
// let hR = hole.radius;
// if (hR < r + 0.001) return null;
// let model = new BlockModel();
// model.face = hole.face;
// model.knifeRadius = r;
// model.knifeName = '';
// model.realKnifeRadius = r;
// model.depth = hole.depth;
// model.canSpace = false;
// model.pointList = [];
// model.realPointList = model.pointList;
// let cx = hole.pointX;
// let cy = hole.pointY;
// let r0 = hR - r;
// if (r0 < 0) r0 = 0;
// //最外层先走一圈,顺时针
// //左,上,右,下
// model.pointList.push( new BlockModelPoint({ pointX: cx - r0, pointY: cy, radius: r0, curve: -0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx, pointY: cy + r0, radius: r0, curve: -0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx + r0, pointY: cy, radius: r0, curve: -0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx, pointY: cy - r0, radius: r0, curve: -0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx - r0, pointY: cy, radius: 0, curve: 0, depth: depth }) );
// //挖穿
// if (depth >= t - 0.001) return model;
// //非挖穿的
// r0 = r0 - r;
// while (r0 > 0)
// {
// //左 ,下,右,上 逆时针
// model.pointList.push( new BlockModelPoint({ pointX: cx - r0, pointY: cy, radius: r0, curve: 0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx, pointY: cy - r0, radius: r0, curve: 0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx + r0, pointY: cy, radius: r0, curve: 0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx, pointY: cy + r0, radius: r0, curve: 0.41421356237309503, depth: depth }) );
// model.pointList.push( new BlockModelPoint({ pointX: cx - r0, pointY: cy, radius: 0, curve: 0, depth: depth }) );
// r0 = r0 - r;
// }
// //圆心
// model.pointList.push( new BlockModelPoint({ pointX: cx, pointY: cy, radius: 0, curve: 0, depth: depth }) );
// return model;
// }
// }
/** 移除无效的面孔:孔不在板内/孔径太小/孔深不够/圆心在外面的孔 */
export function removeInvalidHoles(block: PlaceBlockDetail, minHoleRadius: number, minHoleDepth: number) {
let count = block.holes.length
for (let i = count - 1; i >= 0; i--) {
let hole = block.holes[i]
// 是否无效, 板外,孔径太小,孔深度太浅
let invalid = isInvalidHole(block, hole, 1)
if (invalid) {
block.holes.splice(i, 1)
continue
}
if (hole.face != FaceType.SIDE && hole.depth > block.thickness) {
hole.depth = block.thickness
}
}
function isInvalidHole(blockDetail: PlaceBlockDetail, hole: BlockHole, offset: number): boolean {
if (hole.radius < minHoleRadius)
return true // 孔径太小
if (hole.depth < minHoleDepth)
return true // 孔深度太浅
// 圆心不在板内
if (hole.pointX < -offset)
return true
// if (hole.PointX > block.KaiLiaoWidth) return true;
if (hole.pointY < -offset)
return true
// if (hole.PointY > block.KaiLiaoLength + offset) return true;
return false
}
}
/** 移除二合一的面孔 */
export function remove2in1Hole(block: PlaceBlockDetail, gap: number) {
/** 二合一侧孔离边距离 */
let removeSideHoles = new Array<BlockHole>()
let count = block.holes.length
for (let i = count - 1; i >= 0; i--) {
let hole = block.holes[i]
if (hole.face != FaceType.SIDE) {
let sideHolesL = block.holes.filter(t => t.face == FaceType.SIDE && t.pointY == hole.pointY && t.pointX < hole.pointX && t.pointX >= hole.pointX - hole.radius - gap)
let sideHolesR = block.holes.filter(t => t.face == FaceType.SIDE && t.pointY == hole.pointY && t.pointX > hole.pointX && t.pointX <= hole.pointX + hole.radius + gap)
let sideHolesS = block.holes.filter(t => t.face == FaceType.SIDE && t.pointX == hole.pointX && t.pointY > hole.pointY && t.pointY < hole.pointY + hole.radius + gap)
let sideHolesX = block.holes.filter(t => t.face == FaceType.SIDE && t.pointX == hole.pointX && t.pointY < hole.pointY && t.pointY > hole.pointY - hole.radius - gap)
removeSideHoles = removeSideHoles.concat(sideHolesL, sideHolesR, sideHolesS, sideHolesX)
}
}
for (let removeHole of removeSideHoles) {
let index = block.holes.indexOf(removeHole)
if (index >= 0) {
block.holes.splice(index, 1)
}
}
}
/** 穿孔或打穿造型通孔一刀加工 */
/**
*
* @param bd
* @param config
config
* throughHoleOneTime 通孔穿孔一刀加工
* * throughHoleProcessMode 穿孔对面加工方式:
** 0随意面根据排版尽量正面加工(少翻板)
** 1孔面按碰撞面排孔所在面加工
** 2孔对面按碰撞面排孔所在面的对面打孔
*/
export function resetThroughHoleModes(bd: PlaceBlockDetail, config: any) {
if (!bd.points)
bd.points = []
if (!bd.holes)
bd.holes = []
if (!bd.models)
bd.models = []
const {
throughHoleOneTime = false,
throughHoleProcessMode = 0,
} = config
if (throughHoleOneTime) // 通孔穿孔一刀加工
{
// 判断正反面匹配的
bd.holeListThrough = bd.holes.filter(t => t.depth >= bd.thickness - 0.001) // 穿孔
bd.holeListFaceA = bd.holes.filter(t => t.face == FaceType.FRONT && t.depth < bd.thickness - 0.001)
bd.holeListFaceB = bd.holes.filter(t => t.face == FaceType.BACK && t.depth < bd.thickness - 0.001)
// 通孔判断
for (let i = bd.holeListFaceA.length - 1; i >= 0; i--) {
let hole1 = bd.holeListFaceA[i]
let isThrough = false
for (let j = bd.holeListFaceB.length - 1; j >= 0; j--) {
let hole2 = bd.holeListFaceB[j]
if (isThroughHole(hole1, hole2)) {
bd.holeListFaceB.splice(j, 1)
isThrough = true
}
}
if (isThrough) {
bd.holeListFaceA.splice(i, 1)
hole1.depth = bd.thickness
bd.holeListThrough.push(hole1)
}
}
}
else {
if (throughHoleProcessMode == 2) // 通孔对面加工
{
for (let hole of bd.holes) {
if (hole.holeType == HoleType.THROUGH_HOLE || hole.depth >= bd.thickness - 0.01) {
let oldFace = hole.face
if (oldFace == FaceType.FRONT) {
hole.face = FaceType.BACK
}
else if (oldFace == FaceType.BACK) {
hole.face = FaceType.FRONT
}
}
}
}
bd.holeListFaceA = bd.holes.filter(t => t.face == FaceType.FRONT)
bd.holeListFaceB = bd.holes.filter(t => t.face == FaceType.BACK)
bd.holeListThrough = []
}
bd.modelListFaceA = bd.models.filter(t => t.face == FaceType.FRONT && (t.depth < bd.thickness - 0.01 || t.isVKnifeModel()))
bd.modelListFaceB = bd.models.filter(t => t.face == FaceType.BACK && (t.depth < bd.thickness - 0.01 || t.isVKnifeModel()))
bd.modelListThrough = bd.models.filter(t => t.depth >= bd.thickness - 0.01 && t.isVKnifeModel() == false)
bd.holeCountFront = bd.holeListFaceA.length
bd.holeCountBack = bd.holeListFaceB.length
bd.holeCountThrough = bd.holeListThrough.length
bd.holeCountSide = bd.holeListSide.length
bd.modelCountFront = bd.modelListFaceA.length
bd.modelCountBack = bd.modelListFaceB.length
bd.modelCountThrough = bd.modelListThrough.length
bd.hasModelThrogh = bd.modelListThrough.length > 0
bd.bigHoleInFaceA = bd.holeListFaceA.some(t => t.holeType == HoleType.BIG_HOLE)
bd.isTwoFaceProcess = bd.holeCountFront + bd.modelCountFront > 0 && bd.holeCountBack + bd.modelCountBack > 0
/** 判断两孔是否是通孔 */
function isThroughHole(hole1, hole2) {
// 孔半径一样,位置一样,深度和大于板厚
return equal(hole1.radius, hole2.radius)
&& equal(hole1.pointX, hole2.pointX)
&& equal(hole1.pointY, hole2.pointY)
&& hole1.depth + hole2.depth >= bd.thickness - 0.01
}
}
/** 设置侧孔的方向 */
export function setSideHoleFace(block: PlaceBlockDetail) {
// 矩形板的侧孔face原始数据无法保证正确所有都当做起点终点来计算侧孔的面与方向
for (const hole of block.holeListSide) {
if (Math.abs(hole.pointX - hole.pointX2) < 1 && hole.pointY2 > hole.pointY) {
hole.direct = 0 // 下侧边,向上
hole.sideFace = SideFaceType.BOTTOM_SIDE
}
else if (Math.abs(hole.pointX - hole.pointX2) < 1 && hole.pointY2 < hole.pointY) {
hole.direct = 2 // 上侧边 向下
hole.sideFace = SideFaceType.TOP_SIDE
}
else if (Math.abs(hole.pointY - hole.pointY2) < 1 && hole.pointX2 > hole.pointX) {
hole.direct = 3 // 在左侧板 向右
hole.sideFace = SideFaceType.LEFT_SIDE
}
else if (Math.abs(hole.pointY - hole.pointY2) < 1 && hole.pointX2 < hole.pointX) {
hole.direct = 1 // 右侧边, 向左
hole.sideFace = SideFaceType.RIGHT_SIDE
}
else // 斜边
{
hole.direct = -1
hole.sideFace = SideFaceType.SPECIAL_SHAPED_SIDE
}
}
block.holeCountLeft = ArrayExt.count(block.holeListSide, t => t.faceId == 3)
block.holeCountRight = ArrayExt.count(block.holeListSide, t => t.faceId == 1)
block.holeCountTop = ArrayExt.count(block.holeListSide, t => t.faceId == 2)
block.holeCountBottom = ArrayExt.count(block.holeListSide, t => t.faceId == 0)
block.holeCountBevelled = ArrayExt.count(block.holeListSide, t => ![0, 1, 2, 3].includes(t.faceId))
}
/** 初始化 侧面造型
*
* * 侧面造型的点阵判断逻辑
*
* 提要:
* 1、 face 为 该造型在该板件的第几条边上
* 2、 originModeling 内的造型轮廓点阵的 X Y轴 为
* 以该造型为正面 且小板板面朝上 造型为正面的左下角为原点 板厚 为 Y 横象为X
* 注:最终使用的时候 要得到该造型 对应机台的 轮廓数据和刀路数据
*
* 平行判断 参考 checkIsTilt 修改一个新的方法
* 是否在板内 可使用 isPointInBlock
*
* 要求:要得到
*
* 转换逻辑
* 1、通过face 获取 该造型所在的边
* 2、将这条边 与 板件的坐标轴做比较 判断平行
* 情况1与板件的X轴 平行 则造型 可能为 上 || 下 ,使用 isPointInBlock 判断 具体是上 还是下
* 情况2与板件的Y轴 平行 则造型 可能为 左 || 右 使用 isPointInBlock 判断 具体是左 还是右
* 情况3都不平行 则 朝向的值为斜边
* 最终得到造型的朝向
* 3、依据边的坐标和造型的朝向 可以 根据造型的轮廓数据转为 对应机台的轮廓数据 和刀路数据
*
*
* 注:这里解析出的是设计端的数据
*/
export async function initSideModel(block: PlaceBlock) {
if (!block.blockDetail) {
console.error('initSideModel: blockDetail is undefind')
return
}
let detail = block.blockDetail
if (detail.modelListSide.length > 0) {
// 判断时侧面造型 还是 侧面槽 以及计算槽的相关信息
for (const sideModel of detail.modelListSide) {
let min = 0; // 宽
let max = 0; // 长
// let temp: any = []
let isRect = true // 是否矩形
let lines: Array<any> = []
for (let index = 0; index < sideModel.originModeling.outline.length; index++) {
const baseStartPoint = sideModel.originModeling.outline[index];
const baseEndPoint = sideModel.originModeling.outline[index + 1];
if (!baseEndPoint) {
break
}
const startPoint = sideModel.originModeling.outline[index].pts;
const endPoint = sideModel.originModeling.outline[index + 1].pts;
if (baseStartPoint.buls != 0 || baseEndPoint.buls != 0) {
isRect = false
break
}
let centerPoint = {
x: (startPoint.x + endPoint.x) / 2,
y: (startPoint.y + endPoint.y) / 2,
curve: baseStartPoint.buls,
depth: sideModel.depth,
radius: 0
}
let lineLength = getDis2(startPoint, endPoint) // parseFloat(parseFloat(getDis2(startPoint, endPoint)).toFixed(3))
if (min == 0) {
min = lineLength
}
if (max == 0) {
max = lineLength
}
min = Math.min(min, lineLength)
max = Math.max(max, lineLength)
let temp = { startPoint, endPoint, centerPoint, lineLength }
lines.push(temp);
if (index + 1 == sideModel.originModeling.outline.length) {
break
}
}
let startAndEndLines = lines.filter(e => isInRange(min, e.lineLength - 0.001, e.lineLength + 0.001));
// 槽的起点 和终点
if (startAndEndLines.length == 2) {
sideModel.modelStartPoint = startAndEndLines[0].centerPoint
sideModel.modelEndPoint = startAndEndLines[1].centerPoint
}
isRect = (lines.length == 4 || lines.length == 1) && sideModel.offsetList.length == 0
// console.log('情况123', lines, model,isRect)
sideModel.modelLength = max
sideModel.modelWidth = min
sideModel.isRect = isRect
if (isRect) {
sideModel.isTilt = checkIsTilt(lines)
}
let directionRes = getModelDirection(block, sideModel)
sideModel.direction = directionRes.direction;
// console.log('direction', directionRes.direction, sideModel.isRect, sideModel.isTilt);
if (!detail.borderContour) {
console.error('initSideModel: borderContour is undefind')
return
}
const borders = detail?.borderContour?.borderFinal
const border = borders[sideModel.face]
// 依据 造型的朝向 和 造型的轮廓数据 和 所在边的坐标 生成 轮廓数据 还有刀路数据
if (isRect && sideModel.isTilt == false) {
detail.borderContour.borderFinal
sideModel.modelStartPoint = transformSideModelPoint(sideModel.modelStartPoint, directionRes, border, sideModel, 'modelStartPoint')
sideModel.modelEndPoint = transformSideModelPoint(sideModel.modelEndPoint, directionRes, border, sideModel, 'modelStartPoint')
}
let newPointList: any = []
if (Array.isArray(sideModel.originModeling.outline)) {
for (const linePoint of sideModel.originModeling.outline) {
let tempPoint = {
curve: linePoint.buls,
depth: sideModel.depth,
radius: 1 / linePoint.buls,
x: linePoint.pts.x,
y: linePoint.pts.y,
z: linePoint.pts.z,
}
let temp = transformSideModelPoint(tempPoint, directionRes, border, sideModel, 'linePoint')
let sideModelPoint = new BlockSideModelPoint(temp)
newPointList.push(sideModelPoint)
}
} else {
for (const i in sideModel.originModeling.outline.pts) {
let pts = sideModel.originModeling.outline.pts[i]
let bul = sideModel.originModeling.outline.buls[i]
let tempPoint = {
curve: bul,
depth: sideModel.depth,
radius: 1 / bul,
x: pts.x,
y: pts.y,
z: pts.z,
}
let temp = transformSideModelPoint(tempPoint, directionRes, border, sideModel, 'linePoint')
let sideModelPoint = new BlockSideModelPoint(temp)
newPointList.push(sideModelPoint)
}
}
sideModel.pointList = newPointList
}
}
}
/**侧面造型数据转换 从设计端 转为生产数据
* config:
* placeStyle 小板放置方式
*/
export function transFormSideModelDataToProductData(block: PlaceBlock, config) {
if(!block.blockDetail){
console.error('transFormSideModelDataToProductData: blockDetail is undefind')
return
}
const {
placeStyle= 1
} = config
if (block.blockDetail.modelListSide.length > 0) {
for (const sideModel of block.blockDetail.modelListSide) {
if (sideModel.isRect == true && sideModel.isTilt == false) {
// 矩形槽 要转换下起始点
let p_start = BlockHelper.getPlacedPostionInBlock(placeStyle, block.placeWidth, block.placeLength, sideModel.modelStartPoint.x, sideModel.modelStartPoint.y, false)
let p_end = BlockHelper.getPlacedPostionInBlock(placeStyle, block.placeWidth, block.placeLength, sideModel.modelEndPoint.x, sideModel.modelEndPoint.y, false)
sideModel.modelStartPoint.x = p_start.x
sideModel.modelStartPoint.y = p_start.y
sideModel.modelEndPoint.x = p_end.x
sideModel.modelEndPoint.y = p_end.y
}
// 转换造型 轮廓点阵
for (const point of sideModel.pointList) {
let p = BlockHelper.getPlacedPostionInBlock(placeStyle, block.placeWidth, block.placeLength, point.pointX, point.pointY, false)
point.pointX = p.x
point.pointY = p.y
}
}
}
}
/**
* 值 是否在范围内
* @param value 目标值
* @param min 最小值 比较值
* @param max 最大值 比较值
* @returns
*/
function isInRange(value, min, max) {
return value >= min && value <= max;
}
/**
*
* @param lines
* 注假定2条在坐标轴上的线 与矩形造型的4条线判断是否是平行
*
* 线的起始点 与 坐标轴 X Y 比较 判断是否倾斜 (倾斜的矩形 或者 平行四边形)
*/
// 判断是否是倾斜的
function checkIsTilt(lines) {
// 假定的坐标轴 定义坐标点
let p1 = { x: 0, y: 0 }
let p2 = { x: 0, y: 100 }
let p3 = { x: 100, y: 0 }
// 假定2条在坐标轴上的线
// let tempAxiosXLine = [p1,p3]
// let tempAxiosYLine = [p1,p2]
lines.forEach(line => {
// flag 是否平行的标识 true 平行 false 不平行
let flagX = false
let flagY = false
let startX = line.startPoint.pointX || line.startPoint.x
let startY = line.startPoint.pointY || line.startPoint.y
let endX = line.endPoint.pointX || line.endPoint.x
let endY = line.endPoint.pointY || line.endPoint.y
// 距离X轴的距离是否相等
// 线段的起点 距离X轴的距离
let len1 = getDis_PointLine(p1.x, p1.y, p3.x, p3.y, startX, startY)
// 线段的终点 距离X轴的距离
let len2 = getDis_PointLine(p1.x, p1.y, p3.x, p3.y, endX, endY)
// 实际数据是有误差的 误差 的容差为 0.001
if (isInRange(len1, len2 - 0.001, len2 + 0.001) || isInRange(len2, len1 - 0.001, len1 + 0.001)) {
flagX = true
}
// 距离Y轴的距离是否相等
// 线段起点距离Y轴的距离
let len3 = getDis_PointLine(p1.x, p1.y, p2.x, p2.y, startX, startY)
// 线段终点距离Y轴的距离
let len4 = getDis_PointLine(p1.x, p1.y, p2.x, p2.y, endX, endY)
if (isInRange(len3, len4 - 0.001, len4 + 0.001) || isInRange(len4, len3 - 0.001, len3 + 0.001)) {
flagX = true
}
// 只要和 X || Y 轴 平行 就不是倾斜的
if (flagX || flagY) {
line.isTilt = false
} else {
line.isTilt = true
}
});
// 查找有没有 倾斜的边
const res = lines.filter(e => e.isTilt == true).length > 0 //.findIndex(e => e.isTilt == true) == -1
return res
}
/** 转换 侧面造型的坐标点 */
export function transformSideModelPoint(point, directionRes, border, sideModel: SideModel, flag?: string) {
const { direction, preFlag, nextFlag } = directionRes
let newPoint: any = { x: 0, y: 0, z: 0, buls: 0, depth: 0 }
if (point == null) {
newPoint = null // { x: -1, y: -1, z: -1, buls: 0, depth: 0 }
} else {
/**
*
* 侧面造型的点坐标使用 等比三角形 解决坐标问题
*
*/
// 斜边比例
let rate = point.x / border.m_Length
switch (direction) {
case 0:
/**坐标转换逻辑 下造型
*
* point 里面的
* x 对应 实际的 X
* y 对应 实际的 Z
* 实际的y 为 border 对应的 y
*/
// console.log('下造型',sideModel.modelId)
newPoint.x = point.x
newPoint.y = border.StartPoint.m_Y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 1:
// console.log('右造型',sideModel.modelId)
newPoint.x = border.StartPoint.m_X
newPoint.y = point.x
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 2:
// console.log('上造型',sideModel.modelId)
newPoint.x = border.StartPoint.m_X - point.x
newPoint.y = border.StartPoint.m_Y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 3:
// console.log('左造型',sideModel.modelId)
newPoint.x = border.StartPoint.m_X
newPoint.y = border.StartPoint.m_Y - point.x
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 10:
// console.log('左下造型',sideModel.modelId)
// 底边
var x = Math.abs(border.StartPoint.m_X) - Math.abs(border.EndPoint.m_X)
// 竖边
var y = Math.abs(border.StartPoint.m_Y) - Math.abs(border.EndPoint.m_Y)
// 实际点坐标的 偏移值
var p_x = Math.abs(x * rate)
var p_y = Math.abs(y * rate)
var fakeStartPoint: any = null
// 二次计算的原点坐标
/**
* 根据 造型的坐标系的定位点 进行偏移 (边框的起点 或者终点)
* 根据preFlag (小板的轮廓的上一条边的朝向 判断 定位点事 起点还是终点)
*/
if (preFlag == 'toDown') {
fakeStartPoint =
{
x: border.StartPoint.m_X,
y: border.StartPoint.m_Y
}
} else if (preFlag == 'toLeft') {
fakeStartPoint =
{
x: border.EndPoint.m_X,
y: border.EndPoint.m_Y
}
} else {
console.log('理论上有异常 排查')
}
newPoint.x = fakeStartPoint.x + p_x
newPoint.y = fakeStartPoint.y - p_y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 11:
// console.log('右下造型',sideModel.modelId)
// 底边
var x = Math.abs(border.StartPoint.m_X) - Math.abs(border.EndPoint.m_X)
// 竖边
var y = Math.abs(border.StartPoint.m_Y) - Math.abs(border.EndPoint.m_Y)
// 实际点坐标的 偏移值
var p_x = Math.abs(x * rate)
var p_y = Math.abs(y * rate)
var fakeStartPoint: any = null
// 二次计算的原点坐标
/**
* 根据 造型的坐标系的定位点 进行偏移 (边框的起点 或者终点)
* 根据preFlag (小板的轮廓的上一条边的朝向 判断 定位点事 起点还是终点)
*/
if (preFlag == 'toRight') {
fakeStartPoint =
{
x: border.StartPoint.m_X,
y: border.StartPoint.m_Y
}
} else if (preFlag == 'toDown') {
fakeStartPoint =
{
x: border.EndPoint.m_X,
y: border.EndPoint.m_Y
}
} else {
console.log('理论上有异常 排查')
}
newPoint.x = fakeStartPoint.x + p_x
newPoint.y = fakeStartPoint.y + p_y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 12:
// console.log('右上造型',sideModel.modelId)
// 底边
var x = Math.abs(border.StartPoint.m_X) - Math.abs(border.EndPoint.m_X)
// 竖边
var y = Math.abs(border.StartPoint.m_Y) - Math.abs(border.EndPoint.m_Y)
// 实际点坐标的 偏移值
var p_x = Math.abs(x * rate)
var p_y = Math.abs(y * rate)
var fakeStartPoint: any = null
// 二次计算的原点坐标
/**
* 根据 造型的坐标系的定位点 进行偏移 (边框的起点 或者终点)
* 根据preFlag (小板的轮廓的上一条边的朝向 判断 定位点事 起点还是终点)
*/
if (preFlag == 'toUp') {
fakeStartPoint =
{
x: border.StartPoint.m_X,
y: border.StartPoint.m_Y
}
} else if (preFlag == 'toRight') {
fakeStartPoint =
{
x: border.EndPoint.m_X,
y: border.EndPoint.m_Y
}
} else {
console.log('理论上有异常 排查')
}
newPoint.x = fakeStartPoint.x - p_x
newPoint.y = fakeStartPoint.y - p_y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
case 13:
// console.log('左上造型',sideModel.modelId)
// 底边
var x = Math.abs(border.StartPoint.m_X) - Math.abs(border.EndPoint.m_X)
// 竖边
var y = Math.abs(border.StartPoint.m_Y) - Math.abs(border.EndPoint.m_Y)
// 实际点坐标的 偏移值
var p_x = Math.abs(x * rate)
var p_y = Math.abs(y * rate)
var fakeStartPoint: any = null
// 二次计算的原点坐标
/**
* 根据 造型的坐标系的定位点 进行偏移 (边框的起点 或者终点)
* 根据preFlag (小板的轮廓的上一条边的朝向 判断 定位点事 起点还是终点)
*/
if (preFlag == 'toLeft') {
fakeStartPoint =
{
x: border.StartPoint.m_X,
y: border.StartPoint.m_Y
}
} else if (preFlag == 'toUp') {
fakeStartPoint =
{
x: border.EndPoint.m_X,
y: border.EndPoint.m_Y
}
} else {
console.log('理论上有异常 排查')
}
newPoint.x = fakeStartPoint.x - p_x
newPoint.y = fakeStartPoint.y - p_y
newPoint.z = point.y
newPoint.buls = point.curve
newPoint.depth = sideModel.depth
break
default:
break;
}
}
return newPoint;
}
// 获取侧面造型的朝向
export function getModelDirection(block: PlaceBlock, sideModel) {
console.log('getModelDirection', block);
let detail = block.blockDetail
const borders = detail?.borderContour?.borderFinal
// if(borders==undefined){
// return
// }
const border = borders[sideModel.face]
let polygon: any = []
borders.forEach(br => {
let temp = {
x: br.StartPoint.m_X,
y: br.StartPoint.m_Y
}
polygon.push(temp)
});
// 假定的坐标轴 定义坐标点
let p1 = { x: 0, y: 0 }
let p2 = { x: 0, y: 100 }
let p3 = { x: 100, y: 0 }
// 朝向
let direction = -2;
// 注: 根据上一条边和下一条的朝向判断 造型的 朝向
// 板件轮廓 上一条边的朝向
let preFlag = '';
// 板件轮廓 下一条边的朝向
let nextFlag = '';
let flagX = false
let flagY = false
// 线段的起点 距离X轴的距离
let len1 = getDis_PointLine(p1.x, p1.y, p3.x, p3.y, border.StartPoint.m_X, border.StartPoint.m_Y)
// 线段的终点 距离X轴的距离
let len2 = getDis_PointLine(p1.x, p1.y, p3.x, p3.y, border.EndPoint.m_X, border.EndPoint.m_Y)
if (len1 == len2) {
flagX = true
}
// 距离Y轴的距离是否相等
// 线段起点距离Y轴的距离
let len3 = getDis_PointLine(p1.x, p1.y, p2.x, p2.y, border.StartPoint.m_X, border.StartPoint.m_Y)
// 线段终点距离Y轴的距离
let len4 = getDis_PointLine(p1.x, p1.y, p2.x, p2.y, border.EndPoint.m_X, border.EndPoint.m_Y)
if (len3 == len4) {
flagY = true
}
let xx = (border.StartPoint.m_X + border.EndPoint.m_X) / 2
let yy = (border.StartPoint.m_Y + border.EndPoint.m_Y) / 2
if (flagY == false && flagX == false) {
// 斜的
direction = -1
// 获取 上一条边 和下一条边 (忽略弧形 弧线也按照线段处理 不会影响方向的判断)
let preborderId = sideModel.face - 1
let nextBorderId = sideModel.face + 1
if (preborderId < 0) {
preborderId = borders.length - 1
}
if (nextBorderId > borders.length - 1) {
nextBorderId = 0
}
let preborder = borders[preborderId]
let nextborder = borders[nextBorderId]
let preX = preborder.StartPoint.m_X - preborder.EndPoint.m_X
let preY = preborder.StartPoint.m_Y - preborder.EndPoint.m_Y
let nextX = nextborder.StartPoint.m_X - nextborder.EndPoint.m_X
let nextY = nextborder.StartPoint.m_Y - nextborder.EndPoint.m_Y
if (preX == 0) {
// 上下
if (preY > 0) {
// 向下
preFlag = 'toDown'
} else if (preY < 0) {
// 向上
preFlag = 'toUp'
}
}
if (preY == 0) {
// 左右
if (preX > 0) {
// 向左
preFlag = 'toLeft'
} else if (preX < 0) {
// 向右
preFlag = 'toRight'
}
}
if (nextX == 0) {
// 上下
if (nextY > 0) {
// 向下
nextFlag = 'toDown'
} else if (nextY < 0) {
// 向上
nextFlag = 'toUp'
}
}
if (nextY == 0) {
// 左右
if (nextX > 0) {
// 向左
nextFlag = 'toLeft'
} else if (nextX < 0) {
// 向右
nextFlag = 'toRight'
}
}
// 理论只有下面的情况 不符合的都是异常情况 或者不存在的情况
switch (preFlag) {
case 'toDown':
if (nextFlag == 'toLeft') {
// 造型在 右下斜面
direction = 11
} else if (nextFlag == 'toRight') {
// 造型在 左下斜面
direction = 10
}
break;
case 'toRight':
if (nextFlag == 'toUp') {
// 造型在 右下斜面
direction = 11
} else if (nextFlag == 'toDown') {
// 造型在 右上斜面
direction = 12
}
break;
case 'toUp':
if (nextFlag == 'toLeft') {
// 造型在 右上斜面
direction = 12
} else if (nextFlag == 'toRight') {
// 造型在 左上斜面
direction = 13
}
break;
case 'toLeft':
if (nextFlag == 'toUp') {
// 造型在 左下斜面
direction = 10
} else if (nextFlag == 'toDown') {
// 造型在 左上斜面
direction = 13
}
break;
default:
break;
}
} else if (flagX == true) {
// 上下
const p1 = { x: xx, y: yy - 1 }
const p2 = { x: xx, y: yy + 1 }
const isTop = isPointInPolygon(p1, polygon)
if (isTop) {
direction = 2
} else {
const isBottom = isPointInPolygon(p2, polygon)
if (isBottom) {
direction = 0
}
if (direction == -2) {
}
}
} else if (flagY == true) {
// 左右
const p3 = { x: xx - 1, y: yy }
const p4 = { x: xx + 1, y: yy }
const isRight = isPointInPolygon(p3, polygon)
if (isRight) {
direction = 1
} else {
const isLeft = isPointInPolygon(p4, polygon)
if (isLeft) {
direction = 3
}
if (direction == -2) {
}
}
}
const directionRes = {
direction, preFlag, nextFlag
}
return directionRes
}
/** 判断 点 是否在轮廓内 射线法 */
export function isPointInPolygon(point, polygon) {
const x = point.x;
const y = point.y;
let inside = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i].x;
const yi = polygon[i].y;
const xj = polygon[j].x;
const yj = polygon[j].y;
// 检查点是否位于当前边的水平线上
const intersect = ((yi > y) != (yj > y)) &&
(x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
export function createSideModelRealKnifePoints(block: PlaceBlock, sideModel: SideModel) {
let directionRes = getModelDirection(block, sideModel)
// 确定 轮廓的中点
let x = { min: 0, max: 0 }
let y = { min: 0, max: 0 }
let z = { min: 0, max: 0 }
sideModel.pointList.forEach((p, i) => {
if (i == 0) {
x.min = p.pointX
x.max = p.pointX
y.min = p.pointY
y.max = p.pointY
z.min = p.pointZ
z.max = p.pointZ
} else {
x.min = Math.min(x.min, p.pointX)
x.max = Math.max(x.max, p.pointX)
y.min = Math.min(y.min, p.pointY)
y.max = Math.max(y.max, p.pointY)
z.min = Math.min(z.min, p.pointZ)
z.max = Math.max(z.max, p.pointZ)
}
});
let centerPoint = {
x: (x.min + x.max) / 2,
y: (y.min + y.max) / 2,
z: (z.min + z.max) / 2
}
if (equal(sideModel.realKnifeRadius, sideModel.knifeRadius)) {
let realPointList: any = [];
if (directionRes.direction == 0 || directionRes.direction == 2) {
let tempPoints: any = []
sideModel.pointList.forEach((p) => {
tempPoints.push({ x: p.pointY, y: p.pointZ })
})
var newPointList = shrinkRectangle(tempPoints, centerPoint.y, centerPoint.z, sideModel.realKnifeRadius)
realPointList = sideModel.pointList.map((point, i) => {
let temp = JSON.parse(JSON.stringify(point))
temp.pointY = newPointList[i].x
temp.pointZ = newPointList[i].y
return temp
})
} else if (directionRes.direction == 1 || directionRes.direction == 3) {
let tempPoints: any = []
sideModel.pointList.forEach(p => {
tempPoints.push({ x: p.pointX, y: p.pointZ })
})
var newPointList = shrinkRectangle(tempPoints, centerPoint.x, centerPoint.z, sideModel.realKnifeRadius)
realPointList = sideModel.pointList.map((point, i) => {
let temp = JSON.parse(JSON.stringify(point))
temp.pointX = newPointList[i].x
temp.pointZ = newPointList[i].y
return temp
})
}
}
}
// 刀路 向内铣
/**
* 得到 点阵 向内缩小的 新的点阵
* @param points 点阵
* @param centerX 造型的中心点x
* @param centerY 造型的中心点y
* @param shrinkAmount 向内的偏移量
* @returns
*/
function shrinkRectangle(points, centerX, centerY, shrinkAmount) {
return points.map(point => {
// 计算到中心点的偏移量
const dx = point.x - centerX;
const dy = point.y - centerY;
// 为了避免除以0的错误和保持简单性我们可以使用下面的方法
// 如果dx或dy的绝对值小于shrinkAmount的一半则将其设置为0即该点保持在中心点上或非常接近
// 否则我们按照比例减少dx和dy。
const absDx = Math.abs(dx);
const absDy = Math.abs(dy);
const halfShrink = shrinkAmount;
const newDx = (absDx > halfShrink) ? dx - (Math.sign(dx) * halfShrink) : 0;
const newDy = (absDy > halfShrink) ? dy - (Math.sign(dy) * halfShrink) : 0;
return {
x: centerX + newDx,
y: centerY + newDy
};
});
}
// 刀路 向外铣
/**
* 得到 点阵 向外放大的 新的点阵
* @param points 点坐标
* @param centerX 造型的中心点x
* @param centerY 造型的中心点y
* @param expansionAmount 向外的偏移量
* @returns
*/
function expandRectangleCorrect(points, centerX, centerY, expansionAmount) {
const halfExpansion = expansionAmount; // 在本例中这将是0.5
return points.map(point => ({
// 只加一次halfExpansion因为我们在两个方向上都会加。
x: centerX + (point.x - centerX) + halfExpansion,
y: centerY + (point.y - centerY) + halfExpansion
}));
}
/** 造型轮廓(含封边),扣除封边, 变成开料坐标 */
export function resetModelContour(bd: PlaceBlockDetail) {
let ox = bd.offsetX
let oy = bd.offsetY
for (let m of bd.models) {
if (m.hasContour()) {
let ptsArr = m.originModeling.outline.map(e => e.pts)
for (let pt of ptsArr) {
// 23.8.5 发现矩形的挖穿轮廓坐标是不含封边的
pt.x -= ox
pt.y -= oy
}
}
}
}
export function resetModelKnife(block: PlaceBlock, toolsHelper:ToolsHelper, isUseOffset?: boolean) {
let _isUseOffset = false
if (isUseOffset) {
_isUseOffset = isUseOffset
}
let processModelIdList: number[] = [];
// console.log(block)
for (let m_i = 0; m_i < block.blockDetail.models.length; m_i++) {
let model = block.blockDetail.models[m_i]
if (model.isVKnifeModel())
continue // 二维刀路 不处理
// if (model.realKnifeRadius != 0)
// continue // 已处理
let knife = toolsHelper.getKnifeByParams({knifeName : model.knifeName}) //sysConfig.getModelKnife(model)
if (knife == null) {
model.realKnifeRadius = -1
}
else {
model.realKnifeRadius = knife.diameter / 2
model.realKnifeId = knife.knifeId
// 修复问题 如果是弧线的情况下 出现 弧线生成异常
let checkIsOk = true
for (const p of model.pointList) {
if ((p.curve != 0 && p.radius == 0) || (p.radius != 0 && p.curve == 0)) {
checkIsOk = false
break
}
}
if (equal(model.realKnifeRadius, model.knifeRadius) && checkIsOk) {
model.realPointList = model.pointList
}
else {
model.originModeling.knifeRadius = knife.diameter / 2
model.originModeling.thickness = model.depth
model.originModeling.brThickness = block.thickness
model.originModeling.boardContour = getOrgContour()
let newData: any = null
if (model.originModeling && Array.isArray(model.originModeling.outline)) {
newData = JSON.parse(JSON.stringify(model.originModeling))
let newOutLine = { pts: newData.outline.map(e => e.pts), buls: newData.outline.map(e => e.buls) }
let newHoles = newData?.holes?.map(x => { return { pts: x.map(e => e.pts), buls: x.map(e => e.buls) } })
newData.outline = newOutLine
newData.holes = newHoles || []
} else {
newData = model.originModeling
}
let custborders: any = []
try {
if (model.originModeling.outline) {
custborders = Production.GetChaiDanFeedingPath(newData, 0)
}
} catch (error) {
console.error(error, block.blockNo, model.modelId, model);
}
let offx = _isUseOffset ? block.offsetX() : 0// block.OffsetX;
let offy = _isUseOffset ? block.offsetY() : 0// block.OffsetY;
let ps1: BlockModelPoint[] = []
if (custborders.length > 0) {
let ct = custborders[0]
if (processModelIdList.includes(model.modelId)) {
ct = custborders[model.lineId - 1]
} else {
processModelIdList.push(model.modelId)
}
if (ct) {
for (let i = 0; i < ct.buls.length; i++) {
var r = 0
if (ct.buls[i] != 0) {
let j = i + 1
if (j == ct.buls.length)
j = 0
r = CADExt.getR(ct.pts[i].x, ct.pts[i].y, ct.pts[j].x, ct.pts[j].y, ct.buls[i])
}
ps1.push(new BlockModelPoint({ pointX: ct.pts[i].x - offx, pointY: ct.pts[i].y - offy, curve: ct.buls[i], radius: r, depth: model.depth }))
}
}
}
if (ps1.length > 0) {
model.realPointList = ps1
}
else {
model.realKnifeId = -1
model.realKnifeRadius = -1
model.realPointList = []
}
}
}
}
/** 获取轮廓 */
function getOrgContour() {
if (!block.blockDetail) {
console.error('resetModelKnife=>getOrgContour: blockDetail is undefind')
return
}
if (!block.blockDetail.orgContourData) {
let pts: any = []
let buls: any = []
if (!block.isUnRegular) {
pts.push({ x: 0, y: 0 })
pts.push({ x: block.cutWidth, y: 0 })
pts.push({ x: block.cutWidth, y: block.cutLength })
pts.push({ x: 0, y: block.cutLength })
buls.push(0)
buls.push(0)
buls.push(0)
buls.push(0)
}
else // 矩形板
{
for (let p of block.blockDetail.points) {
pts.push({ x: p.pointX, y: p.pointY })
buls.push(p.curve)
}
}
block.blockDetail.orgContourData = { pts, buls }
}
return block.blockDetail.orgContourData
}
}
export async function resetSideModelKnife(block: PlaceBlock, tools: ToolsHelper) {
if (!block.blockDetail) {
console.error('resetModelKnife=>getOrgContour: blockDetail is undefind')
return
}
for (let model of block.blockDetail.modelListSide) {
let knife = model.knife || tools.getKnifeByParams({ knifeName: model.knifeName })
if (knife == null) {
model.realKnifeRadius = -1
}
else {
model.knife = knife
model.realKnifeRadius = knife.diameter / 2
model.realKnifeId = knife.knifeId
// if(model.pointList.length ==0){
// await initSideModel(block)
// }
if (equal(model.realKnifeRadius, model.knifeRadius)) {
model.realPointList = model.pointList
}
else {
model.originModeling.knifeRadius = knife.diameter / 2
model.originModeling.thickness = model.depth
model.originModeling.brThickness = block.thickness
model.originModeling.boardContour = getOrgContour()
console.log('侧面造型生成新刀路:', model.modelId, model)
let newData: any = null
if (model.originModeling && Array.isArray(model.originModeling.outline)) {
newData = JSON.parse(JSON.stringify(model.originModeling))
let newOutLine = { pts: newData.outline.map(e => e.pts), buls: newData.outline.map(e => e.buls) }
let newHoles = newData?.holes?.map(x => { return { pts: x.map(e => e.pts), buls: x.map(e => e.buls) } })
newData.outline = newOutLine
newData.holes = newHoles || []
} else {
newData = model.originModeling
}
let custborders = model.originModeling.outline ? Production.GetChaiDanFeedingPath(newData) : []
let offx = 0// block.OffsetX;
let offy = 0// block.OffsetY;
let ps1: BlockSideModelPoint[] = []
if (custborders.length > 0) {
if (custborders.length == 1) {
let ct = custborders[0]
model.lineId = 1
for (let i = 0; i < ct.buls.length; i++) {
let r = 0
if (ct.buls[i] != 0) {
let j = i + 1
if (j == ct.buls.length)
j = 0
r = CADExt.getR(ct.pts[i].x, ct.pts[i].y, ct.pts[j].x, ct.pts[j].y, ct.buls[i])
}
ps1.push(new BlockSideModelPoint({ pointX: ct.pts[i].x - offx, pointY: ct.pts[i].y - offy, pointZ: 0, curve: ct.buls[i], radius: r, depth: model.depth }))
}
// 要处理下坐标
if (ps1.length > 0) {
let directionRes = getModelDirection(block, model)
const borders = block.blockDetail?.borderContour?.borderFinal
if (!borders) {
console.error('resetModelKnife=>getOrgContour: blockDetail is undefind')
return
}
const border = borders[model.face]
let newRealPointList: BlockSideModelPoint[] = []
for (const linePoint of ps1) {
let tempPoint = {
curve: linePoint.buls,
depth: model.depth,
radius: 1 / linePoint.buls,
x: linePoint.pointX || 0,
y: linePoint.pointY || 0,
z: linePoint.pointZ || 0,
}
let temp = transformSideModelPoint(tempPoint, directionRes, border, model, 'linePoint')
let sideModelPoint = new BlockSideModelPoint(temp)
newRealPointList.push(sideModelPoint);
}
model.realPointList = newRealPointList
}
else {
model.realKnifeId = -1
model.realKnifeRadius = -1
model.realPointList = []
}
} else {
for (const ct_key in custborders) {
let tempModel = new SideModel(model)
ps1 = []
let ct = custborders[ct_key]
tempModel.lineId = parseFloat(ct_key) + 1
for (let i = 0; i < ct.buls.length; i++) {
let r = 0
if (ct.buls[i] != 0) {
let j = i + 1
if (j == ct.buls.length)
j = 0
r = CADExt.getR(ct.pts[i].x, ct.pts[i].y, ct.pts[j].x, ct.pts[j].y, ct.buls[i])
}
ps1.push(new BlockSideModelPoint({ pointX: ct.pts[i].x - offx, pointY: ct.pts[i].y - offy, pointZ: 0, curve: ct.buls[i], radius: r, depth: tempModel.depth }))
}
if (ps1.length > 0) {
let directionRes = getModelDirection(block, tempModel)
const borders = block.blockDetail?.borderContour?.borderFinal
const border = borders[tempModel.face]
let newRealPointList: BlockSideModelPoint[] = []
for (const linePoint of ps1) {
let tempPoint = {
curve: linePoint.buls,
depth: tempModel.depth,
radius: 1 / linePoint.buls,
x: linePoint.pointX || 0,
y: linePoint.pointY || 0,
z: linePoint.pointZ || 0,
}
let temp = transformSideModelPoint(tempPoint, directionRes, border, tempModel, 'linePoint')
let sideModelPoint = new BlockSideModelPoint(temp)
newRealPointList.push(sideModelPoint);
}
tempModel.realPointList = newRealPointList
}
else {
tempModel.realKnifeId = -1
tempModel.realKnifeRadius = -1
tempModel.realPointList = []
}
// 避免拆分的刀路造型 重复插入
if (block.blockDetail.modelListSide.findIndex(e => e.modelId == tempModel.modelId && e.lineId == tempModel.lineId) == -1) {
block.blockDetail.modelListSide.push(tempModel)
} else {
model = tempModel
}
}
}
}
}
}
}
/** 获取轮廓 */
function getOrgContour() {
if (!block.blockDetail) {
console.error('resetModelKnife=>getOrgContour: blockDetail is undefind')
return
}
if (!block.blockDetail.orgContourData) {
let pts: any = []
let buls: any = []
if (!block.isUnRegular) {
pts.push({ x: 0, y: 0 })
pts.push({ x: block.cutWidth, y: 0 })
pts.push({ x: block.cutWidth, y: block.cutLength })
pts.push({ x: 0, y: block.cutLength })
buls.push(0)
buls.push(0)
buls.push(0)
buls.push(0)
}
else // 矩形板
{
for (let p of block.blockDetail.points) {
pts.push({ x: p.pointX, y: p.pointY })
buls.push(p.curve)
}
}
block.blockDetail.orgContourData = { pts, buls }
}
return block.blockDetail.orgContourData
}
}
/** 二维刀路初始化 */
export function init2VModel(blockDetail: PlaceBlockDetail, tools: ToolsHelper, isCNC = false) {
for (let model of blockDetail.models) {
if (!model.isVKnifeModel())
continue
let vModels: any[] = []
model.VLines = vModels
let isFaceB = model.face == FaceType.BACK
if (model.pointList.length < 1)
continue
let ps = model.pointList.map((t) => { return { x: t.pointX, y: t.pointY, bul: t.curve } })
let pl = PolylineHelper.create(ps)
if (model.VLines?.length > 0)
return // 已经分析了
model.VLines = []
for (let os of model.offsetList) {
// 根据刀名称找刀
let knife1 = isCNC ? null : tools.getKnifeByParams({ knifeName: os.name })
let knifeR = os.radius
let knifeId = knife1 ? knife1.knifeId : -1
try {
let vps_1 = PolylineHelper.getVModelPoints_offset(pl, os.offset, os.depth, os.angle)
let vLine = { isFaceB, name: os.name, value: os.offset, knife: knife1, knifeId, knifeRadius: knifeR, depth: os.depth, points: vps_1, offset: os }
vModels.push(vLine) // 偏移路径
model.VLines.push(vLine)
}
catch (err) {
console.log('v型刀走刀路径算法出错。' + err)
}
}
model.VLines = vModels
}
}
/** 异形板 封边值 */
export function resetBorderValue(block: PlaceBlock) {
if (!block.blockDetail) {
console.error('resetBorderValue: blockDetail is undefind')
return
}
if (block.isUnRegular) {
block.cutWidth = block.blockDetail.cutWidth
block.cutLength = block.blockDetail.cutLength
}
block.blockDetail.cutWidth = block.cutWidth
block.blockDetail.cutLength = block.cutLength
if (block.isUnRegular == false)
return
// 计算异形板 的上下左右 封边值
block.sealLeft = getSealEdge('LEFT')
block.sealRight = getSealEdge('RIGHT')
block.sealTop = getSealEdge('TOP')
block.sealBottom = getSealEdge('BOTTOM')
function getSealEdge(sealEdge) {
let closetP
let dis = 1000000
for (let i = 0; i < block.orgPoints.length; i++) {
let p0 = block.orgPoints[i]
let p1 = i == block.orgPoints.length - 1 ? block.orgPoints[0] : block.orgPoints[i + 1]
if (sealEdge == 'LEFT') {
if (equal(p0.pointX, 0) && equal(p1.pointX, 0))
return p0.sealSize
let dis_t = (p0.pointX + p1.pointX) * 0.5
if (dis_t < dis) {
closetP = p0
dis = dis_t
}
}
if (sealEdge == 'RIGHT') {
if (equal(p0.pointX, block.width) && equal(p1.pointX, block.width))
return p0.sealSize
let dis_t = (p0.pointX + p1.pointX) * 0.5
if (block.width - dis_t < dis) {
closetP = p0
dis = block.width - dis_t
}
}
if (sealEdge == 'TOP') {
if (equal(p0.pointY, block.length) && equal(p1.pointY, block.length))
return p0.sealSize
let dis_t = (p0.pointY + p1.pointY) * 0.5
if (block.length - dis_t < dis) {
closetP = p0
dis = dis_t
}
}
if (sealEdge == 'BOTTOM') {
if (equal(p0.pointY, 0) && equal(p1.pointY, 0))
return p0.sealSize
let dis_t = (p0.pointY + p1.pointY) * 0.5
if (dis_t < dis) {
closetP = p0
dis = dis_t
}
}
}
// 找最接近边的点
return closetP ? closetP.sealSize : 0
}
}
/**
* 设置小板是否反面排版优化
* @param block 小板
* @param processMode 加工模式(0开料机(雕刻机)加工 1开料机CNC组合 2定制加工)
*/
export function setFaceToPlace(block: PlaceBlock, config) {
// let processMode = 0;
// if(sys.isCutProcess) processMode = 0;
// if(sys.isCutAndCNCProcess) processMode = 1;
// if(sys.isCustomized) processMode = 2;
const {
processMode = 0
} = config
block.isTurnFaceToPlace = !getDoFace(block, processMode)
}