2396 lines
82 KiB
TypeScript
2396 lines
82 KiB
TypeScript
|
import { Circle, Contour, ConverToPolylineAndSplitArc, Shape, ShapeManager } from 'cadapi'
|
|||
|
import type { Polyline } from 'cadapi'
|
|||
|
import { Vector3 } from 'three'
|
|||
|
import { PolylineHelper } from '../../common/LayoutEngine/PolylineHelper.js'
|
|||
|
import type { Curve2d } from '../../common/base/CAD.js'
|
|||
|
import { Arc2d, Line2d, Point2d } from '../../common/base/CAD.js'
|
|||
|
import { PlaceStyle, SizeExpand, PlaceBlock, PlaceBlockDetail, PlaceBorderContour, PlaceSpace, PlaceMaterial } from '../../confClass.js'
|
|||
|
import { equal, getDis, getDis2, getDis_PointLine, getRect } from '../../common/base/MathComm.js'
|
|||
|
import { getPlacePosition } from '../../common/base/PlaceStyleHelper'
|
|||
|
import { SpacePlus } from './SpacePlus'
|
|||
|
|
|||
|
/**板件计算工具类 小板轮廓,走刀路径等 */
|
|||
|
export class BlockPlus {
|
|||
|
|
|||
|
/** 小板初始化:1各种轮廓|走刀路径|,2尺寸扩展后的轮廓与走刀路径
|
|||
|
* 配置入参
|
|||
|
* isRectBlockChamfer = false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer = false, // 异形板件倒角开料
|
|||
|
preMillingSize = 0, // 预铣尺寸
|
|||
|
*/
|
|||
|
static initBlock(block: PlaceBlock, placeMaterial: PlaceMaterial, params: any) {
|
|||
|
if(block.blockDetail == null) {
|
|||
|
console.error('BlockPlus.initBlock: block.blockDetail is undefined', block)
|
|||
|
return
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour)
|
|||
|
return // 已初始化
|
|||
|
|
|||
|
const {
|
|||
|
isRectBlockChamfer = false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer = false, // 异形板件倒角开料
|
|||
|
preMillingSize = 0, // 预铣尺寸
|
|||
|
helpCutStyle = 0, // 辅助开料方式(0同刀辅助开料 1小刀辅助开料) useSameKnifeToHelpCutStyle
|
|||
|
helpCutGap = 2, // 同刀辅助开料缝隙
|
|||
|
} = params
|
|||
|
|
|||
|
if (!block.blockDetail) { return }
|
|||
|
const pm = placeMaterial
|
|||
|
const bd = block.blockDetail
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (pm == null) {
|
|||
|
return // 异常
|
|||
|
}
|
|||
|
const cutKnifeR = pm.diameter / 2
|
|||
|
const cutGap = pm.cutKnifeGap
|
|||
|
|
|||
|
// 开料偏移值 ,矩形波倒角
|
|||
|
bd.offsetKnifeRadius = pm.diameter / 2
|
|||
|
bd.isOffsetRounding = true // 默认要倒角
|
|||
|
bd.preMillingSize = pm.preMillingSize
|
|||
|
|
|||
|
if (bd.points.length == 0) // 矩形板,设置不倒角
|
|||
|
{
|
|||
|
bd.isOffsetRounding = isRectBlockChamfer
|
|||
|
}
|
|||
|
else // 异形板
|
|||
|
{
|
|||
|
// 异形板倒角
|
|||
|
bd.isOffsetRounding = isUnRegularBlockChamfer
|
|||
|
}
|
|||
|
|
|||
|
// 初始化 小板基础轮廓
|
|||
|
// 1.原始轮廓,成品轮廓
|
|||
|
|
|||
|
const border_final = this.createFinalBorder(bd, block)
|
|||
|
// 2.开料轮廓 <不含预铣>
|
|||
|
const border_org = this.createOrgBorder(bd)
|
|||
|
|
|||
|
bd.borderContour = new PlaceBorderContour(PlaceStyle.FRONT, border_final, border_org)
|
|||
|
|
|||
|
// 3.开料轮廓_带预铣, 外扩尺寸
|
|||
|
bd.borderContour.borderPreMilling = border_org
|
|||
|
bd.preMillingExpandSize = new SizeExpand()
|
|||
|
|
|||
|
if (preMillingSize > 0.0001) {
|
|||
|
const rt = this.creatOrgBorderWithPrevCut(block, border_org, preMillingSize)
|
|||
|
bd.borderContour.borderPreMilling = rt?.newBorders || []
|
|||
|
bd.preMillingExpandSize = rt?.newSizeExpand || new SizeExpand()
|
|||
|
// console.log('开料轮廓_带预铣, 外扩尺寸==》after', block, rt.newSizeExpand)
|
|||
|
}
|
|||
|
|
|||
|
// 4. 板内走刀路径,板内空间
|
|||
|
const innerGroup = this.analyeInners(bd, cutKnifeR, cutGap)
|
|||
|
|
|||
|
bd.borderContour.borderModelThrough = innerGroup.borders_inner_org
|
|||
|
bd.borderContour.borderModelThroughR = innerGroup.borders_inner_r
|
|||
|
bd.borderContour.cutLinesModelThrough = innerGroup.borders_inner_cut
|
|||
|
bd.borderContour.borderInnerPlace = innerGroup.borders_inner_place
|
|||
|
bd.borderContour.blockInnerSpace = innerGroup.spaces
|
|||
|
|
|||
|
// 5 造型外扩轮廓, 外扩尺寸
|
|||
|
const { pls_model, sizeout: sizeout_model } = this.createPolyline_model(block)
|
|||
|
bd.borderContour.polylinesOutModel = pls_model
|
|||
|
bd.modelExpandSize = sizeout_model
|
|||
|
|
|||
|
// 6. 2V刀路 外扩轮廓,外扩尺寸
|
|||
|
const { pls_2v, sizeout_2v } = this.createPolyline_2vModel(block)
|
|||
|
bd.borderContour.polylines2vModel = pls_2v || []
|
|||
|
bd.vKnifeModelExpandSize = sizeout_2v
|
|||
|
|
|||
|
// 7.同刀辅助 外扩尺寸
|
|||
|
let isUseSameKnifeToHelpCut = helpCutStyle || 0
|
|||
|
let useSameKnifeToHelpCutGap = helpCutGap || 0
|
|||
|
const isSameKnifeToCut = isUseSameKnifeToHelpCut && useSameKnifeToHelpCutGap > 0
|
|||
|
if (isSameKnifeToCut == false || bd.isUseSameKnifeToHelpCut == false) {
|
|||
|
// 未启动同刀辅助, 或 该小板 不需要同刀辅助
|
|||
|
bd.useSameKnifeToHelpCutGap = 0
|
|||
|
bd.sameKnifeHelpExpandSize = new SizeExpand()
|
|||
|
}
|
|||
|
else {
|
|||
|
const gap = useSameKnifeToHelpCutGap
|
|||
|
bd.useSameKnifeToHelpCutGap = gap
|
|||
|
bd.sameKnifeHelpExpandSize = new SizeExpand({ left: gap, right: gap, under: gap, upper: gap })
|
|||
|
}
|
|||
|
// 2V刀路,预洗,同刀辅助开料,出板造型刀
|
|||
|
this.resetBlock(block, pm)
|
|||
|
}
|
|||
|
|
|||
|
/** 重设小板 ,因为板材重新设置 预铣值 或 板外下刀 */
|
|||
|
static resetBlock(block: PlaceBlock, placeMaterial: PlaceMaterial) {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.resetBlock: block.blockDetail is undefined', block)
|
|||
|
return
|
|||
|
}
|
|||
|
const pm = placeMaterial
|
|||
|
const bd = block.blockDetail
|
|||
|
|
|||
|
const preMillingSize = pm.preMillingSize
|
|||
|
// startDebug(block);
|
|||
|
if (!bd.borderContour) {
|
|||
|
console.error('BlockPlus.resetBlock: bd.borderContour is undefined', block)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 开料刀 修改了,内部空间发生变化
|
|||
|
if (!equal(bd.offsetKnifeRadius, pm.diameter / 2)) {
|
|||
|
bd.offsetKnifeRadius = pm.diameter / 2
|
|||
|
bd.borderContour.cutKnifeChanged()
|
|||
|
|
|||
|
// 4. 板内走刀路径,板内空间
|
|||
|
const innerGroup = this.analyeInners(bd, pm.diameter / 2, pm.cutKnifeGap)
|
|||
|
|
|||
|
bd.borderContour.borderModelThrough = innerGroup.borders_inner_org
|
|||
|
bd.borderContour.cutLinesModelThrough = innerGroup.borders_inner_cut
|
|||
|
bd.borderContour.borderInnerPlace = innerGroup.borders_inner_place
|
|||
|
bd.borderContour.blockInnerSpace = innerGroup.spaces
|
|||
|
}
|
|||
|
|
|||
|
// 因为预铣, 同刀辅助会影响到开料走刀等轮廓,所以要将受影响的轮廓清空,需要的时候再生成
|
|||
|
// 预铣
|
|||
|
if (!equal(bd.preMillingSize, pm.preMillingSize)) {
|
|||
|
bd.preMillingSize = preMillingSize
|
|||
|
bd.borderContour.preValueChanged()
|
|||
|
}
|
|||
|
// 同刀辅助
|
|||
|
let newTDFZ = 0
|
|||
|
if (pm.isHelpCut && pm.helpCutGap > 0 && block.blockDetail.isUseSameKnifeToHelpCut) {
|
|||
|
newTDFZ = pm.helpCutGap
|
|||
|
block.blockDetail.sameKnifeHelpExpandSize = new SizeExpand({ left: newTDFZ, right: newTDFZ, upper: newTDFZ, under: newTDFZ })
|
|||
|
}
|
|||
|
else {
|
|||
|
newTDFZ = 0
|
|||
|
block.blockDetail.sameKnifeHelpExpandSize = new SizeExpand()
|
|||
|
}
|
|||
|
|
|||
|
if (!equal(newTDFZ, bd.useSameKnifeToHelpCutGap)) {
|
|||
|
bd.useSameKnifeToHelpCutGap = newTDFZ
|
|||
|
bd.borderContour.sameKnifeGapChanged()
|
|||
|
}
|
|||
|
|
|||
|
const cutRadius = (pm.diameter + pm.cutKnifeGap) / 2
|
|||
|
|
|||
|
// 预铣
|
|||
|
let off1 = block.blockDetail.preMillingExpandSize || new SizeExpand()
|
|||
|
// 造型外扩
|
|||
|
const off2 = block.blockDetail.modelExpandSize || new SizeExpand()
|
|||
|
// 2v 板外下刀
|
|||
|
const off3 = block.blockDetail.vKnifeModelExpandSize || new SizeExpand()
|
|||
|
// 同刀辅助
|
|||
|
let off4 = block.blockDetail?.sameKnifeHelpExpandSize || new SizeExpand()
|
|||
|
|
|||
|
// 不启用 预铣
|
|||
|
// if (preMillingSize < 0.0001)
|
|||
|
// off1 = new SizeExpand()
|
|||
|
if (newTDFZ < 0.001)
|
|||
|
off4 = new SizeExpand()
|
|||
|
|
|||
|
// 预铣+同刀辅助+, 造型外扩,2v刀路 应该取最大值
|
|||
|
const off = new SizeExpand()
|
|||
|
off.left = Math.max(off1.left + off4.left + cutRadius, off2.left, off3.left)
|
|||
|
off.right = Math.max(off1.right + off4.right + cutRadius, off2.right, off3.right)
|
|||
|
off.bottom = Math.max(off1.bottom + off4.bottom + cutRadius, off2.bottom, off3.bottom)
|
|||
|
off.top = Math.max(off1.top + off4.top + cutRadius, off2.top, off3.top)
|
|||
|
|
|||
|
off.setSize()
|
|||
|
bd.currentSizeExpand = off
|
|||
|
}
|
|||
|
|
|||
|
/** 小板是否有超出造型或二维刀路 */
|
|||
|
static hasModelOutBlock(block: PlaceBlock): boolean {
|
|||
|
if (block.blockDetail == null)
|
|||
|
return false
|
|||
|
if (block.blockDetail.borderContour == null)
|
|||
|
return false
|
|||
|
|
|||
|
if (block.blockDetail.borderContour.polylinesOutModel == null || block.blockDetail.borderContour.polylines2vModel == null)
|
|||
|
return false
|
|||
|
|
|||
|
return block.blockDetail.borderContour.polylinesOutModel.length + block.blockDetail.borderContour.polylines2vModel.length > 0
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 成品轮廓 isPlaced=false为不旋转的 */
|
|||
|
static getFinalBorder(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getOrgBorderNew: bu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
return bu.borderFinal
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 开料轮廓-不含预铣 isPlaced=false为不旋转的 */
|
|||
|
static getOrgBorder(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getOrgBorder: bu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
return bu.borderOrg
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 开料轮廓-不含预铣 isPlaced=false为不旋转的 */
|
|||
|
static getOrgBorderNew(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
const bu = this.getPlacedUnitNew(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getOrgBorderNew: bu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
return bu.borderOrg
|
|||
|
}
|
|||
|
/** 获得当前板 轮廓多段线 */
|
|||
|
static getOrgPolyline(block: PlaceBlock): Polyline | null {
|
|||
|
if (block.blockDetail == null) {
|
|||
|
console.error('BlockPlus.getOrgPolyline: block.blockDetail is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
const bd = block.blockDetail.borderContour
|
|||
|
if (bd == null) {
|
|||
|
console.error('BlockPlus.getOrgPolyline: bd is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
if (!bd.polylineOrg) {
|
|||
|
const border = bd.borderOrg
|
|||
|
const pl = PolylineHelper.createByCurve2d(border)
|
|||
|
bd.polylineOrg = pl
|
|||
|
}
|
|||
|
return bd.polylineOrg
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 开料轮廓 _有预铣含预铣 */
|
|||
|
static getBorder(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
if (block.blockDetail == null) {
|
|||
|
console.error('BlockPlus.getBorder: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
|
|||
|
let preSize = block.blockDetail.preMillingSize
|
|||
|
if (preSize < 0.0001)
|
|||
|
preSize = 0
|
|||
|
|
|||
|
// 初始
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
if (baseContour == null) {
|
|||
|
console.error('BlockPlus.getBorder: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!baseContour.border ||(Array.isArray(baseContour.border) && baseContour.border.length ==0)) // 生成 预铣轮廓
|
|||
|
{
|
|||
|
const border = preSize == 0 ? baseContour.borderOrg : baseContour.borderPreMilling
|
|||
|
baseContour.border = border
|
|||
|
}
|
|||
|
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.border) {
|
|||
|
pbu.border = this.transformBorder(baseContour.border, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.border
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 开料轮廓—有预铣带预铣-有同刀辅助带同刀辅助 */
|
|||
|
static getBorder_sameKnife(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
if (block.blockDetail == null) {
|
|||
|
console.error('BlockPlus.getBorder_sameKnife: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
// 如果没有同刀辅助,直接返回开料轮廓
|
|||
|
let helpCutGap = block.blockDetail.useSameKnifeToHelpCutGap
|
|||
|
|
|||
|
if (helpCutGap < 0.001)
|
|||
|
helpCutGap = 0
|
|||
|
|
|||
|
// 初始
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
if (baseContour == null) {
|
|||
|
console.error('BlockPlus.getBorder_sameKnife: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!baseContour.borderSameKnifeHelpCut) {
|
|||
|
const borders = this.getBorder(block, false)
|
|||
|
if (helpCutGap == 0) // 无同刀辅助
|
|||
|
{
|
|||
|
baseContour.borderSameKnifeHelpCut = borders
|
|||
|
}
|
|||
|
else {
|
|||
|
let rounding = block.blockDetail.isOffsetRounding
|
|||
|
if (block.isUnRegular)
|
|||
|
rounding = true // 异形板 必须倒角
|
|||
|
baseContour.borderSameKnifeHelpCut = this.offsetCurves(borders, helpCutGap, rounding) // 必须倒角,否则 尖角超出 开料范围
|
|||
|
}
|
|||
|
}
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.borderSameKnifeHelpCut) {
|
|||
|
pbu.borderSameKnifeHelpCut = this.transformBorder(baseContour.borderSameKnifeHelpCut, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.borderSameKnifeHelpCut
|
|||
|
}
|
|||
|
|
|||
|
/** 获得走刀路径(含预铣) isPlaced = false为不旋转 */
|
|||
|
/**
|
|||
|
*
|
|||
|
* @param block 小板
|
|||
|
* @param placeMaterial 开料大板
|
|||
|
* @param isPlaced 是否旋转
|
|||
|
* @param placeStyle 旋转后的放置方式
|
|||
|
* @param config 配置
|
|||
|
{
|
|||
|
isRectBlockChamfer: false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer: false, // 异形板件倒角开料
|
|||
|
}
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
static getCutLines(block: PlaceBlock, placeMaterial: PlaceMaterial, isPlaced = true, placeStyle: PlaceStyle | undefined, config: any): Curve2d[] {
|
|||
|
// 走刀路径由开料轮廓(含预铣) border_plus 偏移一个刀半径而成
|
|||
|
const {
|
|||
|
isRectBlockChamfer = false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer = false, // 异形板件倒角开料
|
|||
|
|
|||
|
} = config
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.getCutLines: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!block.blockDetail.borderContour) {
|
|||
|
console.error('BlockPlus.getCutLines: block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
// 初始
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
if (!baseContour.cutLines) {
|
|||
|
const borders = this.getBorder(block, false)
|
|||
|
// 偏移值
|
|||
|
const offvalue = placeMaterial.diameter / 2 // 开料刀的一半
|
|||
|
// 是否倒角
|
|||
|
let isOffsetRounding = false // block.SaleBlockDetail.IsOffsetRounding;
|
|||
|
if (block.isUnRegular == false) // 矩形板,设置不倒角
|
|||
|
{
|
|||
|
isOffsetRounding = isRectBlockChamfer
|
|||
|
}
|
|||
|
else // 异形板
|
|||
|
{
|
|||
|
// 异形倒角
|
|||
|
isOffsetRounding = isUnRegularBlockChamfer
|
|||
|
}
|
|||
|
baseContour.cutLines = this.offsetCurves(borders, offvalue, isOffsetRounding)
|
|||
|
}
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.cutLines) {
|
|||
|
pbu.cutLines = this.transformBorder(baseContour.cutLines, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.cutLines
|
|||
|
}
|
|||
|
/**
|
|||
|
* 获得 同刀辅助 的走刀路径
|
|||
|
* @param block 小板
|
|||
|
* @param isPlaced 是否翻转
|
|||
|
* @param placeStyle 翻转后的放置方式
|
|||
|
* @param config 配置
|
|||
|
* {
|
|||
|
isRectBlockChamfer: false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer: false, // 异形板件倒角
|
|||
|
} = config || {}
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
static getCutLines_sameKnife(block: PlaceBlock, placeMaterial: PlaceMaterial, isPlaced = true, placeStyle?: PlaceStyle, config?: any): Curve2d[] {
|
|||
|
// 同刀辅助 走刀路径 由 开料轮廓 _含预铣_同刀辅助 偏移一个刀半径 厚度 而成
|
|||
|
const {
|
|||
|
isRectBlockChamfer = false, // 矩形板件倒角开料
|
|||
|
isUnRegularBlockChamfer = false, // 异形板件倒角开料
|
|||
|
|
|||
|
} = config || {}
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.getCutLines_sameKnife: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
// 不用同刀辅助
|
|||
|
const helpCutGap = block.blockDetail.useSameKnifeToHelpCutGap
|
|||
|
if (helpCutGap < 0.001) {
|
|||
|
return this.getCutLines(block, placeMaterial, isPlaced, placeStyle, config)
|
|||
|
}
|
|||
|
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
if (baseContour == null) {
|
|||
|
console.error('BlockPlus.getCutLines_sameKnife: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!baseContour.cutLinesSameKnifeHelpCut) {
|
|||
|
const borders = this.getBorder_sameKnife(block, false)
|
|||
|
// 偏移值
|
|||
|
const kr = placeMaterial.diameter / 2 // 开料刀的一半
|
|||
|
// 同刀辅助 不倒角 ,
|
|||
|
// 是否倒角 异形板必须倒角
|
|||
|
let isOffsetRounding = false // block.SaleBlockDetail.IsOffsetRounding;
|
|||
|
if (block.isUnRegular == false) // 矩形板,设置不倒角
|
|||
|
{
|
|||
|
isOffsetRounding = isRectBlockChamfer
|
|||
|
}
|
|||
|
else // 异形板
|
|||
|
{
|
|||
|
isOffsetRounding = isUnRegularBlockChamfer
|
|||
|
}
|
|||
|
baseContour.cutLinesSameKnifeHelpCut = this.offsetCurves(borders, kr, isOffsetRounding)
|
|||
|
}
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.cutLinesSameKnifeHelpCut) {
|
|||
|
pbu.cutLinesSameKnifeHelpCut = this.transformBorder(baseContour.cutLinesSameKnifeHelpCut, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.cutLinesSameKnifeHelpCut
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获得 手动排版路径 包括板外下刀等轮廓
|
|||
|
* 由开料轮廓 偏移 ( 预铣 ,同刀辅助, 开料刀半径 , 缝隙/2 )
|
|||
|
* 再与 二维刀路,板外小刀,造型外扩 合并起来的
|
|||
|
*/
|
|||
|
static getBorder_moving(block: PlaceBlock, placeMaterial: PlaceMaterial, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
if (!block.blockDetail || !block.blockDetail.borderContour) {
|
|||
|
console.error('BlockPlus.getBorder_moving: block.blockDetail or block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
this.theBlock = block
|
|||
|
const bd = block.blockDetail
|
|||
|
|
|||
|
// 初始
|
|||
|
const baseContour = bd.borderContour
|
|||
|
if (baseContour == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!baseContour.borderMoving) {
|
|||
|
// 1.开料轮廓<带预铣>
|
|||
|
const borders = this.getBorder(block, false)
|
|||
|
// 偏移值 = 同刀辅助 + 刀半径 + 缝隙 /2
|
|||
|
const cutGap = block.blockDetail.useSameKnifeToHelpCutGap + (placeMaterial.diameter + placeMaterial.cutKnifeGap) / 2
|
|||
|
// 是否倒角(如果倒角,手动排版,拖拉时,停靠点不便计算,所以设置成不倒角,然后截断>
|
|||
|
const isOffsetRounding = false
|
|||
|
|
|||
|
// 原轮廓
|
|||
|
let border_moving = this.offsetCurves(borders, cutGap, isOffsetRounding)
|
|||
|
const pl = this.borderToPolyline(border_moving)
|
|||
|
|
|||
|
// 造型的外扩,2v刀路的
|
|||
|
const pls_m = baseContour.polylinesOutModel.concat(baseContour.polylines2vModel)
|
|||
|
// 合并
|
|||
|
const rpl = this.unionPolylines(pl, pls_m)
|
|||
|
//
|
|||
|
border_moving = this.polylineToBorder(rpl)
|
|||
|
|
|||
|
baseContour.borderMoving = border_moving
|
|||
|
}
|
|||
|
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
return pbu.borderMoving
|
|||
|
}
|
|||
|
static getBorder_moving_new(block: PlaceBlock, pb: PlaceMaterial, isPlaced = true, placeStyle: PlaceStyle): Curve2d[] {
|
|||
|
if (block.blockDetail == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
this.theBlock = block
|
|||
|
const bd = block.blockDetail
|
|||
|
|
|||
|
// 初始
|
|||
|
const baseContour = bd.borderContour
|
|||
|
if (!baseContour) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!baseContour.borderMoving) {
|
|||
|
// 1.开料轮廓<带预铣>
|
|||
|
const borders = this.getBorder(block, false)
|
|||
|
// 偏移值 = 同刀辅助 + 刀半径 + 缝隙 /2
|
|||
|
const cutGap = block.blockDetail.useSameKnifeToHelpCutGap + (pb.diameter + pb.cutKnifeGap) / 2
|
|||
|
// 是否倒角(如果倒角,手动排版,拖拉时,停靠点不便计算,所以设置成不倒角,然后截断>
|
|||
|
const isOffsetRounding = false
|
|||
|
|
|||
|
// 原轮廓
|
|||
|
let border_moving = this.offsetCurves(borders, cutGap, isOffsetRounding)
|
|||
|
const pl = this.borderToPolyline(border_moving)
|
|||
|
|
|||
|
// 造型的外扩,2v刀路的
|
|||
|
const pls_m = baseContour.polylinesOutModel.concat(baseContour.polylines2vModel)
|
|||
|
// 合并
|
|||
|
const rpl = this.unionPolylines(pl, pls_m)
|
|||
|
//
|
|||
|
border_moving = this.polylineToBorder(rpl)
|
|||
|
|
|||
|
baseContour.borderMoving = border_moving
|
|||
|
}
|
|||
|
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getBorder_moving_new: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.borderMoving) {
|
|||
|
pbu.borderMoving = this.transformBorder(baseContour.borderMoving, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.borderMoving
|
|||
|
}
|
|||
|
|
|||
|
static getOutModelPloyline(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Polyline[] {
|
|||
|
if (!block.blockDetail || !block.blockDetail.borderContour) {
|
|||
|
console.error('BlockPlus.getOutModelPloyline: block.blockDetail or block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
const bd = block.blockDetail
|
|||
|
// 初始
|
|||
|
const baseContour = bd.borderContour
|
|||
|
|
|||
|
if (baseContour == null) {
|
|||
|
console.error('BlockPlus.getOutModelPloyline: baseContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
const pls_m = baseContour.polylinesOutModel.concat(baseContour.polylines2vModel)
|
|||
|
|
|||
|
if (placeStyle == PlaceStyle.FRONT)
|
|||
|
return pls_m
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
console.error('BlockPlus.getOutModelPloyline: pbu is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
let newPls: Polyline[] = []
|
|||
|
for (let pl of pls_m) {
|
|||
|
let newpl = this.transformPolyline(pl, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
newPls.push(newpl)
|
|||
|
}
|
|||
|
return newPls
|
|||
|
}
|
|||
|
|
|||
|
static theBlock
|
|||
|
/** 获取轮廓用于王者优化,预铣 + 同刀辅助 ,造型外扩 + 2维刀路外扩 */
|
|||
|
static getBorder_WZYH(block: PlaceBlock, placeMaterial: PlaceMaterial, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[] {
|
|||
|
this.theBlock = block
|
|||
|
const bd = block.blockDetail
|
|||
|
if (!bd || !bd.borderContour) {
|
|||
|
console.error('BlockPlus.getBorder_WZYH: block.blockDetail or block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
const baseContour = bd.borderContour
|
|||
|
// 生成 同刀辅助 路径 <原方向》
|
|||
|
if (baseContour.borderKingOptimize == null) {
|
|||
|
// 开料轮廓 <同刀辅助>
|
|||
|
const borders = this.getBorder_sameKnife(block, false)
|
|||
|
|
|||
|
// 偏移值= 同刀辅助 + 刀半径 + + 缝隙 /2
|
|||
|
const cutGap = (placeMaterial.diameter + placeMaterial.diameter) / 2
|
|||
|
// 是否倒角 < 如果倒角,手动排版,拖拉时,停靠点 不好计算,所以设置成不倒角,然后截断>,
|
|||
|
const isOffsetRounding = bd.isOffsetRounding
|
|||
|
|
|||
|
// 走刀路径
|
|||
|
const borders2 = this.offsetCurves(borders, cutGap, isOffsetRounding)
|
|||
|
const pl = this.borderToPolyline(borders2)
|
|||
|
// 造型的外扩,2v刀路的
|
|||
|
const pls_m = baseContour.polylinesOutModel.concat(baseContour.polylines2vModel)
|
|||
|
// 合并
|
|||
|
const rpl = this.unionPolylines(pl, pls_m)
|
|||
|
|
|||
|
baseContour.borderKingOptimize = this.polylineToBorder(rpl)
|
|||
|
}
|
|||
|
|
|||
|
// 放置后
|
|||
|
const pbu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (pbu == null) {
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!pbu.borderKingOptimize) {
|
|||
|
pbu.borderKingOptimize = this.transformBorder(baseContour.borderKingOptimize, pbu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
}
|
|||
|
return pbu.borderKingOptimize
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 内部轮廓 <挖穿造型> */
|
|||
|
static getBorders_inner(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[][] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getBorders_inner: 获取板的内部轮廓失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
// 如果没有内部轮廓
|
|||
|
if (bu.borderModelThrough == null) {
|
|||
|
const borders = this.getBorders_inner(block, false)
|
|||
|
const borders_off: Curve2d[][] = []
|
|||
|
for (const border of borders) {
|
|||
|
const newBorder = this.transformBorder(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
borders_off.push(newBorder)
|
|||
|
}
|
|||
|
bu.borderModelThrough = borders_off
|
|||
|
}
|
|||
|
return bu.borderModelThrough
|
|||
|
}
|
|||
|
/** 获得 内部轮廓 <挖穿造型> */
|
|||
|
static getBorders_innerNew(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[][] {
|
|||
|
const bu = this.getPlacedUnitNew(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getBorders_innerNew: 获取板的内部轮廓失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (bu.borderModelThrough == null) {
|
|||
|
const borders = this.getBorders_innerNew(block, false)
|
|||
|
const borders_off: Curve2d[][] = []
|
|||
|
for (const border of borders) {
|
|||
|
const newBorder = this.transformBorderNew(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
borders_off.push(newBorder)
|
|||
|
}
|
|||
|
bu.borderModelThrough = borders_off
|
|||
|
}
|
|||
|
return bu.borderModelThrough
|
|||
|
}
|
|||
|
/** 获得内部轮廓 <挖穿造型> 半径 */
|
|||
|
static getBorders_inner_r(block: PlaceBlock) {
|
|||
|
if (block.blockDetail == null || block.blockDetail.borderContour == null) {
|
|||
|
console.error('BlockPlus.getBorders_inner_r: block.blockDetail or block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
return block.blockDetail.borderContour.borderModelThroughR
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 内部走刀轮廓 <挖穿造型> */
|
|||
|
static getCutLines_inner(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[][] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getCutLines_inner: 获取板的内部走刀轮廓失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (bu.cutLinesModelThrough == null) {
|
|||
|
const borders = this.getCutLines_inner(block, false)
|
|||
|
const borders_off: Curve2d[][] = []
|
|||
|
for (const border of borders) {
|
|||
|
const newBorder = this.transformBorder(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
borders_off.push(newBorder)
|
|||
|
}
|
|||
|
bu.cutLinesModelThrough = borders_off
|
|||
|
}
|
|||
|
return bu.cutLinesModelThrough
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 内部排版轮廓 <挖穿造型> */
|
|||
|
static getInnerPlaceBorders(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[][] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getInnerPlaceBorders: 获取板的内部排版轮廓失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (bu.borderInnerPlace == null) {
|
|||
|
const borders = this.getInnerPlaceBorders(block, false)
|
|||
|
const borders_off: Curve2d[][] = []
|
|||
|
for (const border of borders) {
|
|||
|
const newBorder = this.transformBorder(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
borders_off.push(newBorder)
|
|||
|
}
|
|||
|
bu.borderInnerPlace = borders_off
|
|||
|
}
|
|||
|
return bu.borderInnerPlace
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 板内空间 《挖穿孔洞 + 缺角》 */
|
|||
|
static getSpaces(block: PlaceBlock, pm: PlaceMaterial): PlaceSpace[] {
|
|||
|
if (block.blockDetail == null || block.blockDetail.borderContour == null) {
|
|||
|
console.error('BlockPlus.getSpaces: block.blockDetail or block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
const bu = block.blockDetail.borderContour
|
|||
|
if (!bu.blockOuterSpace)
|
|||
|
bu.blockOuterSpace = this.createOutSpaces(block, pm) // 缺角空间不存在,创建
|
|||
|
// 挖穿孔洞 + 缺角
|
|||
|
return bu.blockInnerSpace.concat(bu.blockOuterSpace)
|
|||
|
}
|
|||
|
|
|||
|
static getInnerSpaces(block: PlaceBlock): PlaceSpace[] {
|
|||
|
const bu = this.getPlacedUnit(block, false)
|
|||
|
// 挖穿孔洞
|
|||
|
return bu ? bu.blockInnerSpace : []
|
|||
|
}
|
|||
|
|
|||
|
static getModelHole(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle): Curve2d[][] {
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getModelHole: 获取板的轮廓集失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (!bu.borderInnerPlace) {
|
|||
|
if (block.blockDetail == undefined) {
|
|||
|
console.error('BlockPlus.getModelHole: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour == undefined) {
|
|||
|
console.error('BlockPlus.getModelHole: block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
|
|||
|
const org_list = block.blockDetail.borderContour.borderInnerPlace
|
|||
|
if (!org_list || org_list.length == 0)
|
|||
|
return []
|
|||
|
const liset: Curve2d[][] = []
|
|||
|
for (const cur of org_list) {
|
|||
|
const newCur = this.transformBorder(cur, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
if (newCur)
|
|||
|
liset.push(newCur)
|
|||
|
}
|
|||
|
bu.borderInnerPlace = liset
|
|||
|
}
|
|||
|
return bu.borderInnerPlace
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 板的轮廓多段线(包括内部挖穿) */
|
|||
|
static getOrgPloylines(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle) {
|
|||
|
const borderPlus = this.getBorder(block, isPlaced, placeStyle)
|
|||
|
const innerBorders = this.getBorders_inner(block, isPlaced, placeStyle)
|
|||
|
|
|||
|
const pl = this.borderToPolyline(borderPlus)
|
|||
|
const pls_inner = new Array<Polyline>()
|
|||
|
for (const border of innerBorders) {
|
|||
|
const npl = this.borderToPolyline(border)
|
|||
|
pls_inner.push(npl)
|
|||
|
}
|
|||
|
return { pl, pls_inner }
|
|||
|
}
|
|||
|
|
|||
|
/** 获得 板的开料多段线(包括内部挖穿) */
|
|||
|
static getCutPloylines(block: PlaceBlock, pm: PlaceMaterial, isPlaced = true, placeStyle?: PlaceStyle) {
|
|||
|
const borderPlus = this.getCutLines_sameKnife(block, pm, isPlaced, placeStyle)
|
|||
|
const innerBorders = this.getCutLines_inner(block, isPlaced, placeStyle)
|
|||
|
|
|||
|
const pl = this.borderToPolyline(borderPlus)
|
|||
|
const pls_inner = new Array<Polyline>()
|
|||
|
for (const border of innerBorders) {
|
|||
|
const npl = this.borderToPolyline(border)
|
|||
|
pls_inner.push(npl)
|
|||
|
}
|
|||
|
return { pl, pls_inner }
|
|||
|
}
|
|||
|
|
|||
|
/** 获得小板 板外造型轮廓 */
|
|||
|
static getOutModelBorders(block: PlaceBlock, isPlaced = true, placeStyle?: PlaceStyle) {
|
|||
|
// b1.SaleBlockDetail.borderUnit.polylines_outModel
|
|||
|
// b1.SaleBlockDetail.borderUnit.polylines_2vModel
|
|||
|
const bu = this.getPlacedUnit(block, isPlaced, placeStyle)
|
|||
|
if (bu == null) {
|
|||
|
console.error('BlockPlus.getOutModelBorders: 获取板的轮廓集失败', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (block.blockDetail == undefined) {
|
|||
|
console.error('BlockPlus.getOutModelBorders: block.blockDetail is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour == undefined) {
|
|||
|
console.error('BlockPlus.getOutModelBorders: block.blockDetail.borderContour is undefined', block)
|
|||
|
return []
|
|||
|
}
|
|||
|
if (bu.polylinesOutModel == null) {
|
|||
|
const polylines_outModel = block.blockDetail.borderContour.polylinesOutModel
|
|||
|
const new_outModels: Polyline[] = []
|
|||
|
for (const border of polylines_outModel) {
|
|||
|
const newBorder = this.transformPolyline(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
new_outModels.push(newBorder)
|
|||
|
}
|
|||
|
bu.polylinesOutModel = new_outModels
|
|||
|
}
|
|||
|
if (bu.polylines2vModel == null) {
|
|||
|
const polylines_2vModel = block.blockDetail.borderContour.polylines2vModel
|
|||
|
const new_outModels: Polyline[] = []
|
|||
|
for (const border of polylines_2vModel) {
|
|||
|
const newBorder = this.transformPolyline(border, bu.placeStyle, block.cutWidth, block.cutLength)
|
|||
|
new_outModels.push(newBorder)
|
|||
|
}
|
|||
|
bu.polylines2vModel = new_outModels
|
|||
|
}
|
|||
|
return bu.polylinesOutModel.concat(bu.polylines2vModel)
|
|||
|
}
|
|||
|
|
|||
|
/** 获得小板外形轮廓 */
|
|||
|
static getOrgContour(block: PlaceBlock): any {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.getOrgContour: block.blockDetail is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
|
|||
|
if (!block.blockDetail.orgContourData) {
|
|||
|
const pts: any = []
|
|||
|
const buls: any = []
|
|||
|
if (!block.isUnRegular) {
|
|||
|
pts.push({ x: 0, y: 0 })
|
|||
|
pts.push({ x: block.width, y: 0 })
|
|||
|
pts.push({ x: block.width, y: block.length })
|
|||
|
pts.push({ x: 0, y: block.length })
|
|||
|
buls.push(0)
|
|||
|
buls.push(0)
|
|||
|
buls.push(0)
|
|||
|
buls.push(0)
|
|||
|
}
|
|||
|
else // 矩形板
|
|||
|
{
|
|||
|
for (const p of block.blockDetail.orgPoints) {
|
|||
|
pts.push({ x: p.pointX, y: p.pointY })
|
|||
|
buls.push(p.curve)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
block.blockDetail.orgContourData = { pts, buls }
|
|||
|
}
|
|||
|
return block.blockDetail.orgContourData
|
|||
|
}
|
|||
|
|
|||
|
/** 获得板的 轮廓集 isPlaced=false为不旋转的 */
|
|||
|
private static getPlacedUnit(block: PlaceBlock, isPlaced = true, style?: PlaceStyle): PlaceBorderContour | null {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.getPlacedUnit: block.blockDetail is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour == undefined) {
|
|||
|
console.error('BlockPlus.getPlacedUnit: block.blockDetail.borderContour is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
if (isPlaced == false)
|
|||
|
style = PlaceStyle.FRONT
|
|||
|
if (isPlaced == true) {
|
|||
|
if (style == undefined || style == null)
|
|||
|
style = block.placeStyle
|
|||
|
}
|
|||
|
|
|||
|
if (style == undefined) {
|
|||
|
style = PlaceStyle.FRONT
|
|||
|
}
|
|||
|
|
|||
|
if (style == PlaceStyle.FRONT)
|
|||
|
return baseContour
|
|||
|
|
|||
|
let placeContour = baseContour.placeContours.find(t => t.placeStyle == style)
|
|||
|
if (placeContour == null) {
|
|||
|
const border_final = this.transformBorder(baseContour.borderFinal, style, block.width, block.length)
|
|||
|
const border_org = this.transformBorder(baseContour.borderOrg, style, block.cutWidth, block.cutLength)
|
|||
|
placeContour = new PlaceBorderContour(style, border_final, border_org)
|
|||
|
baseContour.placeContours.push(placeContour)
|
|||
|
}
|
|||
|
return placeContour
|
|||
|
}
|
|||
|
/**
|
|||
|
* 获得板的 轮廓集 isPlaced=false为不旋转的
|
|||
|
* @param block
|
|||
|
* @param isPlaced
|
|||
|
* @param style
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
private static getPlacedUnitNew(block: PlaceBlock, isPlaced = true, style?: PlaceStyle): PlaceBorderContour | null {
|
|||
|
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error('BlockPlus.getPlacedUnitNew: block.blockDetail is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour == undefined) {
|
|||
|
console.error('BlockPlus.getPlacedUnitNew: block.blockDetail.borderContour is undefined', block)
|
|||
|
return null
|
|||
|
}
|
|||
|
const baseContour = block.blockDetail.borderContour
|
|||
|
|
|||
|
|
|||
|
if (isPlaced == false)
|
|||
|
style = PlaceStyle.FRONT
|
|||
|
if (isPlaced == true) {
|
|||
|
if (style == undefined || style == null)
|
|||
|
style = block.placeStyle
|
|||
|
}
|
|||
|
|
|||
|
if (style == undefined) {
|
|||
|
style = PlaceStyle.FRONT
|
|||
|
}
|
|||
|
|
|||
|
if (style == PlaceStyle.FRONT)
|
|||
|
return baseContour
|
|||
|
|
|||
|
let placeContour = baseContour.placeContours.find(t => t.placeStyle == style)
|
|||
|
if (placeContour == null) {
|
|||
|
const border_final = this.transformBorderNew(baseContour.borderFinal, style, block.width, block.length)
|
|||
|
const border_org = this.transformBorderNew(baseContour.borderOrg, style, block.cutWidth, block.cutLength)
|
|||
|
placeContour = new PlaceBorderContour(style, border_final, border_org)
|
|||
|
baseContour.placeContours.push(placeContour)
|
|||
|
}
|
|||
|
return placeContour
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/** 创建 小板成品轮廓 */
|
|||
|
private static createFinalBorder(bd: PlaceBlockDetail, block: PlaceBlock): Curve2d[] {
|
|||
|
const orgPoints = bd.orgPoints
|
|||
|
const orgBorderCurveList = new Array<Curve2d>()
|
|||
|
if (orgPoints && orgPoints.length > 1) // 异形
|
|||
|
{
|
|||
|
|
|||
|
const count = orgPoints.length
|
|||
|
for (let i = 0; i < count; i++) {
|
|||
|
const p0 = orgPoints[i]
|
|||
|
const p1 = i == count - 1 ? orgPoints[0] : orgPoints[i + 1]
|
|||
|
|
|||
|
const sideHoleCount = bd.holeListSide.filter(t => t.faceId == i).length
|
|||
|
|
|||
|
if (p0.curve == 0) // 直线
|
|||
|
{
|
|||
|
const newLine = Line2d.New(p0.pointX, p0.pointY, p1.pointX, p1.pointY)
|
|||
|
newLine.tagData = p0.sealSize
|
|||
|
newLine.tagData2 = sideHoleCount
|
|||
|
orgBorderCurveList.push(newLine)
|
|||
|
p0.radius = 0
|
|||
|
}
|
|||
|
else // 曲线
|
|||
|
{
|
|||
|
const crc = Arc2d.New(p0.pointX, p0.pointY, p1.pointX, p1.pointY, p0.curve)
|
|||
|
crc.tagData = p0.sealSize
|
|||
|
crc.tagData2 = sideHoleCount
|
|||
|
p0.radius = crc.m_Radius
|
|||
|
orgBorderCurveList.push(crc)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // 矩形板
|
|||
|
{
|
|||
|
const w = block.width
|
|||
|
const l = block.length
|
|||
|
|
|||
|
const line0 = Line2d.New(0, 0, w, 0)
|
|||
|
line0.tagData = block.sealBottom
|
|||
|
line0.tagData2 = block.holeCountBottom()
|
|||
|
|
|||
|
const line1 = Line2d.New(w, 0, w, l)
|
|||
|
line1.tagData = block.sealRight
|
|||
|
line1.tagData2 = block.holeCountRight()
|
|||
|
|
|||
|
const line2 = Line2d.New(w, l, 0, l)
|
|||
|
line2.tagData = block.sealTop
|
|||
|
line2.tagData2 = block.holeCountTop()
|
|||
|
|
|||
|
const line3 = Line2d.New(0, l, 0, 0)
|
|||
|
line3.tagData = block.sealLeft
|
|||
|
line3.tagData2 = block.holeCountLeft()
|
|||
|
|
|||
|
orgBorderCurveList.push(line0)
|
|||
|
orgBorderCurveList.push(line1)
|
|||
|
orgBorderCurveList.push(line2)
|
|||
|
orgBorderCurveList.push(line3)
|
|||
|
}
|
|||
|
return orgBorderCurveList
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 开料轮廓 */
|
|||
|
private static createOrgBorder(bd: PlaceBlockDetail): Curve2d[] {
|
|||
|
const borders = new Array<Curve2d>()
|
|||
|
|
|||
|
if (bd.points && bd.points.length > 1) // 异形
|
|||
|
{
|
|||
|
const count = bd.points.length
|
|||
|
for (let i = 0; i < count - 1; i++) // 异形点(无封边,起点终点 是重复的)
|
|||
|
{
|
|||
|
const p0 = bd.points[i]
|
|||
|
const p1 = i == count - 1 ? bd.points[0] : bd.points[i + 1]
|
|||
|
|
|||
|
const sideHoleCount = bd.holeListSide.filter(t => t.faceId == i).length
|
|||
|
|
|||
|
if (p0.curve == 0) // 直线
|
|||
|
{
|
|||
|
const newLine = Line2d.New(p0.pointX, p0.pointY, p1.pointX, p1.pointY)
|
|||
|
newLine.tagData = p0.sealSize
|
|||
|
newLine.tagData2 = sideHoleCount
|
|||
|
borders.push(newLine)
|
|||
|
p0.radius = 0
|
|||
|
}
|
|||
|
else // 曲线
|
|||
|
{
|
|||
|
const crc = Arc2d.New(p0.pointX, p0.pointY, p1.pointX, p1.pointY, p0.curve)
|
|||
|
crc.tagData = p0.sealSize
|
|||
|
crc.tagData2 = sideHoleCount
|
|||
|
p0.radius = crc.m_Radius
|
|||
|
if (p0.radius < 2) {
|
|||
|
p0.curve = 0
|
|||
|
p0.radius = 0
|
|||
|
}
|
|||
|
borders.push(crc)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // 矩形板
|
|||
|
{
|
|||
|
const w = bd.cutWidth
|
|||
|
const l = bd.cutLength
|
|||
|
const line0 = Line2d.New(0, 0, w, 0)
|
|||
|
const line1 = Line2d.New(w, 0, w, l)
|
|||
|
const line2 = Line2d.New(w, l, 0, l)
|
|||
|
const line3 = Line2d.New(0, l, 0, 0)
|
|||
|
|
|||
|
borders.push(line0)
|
|||
|
borders.push(line1)
|
|||
|
borders.push(line2)
|
|||
|
borders.push(line3)
|
|||
|
}
|
|||
|
|
|||
|
return borders
|
|||
|
}
|
|||
|
|
|||
|
/** 创建预铣轮廓 */
|
|||
|
private static creatOrgBorderWithPrevCut(block: PlaceBlock, border: Curve2d[], preSize: number) {
|
|||
|
// 矩形板
|
|||
|
const newBorders: Curve2d[] = []
|
|||
|
const newSizeExpand = new SizeExpand()
|
|||
|
if (!block.isUnRegular) {
|
|||
|
let x1 = 0
|
|||
|
let y1 = 0
|
|||
|
let x2 = block.cutWidth
|
|||
|
let y2 = block.cutLength
|
|||
|
|
|||
|
if (block.isUnRegular == false) // 矩形板
|
|||
|
{
|
|||
|
if (block.sealLeft > 0.001) {
|
|||
|
x1 -= preSize
|
|||
|
newSizeExpand.left = preSize
|
|||
|
}
|
|||
|
if (block.sealRight > 0.001) {
|
|||
|
x2 += preSize
|
|||
|
newSizeExpand.right = preSize
|
|||
|
}
|
|||
|
if (block.sealBottom > 0.001) {
|
|||
|
y1 -= preSize
|
|||
|
newSizeExpand.bottom = preSize
|
|||
|
}
|
|||
|
if (block.sealTop > 0.001) {
|
|||
|
y2 += preSize
|
|||
|
newSizeExpand.top = preSize
|
|||
|
}
|
|||
|
}
|
|||
|
newBorders.push(Line2d.New(x1, y1, x2, y1))
|
|||
|
newBorders.push(Line2d.New(x2, y1, x2, y2))
|
|||
|
newBorders.push(Line2d.New(x2, y2, x1, y2))
|
|||
|
newBorders.push(Line2d.New(x1, y2, x1, y1))
|
|||
|
newSizeExpand.setSize()
|
|||
|
return { newBorders, newSizeExpand }
|
|||
|
}
|
|||
|
|
|||
|
// 二。异形板
|
|||
|
// 2.1 先分析 每条原始边 是否预铣
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error("创建预铣轮廓时,block.blockDetail 为空", block);
|
|||
|
return;
|
|||
|
}
|
|||
|
const bd = block.blockDetail
|
|||
|
for (let i = 0; i < bd.orgPoints.length; i++) {
|
|||
|
let s = i - 1
|
|||
|
let j = i + 1
|
|||
|
if (s == -1)
|
|||
|
s = bd.orgPoints.length - 1
|
|||
|
if (j == bd.orgPoints.length)
|
|||
|
j = 0
|
|||
|
|
|||
|
const p0 = bd.orgPoints[s]
|
|||
|
const p1 = bd.orgPoints[i]
|
|||
|
const p2 = bd.orgPoints[j]
|
|||
|
|
|||
|
p1.isPreCutRequired = checkYX(p0, p1, p2, block.width, block.length)
|
|||
|
}
|
|||
|
|
|||
|
// 2.1.5 同一边,如果有缺角,则都不能预铣
|
|||
|
for (let i = 0; i < bd.orgPoints.length - 1; i++) {
|
|||
|
const j = (i + 1) % bd.orgPoints.length
|
|||
|
const pi = bd.orgPoints[i]
|
|||
|
const pj = bd.orgPoints[j]
|
|||
|
|
|||
|
// if(pi.needPreCut==false) continue;
|
|||
|
// 垂直或平行
|
|||
|
let isVertical = equal(pi.pointX, pj.pointX)
|
|||
|
if (isVertical == false) {
|
|||
|
if (equal(pi.pointY, pj.pointY)) {
|
|||
|
isVertical = false
|
|||
|
}
|
|||
|
else {
|
|||
|
continue // 斜线
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (let m = j; m < bd.orgPoints.length; m++) {
|
|||
|
const n = (m + 1) % bd.orgPoints.length
|
|||
|
|
|||
|
const pm = bd.orgPoints[m]
|
|||
|
const pn = bd.orgPoints[n]
|
|||
|
|
|||
|
// 垂直 ,同边 有缝隙,多段线 ,不能预铣
|
|||
|
if (isVertical && equal(pi.pointX, pm.pointX) && equal(pi.pointX, pn.pointX)) {
|
|||
|
pi.isPreCutRequired = false
|
|||
|
pm.isPreCutRequired = false
|
|||
|
}
|
|||
|
// 水平 ,同边 有缝隙,多段线 ,不能预铣
|
|||
|
if (isVertical == false && equal(pi.pointY, pm.pointY) && equal(pi.pointY, pn.pointY)) {
|
|||
|
pi.isPreCutRequired = false
|
|||
|
pm.isPreCutRequired = false
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 2.2 生成预铣轮廓
|
|||
|
for (let i = 0; i < border.length; i++) {
|
|||
|
const cur = border[i]
|
|||
|
let newCur: Curve2d
|
|||
|
if (cur instanceof Arc2d) {
|
|||
|
newCur = new Arc2d(cur.StartPoint, cur.EndPoint, cur.Bul)
|
|||
|
}
|
|||
|
else {
|
|||
|
newCur = new Line2d(cur.StartPoint, cur.EndPoint)
|
|||
|
}
|
|||
|
|
|||
|
if ((newCur instanceof Line2d) && newCur.m_Length < 0.001)
|
|||
|
continue
|
|||
|
// 曲线肯定不能偏移,
|
|||
|
// 直线的话,需要跟 板原始轮廓边 比对确定是否需要偏移
|
|||
|
const curNeedOff = preSize > 0 && needPrev(cur)
|
|||
|
if (curNeedOff) {
|
|||
|
// 偏移
|
|||
|
const line = cur as Line2d
|
|||
|
newCur = line.Offset(preSize)
|
|||
|
}
|
|||
|
|
|||
|
// 判断前一条边的终点是否 != 当前边的起点,需要加一条连接线
|
|||
|
if (newBorders.length > 0) {
|
|||
|
const pLast = newBorders[newBorders.length - 1]
|
|||
|
if (equal2Point(pLast.EndPoint, newCur.StartPoint) == false) {
|
|||
|
let hasJD = false
|
|||
|
if ((pLast instanceof Line2d) && (newCur instanceof Line2d)) {
|
|||
|
const p_jds: Point2d[] = []
|
|||
|
newCur.IntersectWith(pLast, p_jds)
|
|||
|
if (p_jds.length == 1) {
|
|||
|
pLast.EndPoint = new Point2d(p_jds[0].m_X, p_jds[0].m_Y)
|
|||
|
newCur.StartPoint = new Point2d(p_jds[0].m_X, p_jds[0].m_Y)
|
|||
|
hasJD = true
|
|||
|
}
|
|||
|
}
|
|||
|
if (hasJD == false) // 直接连接
|
|||
|
{
|
|||
|
const linkLine = new Line2d(pLast.EndPoint, newCur.StartPoint)
|
|||
|
newBorders.push(linkLine)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// 插入新的边
|
|||
|
newBorders.push(newCur)
|
|||
|
}
|
|||
|
|
|||
|
// 2.3 闭合 最后一边 ,是否与 第一条边 连接
|
|||
|
const firstB = newBorders[0]
|
|||
|
const lastB = newBorders[newBorders.length - 1]
|
|||
|
if (equal2Point(lastB.EndPoint, firstB.StartPoint) == false) {
|
|||
|
// 如果前后都是直线则求交点, 直接延长直线
|
|||
|
let hasJD = false
|
|||
|
if ((firstB instanceof Line2d) && (lastB instanceof Line2d)) {
|
|||
|
const p_jds: Point2d[] = []
|
|||
|
lastB.IntersectWith(firstB, p_jds)
|
|||
|
if (p_jds.length == 1) {
|
|||
|
lastB.EndPoint = new Point2d(p_jds[0].m_X, p_jds[0].m_Y)
|
|||
|
firstB.StartPoint = new Point2d(p_jds[0].m_X, p_jds[0].m_Y)
|
|||
|
hasJD = true
|
|||
|
}
|
|||
|
}
|
|||
|
if (hasJD == false) // 直接连接
|
|||
|
{
|
|||
|
const linkLine = new Line2d(lastB.EndPoint, firstB.StartPoint)
|
|||
|
newBorders.push(linkLine)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 2.4 生成外扩
|
|||
|
let xz = 0; let xy = block.cutWidth; let yx = 0; let ys = block.cutLength
|
|||
|
for (const cur of newBorders) {
|
|||
|
const p = cur.StartPoint
|
|||
|
if (p.m_X < xz)
|
|||
|
xz = p.m_X
|
|||
|
if (p.m_X > xy)
|
|||
|
xy = p.m_X
|
|||
|
if (p.m_Y < yx)
|
|||
|
yx = p.m_Y
|
|||
|
if (p.m_Y > ys)
|
|||
|
ys = p.m_Y
|
|||
|
}
|
|||
|
newSizeExpand.left = -xz
|
|||
|
newSizeExpand.right = xy - block.cutWidth
|
|||
|
newSizeExpand.bottom = -yx
|
|||
|
newSizeExpand.top = ys - block.cutLength
|
|||
|
newSizeExpand.setSize()
|
|||
|
|
|||
|
return { newBorders, newSizeExpand }
|
|||
|
|
|||
|
// 判断外轮廓点p1是否需要预铣
|
|||
|
function checkYX(p0, p1, p2, width, length) {
|
|||
|
if (p1.curve != 0)
|
|||
|
return false // 本身是圆弧
|
|||
|
if (p1.sealSize < 0.001)
|
|||
|
return false// 本身不封边
|
|||
|
if (p0.curve != 0)
|
|||
|
return false // 前一段是圆弧
|
|||
|
if (p2.curve != 0)
|
|||
|
return false// 后一段是圆弧
|
|||
|
// p1.p2 只要有一点在板内,就不行
|
|||
|
const isIn1 = (p1.pointX > 0.001 && p1.pointX < width - 0.001 && p1.pointY > 0.001 && p1.pointY < length - 0.001)
|
|||
|
if (isIn1)
|
|||
|
return false
|
|||
|
const isIn2 = (p2.pointX > 0.001 && p2.pointX < width - 0.001 && p2.pointY > 0.001 && p2.pointY < length - 0.001)
|
|||
|
if (isIn2)
|
|||
|
return false
|
|||
|
return true // 需要预洗
|
|||
|
}
|
|||
|
|
|||
|
// 判断边是否预铣
|
|||
|
function needPrev(line: Curve2d) {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.error("判断边是否预铣时,block.blockDetail 为空", block);
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (!(line instanceof Line2d))
|
|||
|
return false
|
|||
|
|
|||
|
if (block.isUnRegular == false) // 矩形
|
|||
|
{
|
|||
|
if (line.StartPoint.m_Y == 0 && line.EndPoint.m_Y == 0)
|
|||
|
return block.sealBottom > 0
|
|||
|
if (line.StartPoint.m_X == block.cutWidth && line.EndPoint.m_X == block.cutWidth)
|
|||
|
return block.sealRight > 0
|
|||
|
if (line.StartPoint.m_Y == block.cutLength && line.EndPoint.m_Y == block.cutLength)
|
|||
|
return block.sealTop > 0
|
|||
|
if (line.StartPoint.m_X == 0 && line.EndPoint.m_X == 0)
|
|||
|
return block.sealLeft > 0
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
const offx = block.blockDetail.offsetX
|
|||
|
const offy = block.blockDetail.offsetY
|
|||
|
|
|||
|
const x1 = line.StartPoint.m_X
|
|||
|
const y1 = line.StartPoint.m_Y
|
|||
|
const x2 = line.EndPoint.m_X
|
|||
|
const y2 = line.EndPoint.m_Y
|
|||
|
const tag0 = (x2 - x1) / getDis(x1, y1, x2, y2)
|
|||
|
|
|||
|
// 找出原始轮廓中 对应的边 , 是否有 预洗信息
|
|||
|
for (let i = 0; i < block.orgPoints.length; i++) {
|
|||
|
let j = i + 1
|
|||
|
if (j == block.orgPoints.length)
|
|||
|
j = 0
|
|||
|
if (block.orgPoints[i].isPreCutRequired == false)
|
|||
|
continue
|
|||
|
const tag1 = (block.orgPoints[j].pointX - block.orgPoints[i].pointX) / getDis(block.orgPoints[i].pointX, block.orgPoints[i].pointY, block.orgPoints[j].pointX, block.orgPoints[j].pointY)
|
|||
|
if (equal(tag0, tag1, 0.1) == false)
|
|||
|
continue // 不平行
|
|||
|
|
|||
|
const dis = getDis_PointLine(x1, y1, x2, y2, block.orgPoints[i].pointX - offx, block.orgPoints[i].pointY - offy)
|
|||
|
if (dis < block.orgPoints[i].sealSize * 2 + 3)
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
function equal2Point(p1, p2, dis = 0.001) {
|
|||
|
const x1 = p1.m_X
|
|||
|
const y1 = p1.m_Y
|
|||
|
const x2 = p2.m_X
|
|||
|
const y2 = p2.m_Y
|
|||
|
const len1 = (x1 - x2) * (x1 - x2)
|
|||
|
const len2 = (y1 - y2) * (y1 - y2)
|
|||
|
const len = Math.sqrt(len2 + len1)
|
|||
|
return len < dis
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 挖穿造型,走刀路径,板内空间 */
|
|||
|
private static analyeInners(bd: PlaceBlockDetail, cutR, cutGap = 1) {
|
|||
|
/** 挖穿轮廓 */
|
|||
|
const borders_inner_org: Curve2d[][] = []
|
|||
|
/** 挖穿轮廓 刀半径 */
|
|||
|
const borders_inner_r: number[] = []
|
|||
|
/** 挖穿走刀路径 */
|
|||
|
const borders_inner_cut: Curve2d[][] = []
|
|||
|
/** 挖穿排版轮廓 <加缝隙> */
|
|||
|
const borders_inner_place: Curve2d[][] = []
|
|||
|
/** 排版空间 */
|
|||
|
const spaces: PlaceSpace[] = []
|
|||
|
for (const m of bd.models) {
|
|||
|
if (m.depth < bd.thickness - 0.01)
|
|||
|
continue // 非挖穿
|
|||
|
if (m.isVKnifeModel())
|
|||
|
continue // 挖穿的二维刀路造型 不计算.
|
|||
|
if (m.isCutting == false)
|
|||
|
continue // 不加工
|
|||
|
|
|||
|
// 挖穿轮廓 <切割后的>,顺时针的
|
|||
|
let baseBorder
|
|||
|
if (m.hasContour()) // 有轮廓数据
|
|||
|
{
|
|||
|
let ptsArr = m.originModeling.outline.map(e => e.pts)
|
|||
|
const pts = ptsArr.map((t) => { return { x: t.x, y: t.y } })
|
|||
|
for (let i = 0; i < pts.length; i++) {
|
|||
|
pts[i].bul = m.originModeling.outline[i].buls
|
|||
|
}
|
|||
|
baseBorder = this.createBorderByPts(pts)
|
|||
|
}
|
|||
|
else // 没有轮廓数据,用走刀路径 偏移
|
|||
|
{
|
|||
|
const pts = m.pointList.map((t) => { return { x: t.pointX, y: t.pointY, bul: t.curve } })
|
|||
|
baseBorder = this.createBorderByPts(pts)
|
|||
|
baseBorder = this.offsetCurves(baseBorder, m.knifeRadius, false)
|
|||
|
}
|
|||
|
|
|||
|
// 铣刀路径
|
|||
|
const border_cut = this.offsetCurves(baseBorder, -m.realKnifeRadius, false)
|
|||
|
|
|||
|
// 排版轮廓
|
|||
|
const placeGap = Math.max(m.realKnifeRadius, cutR) * 2 - cutR + cutGap / 2 // 取造型刀,开料刀 最大的
|
|||
|
const border_place = this.offsetCurves(baseBorder, -placeGap, false)
|
|||
|
|
|||
|
borders_inner_org.push(baseBorder)
|
|||
|
borders_inner_r.push(m.realKnifeRadius)
|
|||
|
borders_inner_cut.push(border_cut)
|
|||
|
borders_inner_place.push(border_place)
|
|||
|
|
|||
|
// 内部空间
|
|||
|
let createdSpaces = false
|
|||
|
if (m.hasContour()) // 简单形状,直接生成矩形,圆形
|
|||
|
{
|
|||
|
// 是否矩形,圆形
|
|||
|
const rect = isRect(m.originModeling.outline) || isCircle(m.originModeling.outline)
|
|||
|
if (rect) {
|
|||
|
const gap = placeGap
|
|||
|
rect.x += gap
|
|||
|
rect.y += gap
|
|||
|
rect.w -= gap * 2
|
|||
|
rect.l -= gap * 2
|
|||
|
if (rect.w > 100 && rect.l > 100) {
|
|||
|
const space = new PlaceSpace(rect.x, rect.y, rect.w, rect.l)
|
|||
|
space.isBlockInnerSpace = true
|
|||
|
spaces.push(space)
|
|||
|
}
|
|||
|
createdSpaces = true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (createdSpaces == false) // 复杂形状
|
|||
|
{
|
|||
|
const tmpSpaces = SpacePlus.borderToSpace(border_place)
|
|||
|
if (tmpSpaces) {
|
|||
|
tmpSpaces.forEach(t => t.isBlockInnerSpace = true)
|
|||
|
tmpSpaces.forEach(t => spaces.push(t))
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return { borders_inner_org, borders_inner_r, borders_inner_cut, borders_inner_place, spaces }
|
|||
|
|
|||
|
function isRect(outline: any): any {
|
|||
|
const pts = outline.map(e => e.pts) //outline.pts
|
|||
|
const buls = outline.map(e => e.buls) // outline.buls
|
|||
|
|
|||
|
if (buls.length != 5)
|
|||
|
return null
|
|||
|
if (buls.some(t => t != 0))
|
|||
|
return null
|
|||
|
|
|||
|
if (pts.length != 5)
|
|||
|
return null
|
|||
|
if (pts[4].x != pts[0].x || pts[4].y != pts[0].y)
|
|||
|
return null
|
|||
|
|
|||
|
return getRect(pts[0], pts[1], pts[2], pts[3])
|
|||
|
}
|
|||
|
function isCircle(outline: any): any {
|
|||
|
// const pts = outline.pts
|
|||
|
// const buls = outline.buls
|
|||
|
const pts = outline.map(e => e.pts) //outline.pts
|
|||
|
const buls = outline.map(e => e.buls) // outline.buls
|
|||
|
|
|||
|
|
|||
|
if (buls.length != 3)
|
|||
|
return null
|
|||
|
if (equal(buls[0], 1) && equal(buls[1], 1) && equal(buls[2], 0)) {
|
|||
|
const p0 = Array.isArray(outline) ? outline[0].pts : outline?.pts[0]
|
|||
|
const p1 = Array.isArray(outline) ? outline[1].pts : outline?.pts[1]
|
|||
|
let x0 = Math.min(p0.x, p1.x)
|
|||
|
let x1 = Math.max(p0.x, p1.x)
|
|||
|
let y0 = Math.min(p0.y, p1.y)
|
|||
|
let y1 = Math.max(p0.y, p1.y)
|
|||
|
|
|||
|
let r
|
|||
|
if (equal(x0, x1)) {
|
|||
|
r = (y1 - y0) / 2
|
|||
|
x0 -= r
|
|||
|
x1 += r
|
|||
|
}
|
|||
|
else {
|
|||
|
r = (x1 - x0) / 2
|
|||
|
y0 -= r
|
|||
|
y1 += r
|
|||
|
}
|
|||
|
const t = r / Math.SQRT2
|
|||
|
const dis = r - t
|
|||
|
return { x: x0 + dis, y: y0 + dis, w: t * 2, l: t * 2 }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 缺角空间 */
|
|||
|
private static createOutSpaces(block: PlaceBlock, placeMaterial: PlaceMaterial): PlaceSpace[] {
|
|||
|
if (block.blockDetail == undefined) {
|
|||
|
console.error("创建缺角空间时,block.blockDetail 为空", block);
|
|||
|
return [];
|
|||
|
}
|
|||
|
if (block.blockDetail.borderContour == null) {
|
|||
|
console.error("创建缺角空间时,block.blockDetail.borderContour 为空", block);
|
|||
|
return [];
|
|||
|
}
|
|||
|
if (block.isUnRegular == false && (block.blockDetail.borderContour.polylines2vModel.length + block.blockDetail.borderContour.polylinesOutModel.length == 0))
|
|||
|
return [] // 矩形
|
|||
|
const pm = placeMaterial
|
|||
|
|
|||
|
let border = this.getBorder_WZYH(block, placeMaterial, false) // 获得全偏移的轮廓
|
|||
|
const pl = this.borderToPolyline(border, true)
|
|||
|
|
|||
|
/** 空间 */
|
|||
|
let spaces: PlaceSpace[] = []
|
|||
|
const reg = { z: 0, x: 0, y: 0, s: 0, w: 0, l: 0 } // 外围空间 左右上下 ,宽长
|
|||
|
reg.z = pl.BoundingBox.min.x
|
|||
|
reg.x = pl.BoundingBox.min.y
|
|||
|
reg.y = pl.BoundingBox.max.x
|
|||
|
reg.s = pl.BoundingBox.max.y
|
|||
|
reg.w = -reg.z + reg.y
|
|||
|
reg.l = -reg.x + reg.s
|
|||
|
|
|||
|
const checkSize = new SizeExpand() // 空间验证
|
|||
|
checkSize.left = -block.sizeExpand()?.left - (pm.diameter + pm.cutKnifeGap) / 2
|
|||
|
checkSize.right = block.cutWidth + block.sizeExpand()?.right + (pm.diameter + pm.cutKnifeGap) / 2
|
|||
|
checkSize.bottom = -block.sizeExpand()?.bottom - (pm.diameter + pm.cutKnifeGap) / 2
|
|||
|
checkSize.top = block.cutLength + block.sizeExpand()?.top + (pm.diameter + pm.cutKnifeGap) / 2
|
|||
|
|
|||
|
const offDis = pm.preMillingSize + 0.01 // 点判断是否在边缘 误差 一个预铣值
|
|||
|
|
|||
|
border = border.slice(0)
|
|||
|
// 确保 第一条 起点在边缘
|
|||
|
let count = 0 // 移动不能大于一个循环,避免死循环
|
|||
|
while (count < border.length) {
|
|||
|
const line0 = border[0]
|
|||
|
const isOnBorder = onBorder(line0.StartPoint)
|
|||
|
if (isOnBorder)
|
|||
|
break
|
|||
|
// 如果起点在板内,移动到最后面
|
|||
|
border.shift()
|
|||
|
border.push(line0)
|
|||
|
count++
|
|||
|
}
|
|||
|
SpacePlus.setSpaceStyle(block)
|
|||
|
let lines: Curve2d[] = [] //
|
|||
|
for (let i = 0; i < border.length; i++) {
|
|||
|
const line = border[i]
|
|||
|
const spOnBorder = onBorder(line.StartPoint)
|
|||
|
const epOnBorder = onBorder(line.EndPoint)
|
|||
|
const isxl = isXL(line)
|
|||
|
if (spOnBorder && (!epOnBorder || isxl)) // 起始线
|
|||
|
{
|
|||
|
lines = []
|
|||
|
lines.push(line)
|
|||
|
}
|
|||
|
if (!spOnBorder && !epOnBorder) // 板内线
|
|||
|
{
|
|||
|
if (lines && lines.length > 0 && lines[lines.length - 1] != line)
|
|||
|
lines.push(line)
|
|||
|
}
|
|||
|
if (epOnBorder && (!spOnBorder || isxl)) // 结束线,开始分析空间
|
|||
|
{
|
|||
|
if (lines && lines.length > 0) {
|
|||
|
if (lines[lines.length - 1] != line)
|
|||
|
lines.push(line)
|
|||
|
const newspaces = createSpace(lines)
|
|||
|
if (newspaces && newspaces.length > 0)
|
|||
|
spaces = spaces.concat(newspaces)
|
|||
|
lines = []
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
const newSpaces: PlaceSpace[] = []
|
|||
|
// 空间验证
|
|||
|
for (const space of spaces) {
|
|||
|
let x1 = space.x
|
|||
|
let y1 = space.y
|
|||
|
let x2 = space.topX()
|
|||
|
let y2 = space.topY()
|
|||
|
|
|||
|
if (x1 < checkSize.left)
|
|||
|
x1 = checkSize.left
|
|||
|
if (y1 < checkSize.bottom)
|
|||
|
y1 = checkSize.bottom
|
|||
|
if (x2 > checkSize.right)
|
|||
|
x2 = checkSize.right
|
|||
|
if (y2 > checkSize.top)
|
|||
|
y2 = checkSize.top
|
|||
|
|
|||
|
const newspace = PlaceSpace.create(x1, y1, x2, y2)
|
|||
|
newSpaces.push(newspace)
|
|||
|
}
|
|||
|
|
|||
|
return newSpaces
|
|||
|
|
|||
|
/** 缺角的开始? 起点在边缘,终点在板内的 或 斜线 (终点在另外一边) */
|
|||
|
function isBegin(curve: Curve2d) { return onBorder(curve.StartPoint) && (!onBorder(curve.EndPoint) || isXL(curve)) }
|
|||
|
/** 缺角的结束? 终点在边缘的 起点在板内 或 (起点点在另外一边) */
|
|||
|
function isEnd(curve: Curve2d) { return onBorder(curve.EndPoint) && (!onBorder(curve.StartPoint) || isXL(curve)) }
|
|||
|
/** 在板内 */
|
|||
|
function inBorder(curve: Curve2d) { return !onBorder(curve.StartPoint) && !onBorder(curve.EndPoint) }
|
|||
|
|
|||
|
/** 点是否在边缘 */
|
|||
|
function onBorder(p: Point2d) { return equal(p.m_X, reg.z, offDis) || equal(p.m_X, reg.y, offDis) || equal(p.m_Y, reg.s, offDis) || equal(p.m_Y, reg.x, offDis) }
|
|||
|
/** 斜线 */
|
|||
|
function isXL(line: Curve2d) { return !equal(line.StartPoint.m_X, line.EndPoint.m_X) && !equal(line.StartPoint.m_Y, line.EndPoint.m_Y) }
|
|||
|
/** 线是边缘 */
|
|||
|
function isBorderLine(line: Line2d) { return !isXL(line) && onBorder(line.StartPoint) && onBorder(line.EndPoint) }
|
|||
|
/** 分析空间 */
|
|||
|
function createSpace(curves: Curve2d[]): PlaceSpace[] {
|
|||
|
if (curves.length == 0)
|
|||
|
return []
|
|||
|
|
|||
|
// 1.补边,闭合轮廓
|
|||
|
const sp = curves[0].StartPoint
|
|||
|
const ep = curves[curves.length - 1].EndPoint
|
|||
|
const pushPts: Point2d[] = []
|
|||
|
pushPts.push(ep)
|
|||
|
const sb = getEdge(sp) // 起点的边
|
|||
|
const eb = getEdge(ep) // 终点的边
|
|||
|
if (sb == -1 || eb == -1)
|
|||
|
return []// 不在边上
|
|||
|
// 在同一边 的缺角
|
|||
|
if (sb == eb) {
|
|||
|
if (equal(sp.m_X, ep.m_X, offDis) && sp.m_X != ep.m_X) // 消除误差
|
|||
|
{
|
|||
|
let x = Math.max(sp.m_X, ep.m_X)
|
|||
|
if (sp.m_X > block.width / 2)
|
|||
|
x = Math.min(sp.m_X, ep.m_X)
|
|||
|
sp.m_X = x
|
|||
|
ep.m_X = x
|
|||
|
}
|
|||
|
if (equal(sp.m_Y, ep.m_Y, offDis) && sp.m_Y != ep.m_Y) // 消除误差
|
|||
|
{
|
|||
|
let y = Math.max(sp.m_Y, ep.m_Y)
|
|||
|
if (sp.m_Y > block.length / 2)
|
|||
|
y = Math.min(sp.m_Y, ep.m_Y)
|
|||
|
sp.m_Y = y
|
|||
|
ep.m_Y = y
|
|||
|
}
|
|||
|
}
|
|||
|
// 右下角
|
|||
|
else if (sb == 0 && eb == 1) {
|
|||
|
const cp = new Point2d(ep.m_X, sp.m_Y)
|
|||
|
pushPts.push(cp)
|
|||
|
}
|
|||
|
// 右上角
|
|||
|
else if (sb == 1 && eb == 2) {
|
|||
|
const cp = new Point2d(sp.m_X, ep.m_Y)
|
|||
|
pushPts.push(cp)
|
|||
|
}
|
|||
|
// 左上角
|
|||
|
else if (sb == 2 && eb == 3) {
|
|||
|
const cp = new Point2d(ep.m_X, sp.m_Y)
|
|||
|
pushPts.push(cp)
|
|||
|
}
|
|||
|
// 左下角
|
|||
|
else if (sb == 3 && eb == 0) {
|
|||
|
const cp = new Point2d(sp.m_X, ep.m_Y)
|
|||
|
pushPts.push(cp)
|
|||
|
}
|
|||
|
// 起点下边 -> 终点上边 //因为倒角
|
|||
|
else if (sb == 0 && eb == 2) {
|
|||
|
const cp1 = new Point2d(reg.y, ep.m_Y)
|
|||
|
const cp2 = new Point2d(reg.y, sp.m_Y)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
}
|
|||
|
// 起点右边 -> 终点左边
|
|||
|
else if (sb == 1 && eb == 3) {
|
|||
|
const cp1 = new Point2d(ep.m_X, reg.s)
|
|||
|
const cp2 = new Point2d(sp.m_X, reg.s)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
}
|
|||
|
// 起点上边 -> 终点下边
|
|||
|
else if (sb == 2 && eb == 0) {
|
|||
|
const cp1 = new Point2d(reg.z, ep.m_Y)
|
|||
|
const cp2 = new Point2d(reg.z, sp.m_Y)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
}
|
|||
|
// 起点左边 -> 终点右边
|
|||
|
else if (sb == 3 && eb == 1) {
|
|||
|
const cp1 = new Point2d(ep.m_X, reg.x)
|
|||
|
const cp2 = new Point2d(sp.m_X, reg.x)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
}
|
|||
|
// 起点下边 -> 终点左边
|
|||
|
else if (sb == 0 && eb == 3) {
|
|||
|
const cp1 = new Point2d(reg.z, reg.s)
|
|||
|
const cp2 = new Point2d(reg.y, reg.s)
|
|||
|
const cp3 = new Point2d(reg.y, reg.x)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
pushPts.push(cp3)
|
|||
|
}
|
|||
|
// 起点右边 -> 终点下边
|
|||
|
else if (sb == 1 && eb == 0) {
|
|||
|
const cp1 = new Point2d(reg.z, reg.x)
|
|||
|
const cp2 = new Point2d(reg.z, reg.s)
|
|||
|
const cp3 = new Point2d(reg.y, reg.s)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
pushPts.push(cp3)
|
|||
|
}
|
|||
|
// 起点上 -> 终点右边
|
|||
|
else if (sb == 2 && eb == 1) {
|
|||
|
const cp1 = new Point2d(reg.y, reg.x)
|
|||
|
const cp2 = new Point2d(reg.z, reg.x)
|
|||
|
const cp3 = new Point2d(reg.z, reg.s)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
pushPts.push(cp3)
|
|||
|
}
|
|||
|
// 起点左 -> 终点上边
|
|||
|
else if (sb == 3 && eb == 2) {
|
|||
|
const cp1 = new Point2d(reg.y, reg.s)
|
|||
|
const cp2 = new Point2d(reg.y, reg.x)
|
|||
|
const cp3 = new Point2d(reg.z, reg.x)
|
|||
|
pushPts.push(cp1)
|
|||
|
pushPts.push(cp2)
|
|||
|
pushPts.push(cp3)
|
|||
|
}
|
|||
|
else // 判断不了 缺口 的起点终点 范围
|
|||
|
{
|
|||
|
return []
|
|||
|
}
|
|||
|
pushPts.push(sp)
|
|||
|
for (let i = 0; i < pushPts.length - 1; i++) // 闭合缺口
|
|||
|
{
|
|||
|
const newLine = new Line2d(pushPts[i], pushPts[i + 1])
|
|||
|
curves.push(newLine)
|
|||
|
}
|
|||
|
|
|||
|
// 3 目前轮廓顺时针,必须转成 逆时针
|
|||
|
curves = SpacePlus.reverseCurves(curves)
|
|||
|
|
|||
|
// 4. 分析空间 analyeSpace
|
|||
|
const tmpSpaces = SpacePlus.borderToSpace(curves) || []
|
|||
|
|
|||
|
return tmpSpaces
|
|||
|
}
|
|||
|
|
|||
|
/** 获得点所在的边 getB */
|
|||
|
function getEdge(sp) {
|
|||
|
if (equal(sp.m_Y, reg.x, offDis))
|
|||
|
return 0
|
|||
|
if (equal(sp.m_X, reg.y, offDis))
|
|||
|
return 1
|
|||
|
if (equal(sp.m_Y, reg.s, offDis))
|
|||
|
return 2
|
|||
|
if (equal(sp.m_X, reg.z, offDis))
|
|||
|
return 3
|
|||
|
return -1
|
|||
|
}
|
|||
|
|
|||
|
/** 设置方向 */
|
|||
|
function setDirect(line: Line2d) {
|
|||
|
let fx = -1 // 向右 0,向上 1,向左 2,向下 3 ,右上 4,左上5,左下6,右下 7
|
|||
|
if (line.EndPoint.m_X > line.StartPoint.m_X && equal(line.EndPoint.m_Y, line.StartPoint.m_Y)) {
|
|||
|
fx = 0
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_X < line.StartPoint.m_X && equal(line.EndPoint.m_Y, line.StartPoint.m_Y)) {
|
|||
|
fx = 2
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_Y > line.StartPoint.m_Y && equal(line.EndPoint.m_X, line.StartPoint.m_X)) {
|
|||
|
fx = 1
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_Y < line.StartPoint.m_Y && equal(line.EndPoint.m_X, line.StartPoint.m_X)) {
|
|||
|
fx = 3
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_X > line.StartPoint.m_X && line.EndPoint.m_Y > line.StartPoint.m_Y) {
|
|||
|
fx = 4
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_X < line.StartPoint.m_X && line.EndPoint.m_Y > line.StartPoint.m_Y) {
|
|||
|
fx = 5
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_X < line.StartPoint.m_X && line.EndPoint.m_Y < line.StartPoint.m_Y) {
|
|||
|
fx = 6
|
|||
|
}
|
|||
|
else if (line.EndPoint.m_X > line.StartPoint.m_X && line.EndPoint.m_Y < line.StartPoint.m_Y) {
|
|||
|
fx = 7
|
|||
|
}
|
|||
|
line.fx = fx
|
|||
|
return fx > -1
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 普通造型外扩的 多段线 */
|
|||
|
public static createPolyline_model(block: PlaceBlock) {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.warn("PlaceBlock没有blockDetail,无法创建造型轮廓")
|
|||
|
return { pls_model: [], sizeout: new SizeExpand() }
|
|||
|
}
|
|||
|
const pl_block = this.getOrgPolyline(block)
|
|||
|
const pls_model: Polyline[] = []
|
|||
|
for (const model of block.blockDetail.models) {
|
|||
|
if (model.originModeling == undefined) {
|
|||
|
continue
|
|||
|
}
|
|||
|
let _pts: any[] = []
|
|||
|
let _buls: any[] = []
|
|||
|
if (Array.isArray(model.originModeling.outline)) {
|
|||
|
_pts = model.originModeling.outline.map(e => e.pts)
|
|||
|
_buls = model.originModeling.outline.map(e => e.buls)
|
|||
|
} else {
|
|||
|
_pts = model.originModeling.outline.pts
|
|||
|
_buls = model.originModeling.outline.buls
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (model.isCutting == false)
|
|||
|
continue
|
|||
|
if (model.isVKnifeModel())
|
|||
|
continue
|
|||
|
if (model.depth > block.thickness - 0.01)
|
|||
|
continue
|
|||
|
if (model.pointList.length < 2)
|
|||
|
continue
|
|||
|
if (model.hasContour() == false)
|
|||
|
continue
|
|||
|
if (model.originModeling == null)
|
|||
|
continue
|
|||
|
if (model.originModeling.outline == null)
|
|||
|
continue
|
|||
|
if (!Array.isArray(_pts))
|
|||
|
continue
|
|||
|
if (_pts.length < 1)
|
|||
|
continue
|
|||
|
if (model.knifeRadius < 0.001)
|
|||
|
continue
|
|||
|
const pl_model = PolylineHelper.createByPts(_pts, _buls, true)
|
|||
|
const pl_off = pl_model.GetOffsetCurves(model.knifeRadius)[0]
|
|||
|
if (pl_off == null)
|
|||
|
continue
|
|||
|
if (pl_block.IntersectWith(pl_off, 0).length == 0)
|
|||
|
continue // 造型轮廓偏移一个刀半径 ,没有与板轮廓相交
|
|||
|
|
|||
|
// 有可能超出板外
|
|||
|
const pts: any[] = []
|
|||
|
const p0 = model.pointList[0]
|
|||
|
let isClose = false
|
|||
|
for (let i = 0; i < model.pointList.length; i++) {
|
|||
|
const p = model.pointList[i]
|
|||
|
|
|||
|
if (i == 0) {
|
|||
|
pts.push({ x: p.pointX, y: p.pointY, bul: p.curve })
|
|||
|
continue
|
|||
|
}
|
|||
|
const pp = pts[pts.length - 1]
|
|||
|
if (getDis2(pp, p) < 0.1)
|
|||
|
pts.pop() // 与前一点,接近去掉前一点,避免重合
|
|||
|
pts.push({ x: p.pointX, y: p.pointY, bul: p.curve })
|
|||
|
if (i == model.pointList.length - 1)
|
|||
|
break // 完成了
|
|||
|
isClose = getDis2(p0, p) < 0.1
|
|||
|
if (isClose) // 闭环且后面的点都在环内,那后面的点就不需要考虑了
|
|||
|
{
|
|||
|
const pl = PolylineHelper.create(pts, true)
|
|||
|
let isAllIn = true
|
|||
|
for (let j = i + 1; j < model.pointList.length; j++) {
|
|||
|
const pn = model.pointList[j]
|
|||
|
isAllIn = pl.PtInCurve(new Vector3(pn.pointX, pn.pointY, 0))
|
|||
|
if (isAllIn == false)
|
|||
|
break
|
|||
|
}
|
|||
|
if (isAllIn)
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
this.createModelPLS(pl_block, pls_model, pts, model.knifeRadius)
|
|||
|
}
|
|||
|
catch {
|
|||
|
continue
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 计算外扩偏移
|
|||
|
let xz = 0; let xy = block.cutWidth; let yx = 0; let ys = block.cutLength
|
|||
|
for (const pl of pls_model) {
|
|||
|
if (pl.BoundingBox.min.x < xz)
|
|||
|
xz = pl.BoundingBox.min.x
|
|||
|
if (pl.BoundingBox.min.y < yx)
|
|||
|
yx = pl.BoundingBox.min.y
|
|||
|
if (pl.BoundingBox.max.x > xy)
|
|||
|
xy = pl.BoundingBox.max.x
|
|||
|
if (pl.BoundingBox.max.y > ys)
|
|||
|
ys = pl.BoundingBox.max.y
|
|||
|
}
|
|||
|
|
|||
|
const sizeout_model = new SizeExpand()
|
|||
|
if (xz < 0)
|
|||
|
sizeout_model.left = -xz
|
|||
|
if (xy > block.cutWidth)
|
|||
|
sizeout_model.right = xy - block.cutWidth
|
|||
|
if (yx < 0)
|
|||
|
sizeout_model.bottom = -yx
|
|||
|
if (ys > block.cutLength)
|
|||
|
sizeout_model.top = ys - block.cutLength
|
|||
|
sizeout_model.setSize()
|
|||
|
|
|||
|
return { pls_model, sizeout: sizeout_model }
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 2v板外下刀的 多段线 */
|
|||
|
private static createPolyline_2vModel(block: PlaceBlock) {
|
|||
|
if (!block.blockDetail) {
|
|||
|
console.warn("PlaceBlock没有blockDetail,无法创建造型轮廓")
|
|||
|
return { pls_model: [], sizeout: new SizeExpand() }
|
|||
|
}
|
|||
|
const pls_2v: Polyline[] = []
|
|||
|
for (const model of block.blockDetail.models) {
|
|||
|
|
|||
|
if (model.isVKnifeModel() == false)
|
|||
|
continue
|
|||
|
if (model.isCutting == false)
|
|||
|
continue
|
|||
|
// if(model.depth > block.thickness - 0.01) continue;
|
|||
|
const pl_block = this.getOrgPolyline(block)
|
|||
|
for (const vline of model.VLines) { // knifeRadius 刀半径, depth深度, points{x,y,z,bul,r}
|
|||
|
const r = vline.knifeRadius
|
|||
|
if (r < 0.001)
|
|||
|
continue
|
|||
|
const pts = vline.points.map((t) => { return { x: t.x, y: t.y, bul: t.bul } })
|
|||
|
try {
|
|||
|
this.createModelPLS(pl_block, pls_2v, pts, r, true)
|
|||
|
}
|
|||
|
catch {
|
|||
|
continue
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 计算外扩偏移
|
|||
|
let xz = 0; let xy = block.cutWidth; let yx = 0; let ys = block.cutLength
|
|||
|
for (const pl of pls_2v) {
|
|||
|
if (pl.BoundingBox.min.x < xz)
|
|||
|
xz = pl.BoundingBox.min.x
|
|||
|
if (pl.BoundingBox.min.y < yx)
|
|||
|
yx = pl.BoundingBox.min.y
|
|||
|
if (pl.BoundingBox.max.x > xy)
|
|||
|
xy = pl.BoundingBox.max.x
|
|||
|
if (pl.BoundingBox.max.y > ys)
|
|||
|
ys = pl.BoundingBox.max.y
|
|||
|
}
|
|||
|
|
|||
|
const sizeout_2v = new SizeExpand()
|
|||
|
if (xz < 0)
|
|||
|
sizeout_2v.left = -xz
|
|||
|
if (xy > block.cutWidth)
|
|||
|
sizeout_2v.right = xy - block.cutWidth
|
|||
|
if (yx < 0)
|
|||
|
sizeout_2v.bottom = -yx
|
|||
|
if (ys > block.cutLength)
|
|||
|
sizeout_2v.top = ys - block.cutLength
|
|||
|
sizeout_2v.setSize()
|
|||
|
|
|||
|
return { pls_2v, sizeout_2v }
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 创建超出板外的造型轮廓
|
|||
|
*
|
|||
|
*/
|
|||
|
private static createModelPLS(pl_block: Polyline, pls_model: Polyline[], points: any[], r: number, is2V = false) {
|
|||
|
const lines: any = []
|
|||
|
|
|||
|
// 23.10.9 发现普通造型还是有自交的线段,强制 分段处理
|
|||
|
for (let i = 0; i < points.length - 1; i++) {
|
|||
|
const j = i + 1
|
|||
|
const p1 = { x: points[i].x, y: points[i].y, bul: points[i].bul }
|
|||
|
const p2 = { x: points[j].x, y: points[j].y, bul: 0 }
|
|||
|
lines.push([p1, p2])
|
|||
|
}
|
|||
|
// 对 每段line 进行 偏移多半径,获取闭合多段线
|
|||
|
const pls: Polyline[] = []
|
|||
|
for (const pts of lines) {
|
|||
|
// 1. pts 不闭合,偏移0.5
|
|||
|
// 原路回来,组合成闭合线
|
|||
|
const l = pts.length - 1
|
|||
|
pts[l].bul = 0 // 确保最后一点 是直线点
|
|||
|
const isclose = equal(pts[0].x, pts[l].x) && equal(pts[0].y, pts[l].y)
|
|||
|
if (isclose == false) //
|
|||
|
{
|
|||
|
const pl_0 = PolylineHelper.create(pts, false)
|
|||
|
const pl_1s = pl_0.GetOffsetCurves(0.5)
|
|||
|
let pl_1 = pl_1s[0]
|
|||
|
if (pl_1 == null)
|
|||
|
continue
|
|||
|
pl_1 = pl_1.Reverse()
|
|||
|
for (const p of pl_1.LineData) {
|
|||
|
pts.push({ x: p.pt.x, y: p.pt.y, bul: p.bul })
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 2 偏移刀r后的 轮廓
|
|||
|
let pl_vline = PolylineHelper.create(pts, true)
|
|||
|
if (pl_vline.IsClockWise)
|
|||
|
pl_vline = pl_vline.Reverse()
|
|||
|
const pl_off = pl_vline.GetOffsetCurves(r)[0]
|
|||
|
if (pl_off == null)
|
|||
|
continue
|
|||
|
// if(pl_off.CloseMark == false) ;
|
|||
|
pls.push(pl_off)
|
|||
|
}
|
|||
|
|
|||
|
if (pls.length == 0)
|
|||
|
return
|
|||
|
// 对 多段线进行 合并,获得最后 造型轮廓
|
|||
|
let pl: Polyline | undefined = pls.shift()
|
|||
|
if (pl == undefined || pl == null) {
|
|||
|
console.warn("创建造型轮廓失败,pls数组为空")
|
|||
|
return
|
|||
|
}
|
|||
|
if (pls.length > 0) {
|
|||
|
pl = this.unionPolylines(pl, pls)
|
|||
|
}
|
|||
|
|
|||
|
// 3 造型轮廓 与 板轮廓干涉
|
|||
|
if (pl_block.IntersectWith(pl, 0).length > 0) {
|
|||
|
pls_model.push(pl)
|
|||
|
}
|
|||
|
|
|||
|
// 4 2V 轮廓 可能包含了 板轮廓
|
|||
|
if (pl.BoundingBox.min.x <= pl_block.BoundingBox.min.x
|
|||
|
&& pl.BoundingBox.min.y <= pl_block.BoundingBox.min.y
|
|||
|
&& pl.BoundingBox.max.x >= pl_block.BoundingBox.max.x
|
|||
|
&& pl.BoundingBox.max.y >= pl_block.BoundingBox.max.y) {
|
|||
|
pls_model.push(pl)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 点阵pts ,在 板边缘 干涉到的 区域 */
|
|||
|
private static createInterPLS(pl_block: Polyline, pts: any[], r: number, pls_model: Polyline[]) {
|
|||
|
const pl_vline = PolylineHelper.create(pts)
|
|||
|
let curves
|
|||
|
curves = pl_vline.Explode() // 分解成 一段 一段的
|
|||
|
|
|||
|
const outlines: any = [] // 当前在板外的线段
|
|||
|
for (let i = 0; i < curves.length;) // 判断 有没有交集
|
|||
|
{
|
|||
|
const curve = curves[i]
|
|||
|
const pos = getRelation(pl_block, curve, r)
|
|||
|
|
|||
|
if (pos[0] == -1) {
|
|||
|
if (outlines.length > 0)
|
|||
|
createPL_outLines(outlines, pls_model, r)
|
|||
|
}
|
|||
|
else if (pos[0] == 0 || pos[0] == 1) // 板外,或交接
|
|||
|
{
|
|||
|
outlines.push(curve)
|
|||
|
}
|
|||
|
else // 多个连接点 。,要拆分 多段,处理
|
|||
|
{
|
|||
|
const childs = curve.GetSplitCurves(0.2)
|
|||
|
curves.splice(i, 1)
|
|||
|
for (let j = childs.length - 1; j >= 0; j--) {
|
|||
|
const child = childs[j]
|
|||
|
curves.splice(i, 0, child)
|
|||
|
}
|
|||
|
continue
|
|||
|
}
|
|||
|
i++
|
|||
|
}
|
|||
|
|
|||
|
// 最后一条线段可能是板外,那就要补 板外线段生成
|
|||
|
if (outlines.length > 0)
|
|||
|
createPL_outLines(outlines, pls_model, r)
|
|||
|
|
|||
|
/** 判断 line 与 polyline 的关系 -1 板内,0 板外 ,> 0 相交点数 */
|
|||
|
function getRelation(pl_block, curve, r) {
|
|||
|
const xjd = pl_block.IntersectWith(curve, 0)
|
|||
|
if (xjd.length > 0)
|
|||
|
return [xjd.length, xjd] // 相交点
|
|||
|
|
|||
|
// line 的 4 个点
|
|||
|
const box = curve.BoundingBox
|
|||
|
const x0 = box.min.x - r
|
|||
|
const y0 = box.min.y - r
|
|||
|
const x1 = box.max.x + r
|
|||
|
const y1 = box.max.y + r
|
|||
|
|
|||
|
const p0 = pl_block.PtInCurve(new Vector3(x0, y0))
|
|||
|
const p1 = pl_block.PtInCurve(new Vector3(x1, y0))
|
|||
|
const p2 = pl_block.PtInCurve(new Vector3(x1, y1))
|
|||
|
const p3 = pl_block.PtInCurve(new Vector3(x0, y1))
|
|||
|
|
|||
|
if (p0 && p1 && p2 && p3)
|
|||
|
return [-1, []] // 板内
|
|||
|
|
|||
|
if (!p0 && !p1 && !p2 && !p3)
|
|||
|
return [0, []] // 板外
|
|||
|
return [0, []]
|
|||
|
}
|
|||
|
|
|||
|
function createPL(x0, y0, x1, y1) {
|
|||
|
const pts: any[] = []
|
|||
|
pts.push({ x: x0, y: y0 })
|
|||
|
pts.push({ x: x1, y: y0 })
|
|||
|
pts.push({ x: x1, y: y1 })
|
|||
|
pts.push({ x: x0, y: y1 })
|
|||
|
const pl_line = PolylineHelper.create(pts, true)
|
|||
|
return pl_line
|
|||
|
}
|
|||
|
|
|||
|
function createPL_outLines(outlines, pls_model, r) {
|
|||
|
let xz = 28000; let xy = -100000; let yx = 2900000; let ys = -100000
|
|||
|
for (const curve of outlines) {
|
|||
|
const box = curve.BoundingBox
|
|||
|
const x0 = box.min.x - r - 1
|
|||
|
const y0 = box.min.y - r - 1
|
|||
|
const x1 = box.max.x + r + 1
|
|||
|
const y1 = box.max.y + r + 1
|
|||
|
if (x0 < xz)
|
|||
|
xz = x0
|
|||
|
if (x1 > xy)
|
|||
|
xy = x1
|
|||
|
if (y0 < yx)
|
|||
|
yx = y0
|
|||
|
if (y1 > ys)
|
|||
|
ys = y1
|
|||
|
}
|
|||
|
const pl_line = createPL(xz, yx, xy, ys)
|
|||
|
pls_model.push(pl_line)
|
|||
|
outlines.splice(0) // 清空,可能下面 还有 板外的线段
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 创建 轮廓 pts : {x,y,bul}[] */
|
|||
|
static createBorderByPts(pts: any[]): Curve2d[] {
|
|||
|
const borders: Curve2d[] = []
|
|||
|
for (let i = 0; i < pts.length; i++) {
|
|||
|
let j = i + 1
|
|||
|
if (j == pts.length)
|
|||
|
j = 0
|
|||
|
const pi = pts[i]
|
|||
|
const pj = pts[j]
|
|||
|
if (pi.bul == 0) {
|
|||
|
const line = new Line2d(new Point2d(pi.x, pi.y), new Point2d(pj.x, pj.y))
|
|||
|
borders.push(line)
|
|||
|
}
|
|||
|
else {
|
|||
|
const arc = new Arc2d(new Point2d(pi.x, pi.y), new Point2d(pj.x, pj.y), pi.bul)
|
|||
|
borders.push(arc)
|
|||
|
}
|
|||
|
}
|
|||
|
return borders
|
|||
|
}
|
|||
|
|
|||
|
/** 翻转 多线段 */
|
|||
|
static transformBorder(borders: Curve2d[], placeStyle: PlaceStyle, width: number, length: number, blockNo?: any): Curve2d[] {
|
|||
|
// console.log('翻转 多线段')
|
|||
|
const newBorders: Curve2d[] = []
|
|||
|
for (let i = 0; i < borders.length; i++) {
|
|||
|
const border = borders[i]
|
|||
|
const np1 = getPlacePosition(border.StartPoint.m_X, border.StartPoint.m_Y, width, length, placeStyle)
|
|||
|
const np2 = getPlacePosition(border.EndPoint.m_X, border.EndPoint.m_Y, width, length, placeStyle)
|
|||
|
let p1 = new Point2d(np1.x, np1.y)
|
|||
|
let p2 = new Point2d(np2.x, np2.y)
|
|||
|
if (placeStyle >= 4)
|
|||
|
[p1, p2] = [p2, p1]
|
|||
|
let newBorder
|
|||
|
if (border instanceof Arc2d) {
|
|||
|
newBorder = new Arc2d(p1, p2, border.Bul)
|
|||
|
}
|
|||
|
else {
|
|||
|
newBorder = new Line2d(p1, p2)
|
|||
|
}
|
|||
|
if (border.tagData != undefined || border.tagData != null) {
|
|||
|
newBorder.tagData = border.tagData
|
|||
|
newBorder.tagData2 = border.tagData2
|
|||
|
}
|
|||
|
newBorders.push(newBorder)
|
|||
|
}
|
|||
|
if (placeStyle >= 4)
|
|||
|
newBorders.reverse()
|
|||
|
return newBorders
|
|||
|
}
|
|||
|
|
|||
|
/** 翻转 多线段 */
|
|||
|
static transformBorderNew(borders: Curve2d[], placeStyle: PlaceStyle, width: number, length: number): Curve2d[] {
|
|||
|
|
|||
|
const newBorders: Curve2d[] = []
|
|||
|
for (let i = 0; i < borders.length; i++) {
|
|||
|
const border = borders[i]
|
|||
|
const np1 = getPlacePosition(border.StartPoint.m_X, border.StartPoint.m_Y, width, length, placeStyle)
|
|||
|
const np2 = getPlacePosition(border.EndPoint.m_X, border.EndPoint.m_Y, width, length, placeStyle)
|
|||
|
let p1 = new Point2d(np1.x, np1.y)
|
|||
|
let p2 = new Point2d(np2.x, np2.y)
|
|||
|
if (placeStyle >= 4)
|
|||
|
[p1, p2] = [p2, p1]
|
|||
|
let newBorder
|
|||
|
if (border instanceof Arc2d) {
|
|||
|
newBorder = new Arc2d(p1, p2, border.Bul)
|
|||
|
}
|
|||
|
else {
|
|||
|
newBorder = new Line2d(p1, p2)
|
|||
|
}
|
|||
|
if (border.tagData != undefined || border.tagData != null) {
|
|||
|
newBorder.tagData = border.tagData
|
|||
|
newBorder.tagData2 = border.tagData2
|
|||
|
}
|
|||
|
newBorders.push(newBorder)
|
|||
|
}
|
|||
|
if (placeStyle >= 4)
|
|||
|
newBorders.reverse()
|
|||
|
|
|||
|
return newBorders
|
|||
|
}
|
|||
|
|
|||
|
/** 翻转 多段线 */
|
|||
|
static transformPolyline(pl: Polyline, placeStyle: PlaceStyle, width: number, length: number): Polyline {
|
|||
|
const bx = pl.Position.x
|
|||
|
const by = pl.Position.y
|
|||
|
let pts = pl.LineData.map((t) => { return { x: t.pt.x, y: t.pt.y, bul: t.bul } })
|
|||
|
pts.forEach((t) => { t.x += bx; t.y += by })
|
|||
|
|
|||
|
// 翻面,翻转点阵
|
|||
|
if (placeStyle > 3) {
|
|||
|
const newPts: any[] = []
|
|||
|
for (let j = pts.length - 1; j >= 0; j--) {
|
|||
|
let i = j - 1
|
|||
|
if (i < 0)
|
|||
|
i = pts.length - 1
|
|||
|
const x = pts[j].x
|
|||
|
const y = pts[j].y
|
|||
|
const bul = pts[i].bul
|
|||
|
newPts.push({ x, y, bul })
|
|||
|
}
|
|||
|
pts = newPts
|
|||
|
}
|
|||
|
|
|||
|
// 转换坐标
|
|||
|
for (let i = 0; i < pts.length; i++) {
|
|||
|
const p = pts[i]
|
|||
|
const np = getPlacePosition(p.x, p.y, width, length, placeStyle)
|
|||
|
p.x = np.x
|
|||
|
p.y = np.y
|
|||
|
}
|
|||
|
|
|||
|
const npl = PolylineHelper.create(pts)
|
|||
|
npl.CloseMark = true
|
|||
|
return npl
|
|||
|
}
|
|||
|
|
|||
|
/** 偏移 多段线 */
|
|||
|
static offsetCurves(borders: Curve2d[], offvalue: number, isOffsetRounding: boolean): Curve2d[] {
|
|||
|
if (equal(offvalue, 0))
|
|||
|
return borders
|
|||
|
const pts: any[] = []
|
|||
|
for (const cur of borders) {
|
|||
|
const x = cur.StartPoint.m_X
|
|||
|
const y = cur.StartPoint.m_Y
|
|||
|
const bul = (cur instanceof Arc2d) ? cur.Bul : 0
|
|||
|
pts.push({ x, y, bul })
|
|||
|
}
|
|||
|
if (borders.length != 0) {
|
|||
|
pts.push({ x: borders[0].StartPoint.m_X, y: borders[0].StartPoint.m_Y, bul: 0 })
|
|||
|
}
|
|||
|
|
|||
|
const pl = PolylineHelper.create(pts)
|
|||
|
// 偏移 倒角:直角不倒角 2023.10.27 QQ陈雄
|
|||
|
const pls = isOffsetRounding ? pl.GetFeedingToolPath(offvalue, 0) : pl.GetOffsetCurves(offvalue)
|
|||
|
if (pls.length == 0)
|
|||
|
return borders
|
|||
|
const npls = pls[0] // 偏移多段线
|
|||
|
const ita = ConverToPolylineAndSplitArc(npls, false, true) // 拆分多段线
|
|||
|
|
|||
|
const offsetCurves: Curve2d[] = []
|
|||
|
for (let i = 0; i < ita.pts.length; i++) {
|
|||
|
let j = i + 1
|
|||
|
if (j == ita.pts.length)
|
|||
|
j = 0
|
|||
|
const p1 = ita.pts[i]
|
|||
|
const p2 = ita.pts[j]
|
|||
|
const np1 = new Point2d(p1.x, p1.y)
|
|||
|
const np2 = new Point2d(p2.x, p2.y)
|
|||
|
|
|||
|
if (ita.buls[i] == 0) {
|
|||
|
const line = new Line2d(np1, np2)
|
|||
|
if (line.m_Length < 0.01)
|
|||
|
continue
|
|||
|
offsetCurves.push(line)
|
|||
|
}
|
|||
|
else {
|
|||
|
const arc = new Arc2d(np1, np2, ita.buls[i])
|
|||
|
if (arc.m_Radius < 0.01)
|
|||
|
continue
|
|||
|
offsetCurves.push(arc)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return offsetCurves
|
|||
|
}
|
|||
|
|
|||
|
/** 轮廓 转成 多断线 */
|
|||
|
static borderToPolyline(border: Curve2d[], CloseMark = true): Polyline {
|
|||
|
return PolylineHelper.createByCurve2d(border, CloseMark)
|
|||
|
}
|
|||
|
|
|||
|
/** 多段线 转成 轮廓 */
|
|||
|
static polylineToBorder(pl: Polyline): Curve2d[] {
|
|||
|
const pts = pl.LineData.map((t) => { return { x: t.pt.x, y: t.pt.y, bul: t.bul } })
|
|||
|
return this.createBorderByPts(pts)
|
|||
|
}
|
|||
|
|
|||
|
/** 合并 多段线 */
|
|||
|
static unionPolylines(pl: Polyline, childs: Polyline[]): Polyline {
|
|||
|
const strPLS = PolylineHelper.getStrPLs([pl].concat(childs))
|
|||
|
|
|||
|
if (childs.length == 0)
|
|||
|
return pl
|
|||
|
|
|||
|
try {
|
|||
|
const contour1 = Contour.CreateContour(pl)
|
|||
|
|
|||
|
const reg1 = new ShapeManager([new Shape(contour1)])
|
|||
|
for (const c of childs) {
|
|||
|
const contour2 = Contour.CreateContour(c, false)
|
|||
|
if (contour2 == null) {
|
|||
|
return pl
|
|||
|
} else {
|
|||
|
PolylineHelper.getArcRadius
|
|||
|
const reg2 = new ShapeManager([new Shape(contour2)])
|
|||
|
reg1.UnionBoolOperation(reg2)
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (reg1.ShapeList.length == 0)
|
|||
|
return pl
|
|||
|
|
|||
|
let newStr = ''
|
|||
|
const pls: Array<Polyline | Circle> = []
|
|||
|
for (const sh of reg1.ShapeList) {
|
|||
|
pls.push(sh.Outline.Curve)
|
|||
|
}
|
|||
|
newStr = PolylineHelper.getStrPLs(pls)
|
|||
|
|
|||
|
const cur = reg1.ShapeList[0].Outline.Curve
|
|||
|
let newpl: Polyline
|
|||
|
if (cur instanceof Circle) {
|
|||
|
newpl = PolylineHelper.cicleToPolyline(cur)
|
|||
|
}
|
|||
|
else {
|
|||
|
newpl = cur
|
|||
|
}
|
|||
|
newStr = PolylineHelper.getStrPLs([newpl])
|
|||
|
return PolylineHelper.resetPosition(newpl)
|
|||
|
}
|
|||
|
catch (err) {
|
|||
|
console.log(err);
|
|||
|
throw new Error('有非常规造型或2v刀路在合并空间时发生错误,请导出优化结果cfdat文件,并与软件服务商联系!')
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** 小板 标签位置 */
|
|||
|
static resetLabelPos(b: PlaceBlock) {
|
|||
|
if (!b.blockDetail) {
|
|||
|
console.warn("PlaceBlock没有blockDetail,无法计算标签位置")
|
|||
|
return
|
|||
|
}
|
|||
|
if (b.blockDetail.labelPosX != -1)
|
|||
|
return // 已计算
|
|||
|
|
|||
|
const pls = this.getOrgPloylines(b, false)
|
|||
|
const pl = pls.pl
|
|||
|
const mpls = pls.pls_inner
|
|||
|
|
|||
|
const x = b.cutWidth / 2
|
|||
|
const y = b.cutLength / 2
|
|||
|
|
|||
|
b.blockDetail.labelPosX = x
|
|||
|
b.blockDetail.labelPosY = y
|
|||
|
|
|||
|
// 矩形 且没有挖穿造型
|
|||
|
if (b.isUnRegular == false && mpls.length == 0)
|
|||
|
return
|
|||
|
|
|||
|
const vp = getValidPos()
|
|||
|
if (vp) {
|
|||
|
b.blockDetail.labelPosX = vp.x
|
|||
|
b.blockDetail.labelPosY = vp.y
|
|||
|
}
|
|||
|
|
|||
|
// 从中心点出发,左右上下偏移,求点。
|
|||
|
function getValidPos() {
|
|||
|
const off = 40
|
|||
|
const offw = x / off
|
|||
|
const offl = y / off
|
|||
|
|
|||
|
let nx = 0; let ny = 0
|
|||
|
for (let i = 0; i < offw; i++) {
|
|||
|
for (let j = 0; j < offl; j++) {
|
|||
|
nx = x + i * off
|
|||
|
ny = y + j * off
|
|||
|
if (isInPolyline(pl, mpls, nx, ny))
|
|||
|
return { x: nx, y: ny }
|
|||
|
nx = x + i * off
|
|||
|
ny = y - j * off
|
|||
|
if (isInPolyline(pl, mpls, nx, ny))
|
|||
|
return { x: nx, y: ny }
|
|||
|
nx = x - i * off
|
|||
|
ny = y + j * off
|
|||
|
if (isInPolyline(pl, mpls, nx, ny))
|
|||
|
return { x: nx, y: ny }
|
|||
|
nx = x - i * off
|
|||
|
ny = y - j * off
|
|||
|
if (isInPolyline(pl, mpls, nx, ny))
|
|||
|
return { x: nx, y: ny }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return null
|
|||
|
}
|
|||
|
|
|||
|
/** 判断点 在范围内 */
|
|||
|
function isInPolyline(pl: Polyline, mpls: Polyline[], x: number, y: number): boolean {
|
|||
|
for (const mp of mpls) {
|
|||
|
if (PolylineHelper.isPointInPolyline(mp, x, y))
|
|||
|
return false // 在造型洞里头,
|
|||
|
}
|
|||
|
return PolylineHelper.isPointInPolyline(pl, x, y)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|