!2494 功能:余料归方实现

pull/2282/MERGE
ChenX 10 months ago
parent 80f8be1d6b
commit 7f61ffd525

@ -0,0 +1,171 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`lir 1`] = `
Array [
Box2 {
"max": Vector2 {
"x": 22139.12887289156,
"y": -2841.682010503894,
},
"min": Vector2 {
"x": 21469.741102231354,
"y": -3263.948131063738,
},
},
Box2 {
"max": Vector2 {
"x": 21899.684788619557,
"y": -2641.585451102241,
},
"min": Vector2 {
"x": 21688.071880475363,
"y": -2841.682010503894,
},
},
]
`;
exports[`lir 2`] = `
Array [
Box2 {
"max": Vector2 {
"x": 23460.421387167884,
"y": -2637.4589312808325,
},
"min": Vector2 {
"x": 23048.13690406113,
"y": -3242.62504391121,
},
},
]
`;
exports[`lir 3`] = `
Array [
Box2 {
"max": Vector2 {
"x": 24485.042744543087,
"y": -2542.4597375987987,
},
"min": Vector2 {
"x": 23720.604568827835,
"y": -3516.687337476508,
},
},
Box2 {
"max": Vector2 {
"x": 24131.56193396799,
"y": -2013.675435600278,
},
"min": Vector2 {
"x": 23720.604568827835,
"y": -2542.4597375987987,
},
},
]
`;
exports[`lir 4`] = `
Array [
Box2 {
"max": Vector2 {
"x": 25469.309065156027,
"y": -2798.706322535294,
},
"min": Vector2 {
"x": 24639.22077503745,
"y": -3486.2359715248085,
},
},
Box2 {
"max": Vector2 {
"x": 24932,
"y": -2175,
},
"min": Vector2 {
"x": 24639.22077503745,
"y": -2798.706322535294,
},
},
Box2 {
"max": Vector2 {
"x": 25072.310317708012,
"y": -2434.1892907875726,
},
"min": Vector2 {
"x": 24932,
"y": -2798.706322535294,
},
},
]
`;
exports[`lir 5`] = `
Array [
Box2 {
"max": Vector2 {
"x": 26840,
"y": -2267.7761534803576,
},
"min": Vector2 {
"x": 26140,
"y": -3306,
},
},
Box2 {
"max": Vector2 {
"x": 26540,
"y": -3306,
},
"min": Vector2 {
"x": 26240,
"y": -3486,
},
},
Box2 {
"max": Vector2 {
"x": 26140,
"y": -2246,
},
"min": Vector2 {
"x": 26040,
"y": -2806,
},
},
Box2 {
"max": Vector2 {
"x": 26940,
"y": -2866,
},
"min": Vector2 {
"x": 26840,
"y": -3266,
},
},
]
`;
exports[`lir 6`] = `
Array [
Box2 {
"max": Vector2 {
"x": 20867.54619958679,
"y": -2462.241147060554,
},
"min": Vector2 {
"x": 20334.371107671588,
"y": -3470.37106223355,
},
},
Box2 {
"max": Vector2 {
"x": 20971.36213127695,
"y": -2627.7092790342367,
},
"min": Vector2 {
"x": 20867.54619958679,
"y": -3291.6654797019723,
},
},
]
`;

@ -0,0 +1,24 @@
import { LargestInteriorRectangle } from "../../src/Add-on/testEntity/LargestInteriorRectangle";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { AsVector2, equalv3 } from "../../src/Geometry/GeUtils";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('lir', () =>
{
let d =
{ "file": [6, "Polyline", 10, 2, 30486, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 21688.071880475363, -2641.585451102241, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10111.128053715596, -1330.0440361938563, 0, 1], 0, 0, 1, 2, 15, [0, -91.20902138697647], 0, [-99.27451926151298, -91.20902138697647], 0, [-99.27451926151298, -200.09655940165294], 0, [-218.3307782440097, -200.09655940165294], 0, [-218.3307782440097, -622.3626799614967], 0, [0, -622.3626799614967], 0, [0, -745.6835810795424], 0, [211.61290814419408, -745.6835810795424], 0, [211.61290814419408, -622.3626799614967], 0, [451.0569924161973, -622.3626799614967], 0, [451.0569924161973, -200.09655940165294], 0, [211.61290814419408, -200.09655940165294], 0, [211.61290814419408, 0], 0, [0, 0], 0, [0, -91.20902138697647], 0, false, "Polyline", 10, 2, 30487, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 11643.478317846675, -1064.2917826726493, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 11643.478317846675, -1064.2917826726493, 0, 1], 0, 0, 1, 2, 8, [11404.658586214457, -2178.3332612385607], 0, [11404.658586214457, -1330.8596015191276], 0, [11544.497767619087, -1330.8596015191276], 0, [11544.497767619087, -1458.6436810785299], 0, [11673.487357363012, -1458.6436810785299], 0, [11673.487357363012, -1573.1671486081832], 0, [11816.943069321209, -1573.1671486081832], 0, [11816.943069321209, -2178.3332612385607], 0, true, "Polyline", 10, 2, 30488, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 23720.604568827835, -2013.675435600278, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 7839.635766842221, -1733.9653511997813, 0, 1], 0, 0, 1, 2, 7, [764.4381757152514, -528.7843019985207], 0, [410.95736514015334, -528.7843019985207], 0, [410.95736514015334, 0], 0, [0, 0], 0, [0, -1503.01190187623], 0, [764.4381757152514, -1503.01190187623], 0, [764.4381757152514, -528.7843019985206], 0, false, "Polyline", 10, 2, 30489, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 25072.310317708012, -2434.1892907875726, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 11510.346173220109, -921.6709897391447, 0, 1], 0, 0, 1, 2, 9, [396.9987474480131, -364.5170317477214], 0, [0, -364.5170317477214], 0, [0, 0], 0, [-191.2812146794986, 369.9306510311035], 0, [-220.15385085754497, 398.803287209141], 0, [-433.08954267056106, 398.803287209141], 0, [-433.08954267056106, -1052.0466807372359], 0, [396.9987474480131, -1052.0466807372359], 0, [396.9987474480131, -364.5170317477214], 0, false, "Polyline", 10, 2, 30490, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 14328.52642470492, -1135.02410656956, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 14328.52642470492, -1135.02410656956, 0, 1], 0, 0, 1, 2, 9, [11652.077020504916, -1169.4279001173695], 0, [11960.765451660282, -860.7394689621026], 0, [12049.398763576115, -1132.7520469107974], 0, [12510.903249758816, -1074.6819460003912], 0, [12572.02967176977, -1554.5243587863783], 0, [12706.507800193867, -2095.493193583319], 0, [12229.721708508428, -2315.5483128227534], 0, [12067.736690179401, -2630.349386179165], 0, [11755.991937923536, -2074.0989458794857], 0, true, "Polyline", 10, 2, 30485, 0, 1, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4219.473337791907, -173.97252646749985, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4219.473337791907, -173.97252646749985, 0, 1], 0, 0, 1, 2, 16, [16114.89776987968, -3305.5912097645887], 0, [16114.89776987968, -2288.268620593054], 0, [16648.072861794884, -2288.268620593054], 0, [16648.072861794884, -2453.736752566737], 0, [16707.76395829206, -2453.736752566737], 0, [16721.001408849956, -2416.1080736660547], 0, [16748.57943084557, -2416.1080736660547], 0, [16748.57943084557, -2453.6141835800895], 0, [16782.776178120075, -2419.417436305495], 0, [16782.776178120075, -2480.089084695879], 0, [16861.097760587672, -2480.089084695879], 0, [16837.932222111358, -2536.3482495669314], 0, [16884.26329906399, -2604.7417441160537], 0, [16751.888793485043, -2631.2166452318434], 0, [16751.888793485043, -3117.6929532344725], 0, [16677.979694536796, -3296.3985357660504], 0, true], "basePt": { "x": 20334.371107671588, "y": -3765.373492748725, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let pls = LoadEntityFromFileData(d.file) as Polyline[];
for (let pl of pls)
{
let pts = pl.GetStretchPoints();
if (equalv3(pts[0], pts[pts.length - 1]))
pts.pop();
let lir = new LargestInteriorRectangle;
let rects = lir.ParseLIR(pts.map(AsVector2));
expect(rects).toMatchSnapshot();
}
});

@ -0,0 +1,499 @@
import Flatbush from 'flatbush';
import { Box2, Vector2, Vector3 } from "three";
import { arrayRemoveIf } from '../../Common/ArrayExt';
import { FixIndex } from "../../Common/Utils";
import { InsertSortedIndex, RangeUnion } from "../../DatabaseServices/Room/ParseService/RangeUtils";
import { BoxCheckIntersect } from '../../Geometry/CheckIntersect';
import { equaln } from "../../Geometry/GeUtils";
import { arrayPushArray, arraySortByNumber } from "../../Nest/Common/ArrayExt";
import { Max } from '../../Nest/Common/Util';
import { FuzzyFactory } from '../../csg/core/FuzzyFactory';
/**
*
* @param rects
* @returns
*/
function GetMaxAreaFn(rects: [number, number, number][]): number
{
return Max(rects, (t1, t2) => t2[0] > t1[0]);
}
function GetMaxWidthFn(rects: [number, number, number][]): number
{
return Max(rects, (t1, t2) => t2[1] > t1[1]);
}
function GetMaxHeightFn(rects: [number, number, number][]): number
{
return Max(rects, (t1, t2) => t2[2] > t1[2]);
}
//最大内接矩形
//1.分析盒子
// 1.默认我们使用顶点坐标进行一维展开
// 2.当存在斜线时, 我们精确展开(当跨度大于(100/50)时,我们精确产开另一条轴)
// (1).获取需要精确展开的区间 随后合并区间
// (2).对区间进行展开数值,使用二分搜索,如果在已有的顶点附近,则不进行增项
//2.标记轮廓内的矩形
// (1).我们收集多边形所有的斜线,与矩形盒子求交,如果相交,则矩形盒子无效化
// (2).矩形终点在轮廓内(使用单条射线检测,因为我们始终在端点增加锚点的关系 我们似乎不会在顶点位置得到(交点? 稳妥起见 实现标准的射线检测算法)
//3.获取最大内接矩形
// 迭代开始
// 动态规划 存储每个方块得到的最大矩形
// 获取最大的(根据规则)
// 对池子里的结果进行生存选择(如果被占用了方块,则该结果已经不可用)
// 取剩下可用的最大的(因为我们已经是在合理的情况下拿最大的了,所以不需要在重新迭代)
// 重复迭代
/**
* @example
*
* //1. 设置过滤条件(舍弃掉一些无用的矩形)
* let lir = new LargestInteriorRectangle;
* lir.MinWidth = 200;//设置最小可以接受的矩形宽度
* lir.MinHeight = 200;//设置最小可以接受的矩形宽度
* lir.MinArea = 200 * 200;//设置最小可以接受的矩形面积
*
* //除了变量 也可以设置过滤函数
* //例如:
* lir.FilterRectFn = !(w,h)=> (w>500 || h>500) //这样将对长或者宽不足500的矩形板过滤(舍弃)
*
* //2. 可以设置优先模式,默认提供了面积优先,你也可以使用宽度优先或者高度优先,或许默认规则可能不好用,可以自定义传入自定义函数.
* lir.GetMaxRectIndexFn = LargestInteriorRectangle.GetMaxAreaFn; //或者 LargestInteriorRectangle.GetMaxWidthFn / LargestInteriorRectangle.GetMaxHeightFn
*
* //3. 你已经设置好解析器,你现在可以进行解析了
* let rects = lir.ParseLir([ new Vector3(0,0,0) , new Vector3(100,0,0) , new Vector3(50,100,0)]) //首尾不需要重复,首尾重复可能造成错误,程序不再校验
*
*/
export class LargestInteriorRectangle
{
MinWidth = 100;
MinHeight = 100;
MinArea = 200 * 200;
/** 可以自定义过滤函数,以便过滤掉某些不需要的矩形,当返回true时,我们会过滤它 */
FilterRectFn: (width: number, height: number) => boolean;
GetMaxRectIndexFn: (rects: [number, number, number][]) => number = GetMaxAreaFn;
static GetMaxAreaFn = GetMaxAreaFn;
static GetMaxWidthFn = GetMaxWidthFn;
static GetMaxHeightFn = GetMaxHeightFn;
constructor()
{
}
/**
*
* @param polygonPts ,
*/
ParseLIR(polygonPts: Vector2[]): Box2[]
{
//端点列表
let xs: number[] = [];
let ys: number[] = [];
let xset = new Set<number>();
let yset = new Set<number>();
//需要展开的范围
let xranges: [number, number][] = [];
let yranges: [number, number][] = [];
let polygonBox = new Box2().setFromPoints(polygonPts);
let vec = new Vector2;
let klines: [Vector2, Vector2][] = []; //所有的斜线
// let linesP: [Vector2, Vector2][] = []; //所有的线点
// let linesFb = new Flatbush(pts.length);//所有的线的索引
let fuzzX = new FuzzyFactory(1, 0.1);
let fuzzY = new FuzzyFactory(1, 0.1);
for (let i = 0; i < polygonPts.length; i++)
{
let p = polygonPts[i];
let p2 = polygonPts[FixIndex(i + 1, polygonPts)];
// linesP.push([p, p2]);
// let box = new Box2().setFromPoints([p, p2]);
// linesFb.add(box.min.x, box.min.y, box.max.x, box.max.y);
vec.subVectors(p2, p);
//收集端点
let x = fuzzX.lookupOrCreate([p.x], p.x);
if (!xset.has(x))
{
xs.push(x);
xset.add(x);
}
let y = fuzzY.lookupOrCreate([p.y], p.y);
if (!yset.has(y))
{
ys.push(y);
yset.add(y);
}
//展开斜线 每20分段
if (Math.abs(vec.x) > 20 && Math.abs(vec.y) > 20)
{
if (Math.abs(vec.x) > 20)
yranges.push(vec.y > 0 ? [p.y, p2.y] : [p2.y, p.y]);
if (Math.abs(vec.y) > 20)
xranges.push(vec.x > 0 ? [p.x, p2.x] : [p2.x, p.x]);
}
//收集所有的斜线
if (!equaln(vec.x, 0, 0.1) && !equaln(vec.y, 0, 0.1))
klines.push([p, p2]);
}
// linesFb.finish();
//合并展开区间
xranges.sort((a, b) => a[0] - b[0]);
yranges.sort((a, b) => a[0] - b[0]);
xranges = RangeUnion(xranges);
yranges = RangeUnion(yranges);
arraySortByNumber(xs);
arraySortByNumber(ys);
//展开
RangesAdd(xranges, xs);
RangesAdd(yranges, ys);
//最大化
xs[0] = polygonBox.min.x;
xs[xs.length - 1] = polygonBox.max.x;
ys[0] = polygonBox.min.y;
ys[ys.length - 1] = polygonBox.max.y;
//所有网格的索引
let gridFb = new Flatbush((xs.length - 1) * (ys.length - 1));
// let pls: Polyline[] = [];
for (let i = 0; i < xs.length - 1; i++)
{
for (let j = 0; j < ys.length - 1; j++)
{
gridFb.add(xs[i], ys[j], xs[i + 1], ys[j + 1]);
// let pl = new Polyline().RectangleFrom2Pt(new Vector3(xs[i], ys[j]), new Vector3(xs[i + 1], ys[j + 1]));
// if (false) TestDraw(pl);
// pls.push(pl);
}
}
gridFb.finish();
const matrix: number[][] = new Array(xs.length - 1).fill(1).map(() => new Array(ys.length - 1).fill(1));
//矩形与斜线相交
let checks: BoxCheckIntersect[] = [];
for (let line of klines)
{
let box = new Box2().setFromPoints(line);
let ids = gridFb.search(box.min.x, box.min.y, box.max.x, box.max.y);
for (let id of ids)
{
let check = checks[id];
let i = Math.floor((id) / (ys.length - 1));
let j = id - (i * (ys.length - 1));
if (!check)
{
check = new BoxCheckIntersect(new Box2(new Vector2(xs[i] + 0.01, ys[j] + 0.01), new Vector2(xs[i + 1] - 0.01, ys[j + 1] - 0.01)));
checks[id] = check;
// let pl = new Polyline().RectangleFrom2Pt(new Vector3(xs[i], ys[j]), new Vector3(xs[i + 1], ys[j + 1]));
// TestDraw(pl, 2);
}
if (check.IsIntersectLine(line[0], line[1]))
{
// pls[id].ColorIndex = 1;
// pls[id].Erase();
matrix[i][j] = 0;
}
}
}
//y轴扫描线(矩形在多边形外)
// if (xs.length < ys.length)
{
for (let i = 0; i < xs.length - 1; i++)
{
let x = (xs[i + 1] + xs[i]) * 0.5;
let iPtYs = IsPointInPolygon(polygonPts, new Vector3(x, polygonBox.min.y - 0.1, 0));
arraySortByNumber(iPtYs);
for (let j = 0; j < ys.length - 1; j++)
{
let y = (ys[j + 1] + ys[j]) * 0.5;
while (iPtYs.length && iPtYs[0] < y)
iPtYs.shift();
if (iPtYs.length % 2 !== 1)
{
// pls[i * (ys.length - 1) + j].ColorIndex = 3;
// pls[i * (ys.length - 1) + j].Erase();
matrix[i][j] = 0;
}
}
}
}
// else//x轴扫描线
//ref https://leetcode.cn/problems/maximal-rectangle/solutions/535672/zui-da-ju-xing-by-leetcode-solution-bjlu/
const maximalRectangle = () =>
{
const m = matrix.length;//m个竖条 xlist
if (m === 0) return 0;
const n = matrix[0].length;//n个横条 ylist
if (n === 0) return;
const left: number[][] = new Array(m).fill(0).map(() => new Array(n).fill(0));
for (let i = 0; i < m; i++)
{
for (let j = 0; j < n; j++)
{
if (matrix[i][j])
{
left[i][j] = (j === 0 ? 0 : left[i][j - 1]) + 1;
}
}
}
//area maxXIndex maxYIndex xcount ycount
let rects: [number, number, number, number, number][] = [];
for (let j = 0; j < n; j++) // 对于每一列,使用基于柱状图的方法
{
const up = new Array(m).fill(0);
const down = new Array(m).fill(0);
let stack: number[] = [];
for (let i = 0; i < m; i++)
{
while (stack.length && left[stack[stack.length - 1]][j] >= left[i][j])
{
stack.pop();
}
up[i] = stack.length === 0 ? -1 : stack[stack.length - 1];
stack.push(i);
}
stack = [];
for (let i = m - 1; i >= 0; i--)
{
while (stack.length && left[stack[stack.length - 1]][j] >= left[i][j])
{
stack.pop();
}
down[i] = stack.length === 0 ? m : stack[stack.length - 1];
stack.push(i);
}
for (let i = 0; i < m; i++)
{
const xCount = down[i] - up[i] - 1;
const yCount = left[i][j];
if (!yCount || !xCount) continue;
let width = xs[down[i]] - xs[down[i] - xCount];
let height = ys[j + 1] - ys[j + 1 - yCount];
if (width < this.MinWidth || height < this.MinHeight) continue;
//自定义过滤函数
if (this.FilterRectFn && this.FilterRectFn(width, height)) continue;
let area = width * height;
//面积小于最小允许面积
if (area < this.MinArea) continue;
rects.push([area, down[i], j, xCount, yCount]);
}
}
while (rects.length)
{
let maxIndex = Max(rects, (t1, t2) => t2[0] > t1[0]);
let [area, maxXIndex, maxYIndex, xCount, yCount] = rects[maxIndex];
let xMax = xs[maxXIndex];
let yMax = ys[maxYIndex + 1];
let xMin = xs[maxXIndex - xCount];
let yMin = ys[maxYIndex + 1 - yCount];
maxRects.push(new Box2(new Vector2(xMin, yMin), new Vector2(xMax, yMax)));
rects.splice(maxIndex, 1);
//对方块进行标记
for (let i = 0; i < xCount; i++)
{
for (let j = 0; j < yCount; j++)
{
matrix[maxXIndex - 1 - i][maxYIndex - j] = 0;
}
}
//如果有被标记的方块,则删除它
arrayRemoveIf(rects, rect =>
{
let [area, maxX, maxY, xCount, yCount] = rect;
for (let i = 0; i < xCount; i++)
{
for (let j = 0; j < yCount; j++)
{
if (!matrix[maxX - 1 - i][maxY - j])
return true;
}
}
return false;
});
}
};
let maxRects: Box2[] = [];
while (true)
{
let count = maxRects.length;
maximalRectangle();
if (count === maxRects.length) break;
}
return maxRects;
}
}
function RangesAdd(ranges: [number, number][], vList: number[])
{
let adds: number[] = [];
for (let range of ranges)
{
let dist = range[1] - range[0];
let count = Math.floor(dist / 20);
let divDist = Math.floor(dist / count);
for (let i = 1; i < count - 1; i++)
{
let d = Math.floor(range[0] + divDist * i);
let index = InsertSortedIndex(vList, d, (a, b) => a - b);
if (Math.abs(vList[index] - d) < 5)
continue;
if (index !== vList.length - 1 && Math.abs(vList[index + 1] - d) < 5)
continue;
adds.push(d);
}
}
if (adds.length)
{
arrayPushArray(vList, adds);
arraySortByNumber(vList);
}
}
/**
* 线 LIR,Y
*/
function IsPointInPolygon(polyPts: Vector2[], pt: Vector3): number[]
{
// let crossings = 0;
// let insLine = new Line(pt, p2);
let iPtYs: number[] = [];
for (let i = 0; i < polyPts.length; i++)
{
let sp = polyPts[i];
let ep = polyPts[FixIndex(i + 1, polyPts)];
// if (equalv2(sp, pt, 1e-5) || equalv2(ep, pt, 1e-5))//在起点或者终点
// return false;
//点位于线上面
if (pt.y > Math.max(sp.y, ep.y))
continue;
//线垂直Y轴
let derX = ep.x - sp.x;
if (equaln(derX, 0, 5e-6))
{
// if (equaln(pt.x, ep.x, 1e-5)
// && (pt.y > Math.min(sp.y, ep.y) - 1e-5 && pt.y < Math.max(sp.y, ep.y) + 1e-5))
// return false;//点在线上
continue;
}
//起点
if (equaln(sp.x, pt.x, 5e-6))
{
// if (sp.y > pt.y && derX < 0)
if (derX < 0)
{
// crossings++;
iPtYs.push(sp.y);
}
continue;
}
//终点
if (equaln(ep.x, pt.x, 5e-6))
{
// if (ep.y > pt.y && derX > 0)
if (derX > 0)
{
// crossings++;
iPtYs.push(ep.y);
}
continue;
}
//快速求交,只验证有没有交点
let [x1, x2] = sp.x > ep.x ? [ep.x, sp.x] : [sp.x, ep.x];
if (pt.x > x1 && pt.x < x2)
{
let derY = ep.y - sp.y;
let k = derY / derX;
let iptY = (pt.x - sp.x) * k + sp.y;
// if (equaln(iptY, pt.y, 1e-5))//点在线上 返回false
// return false;
if (iptY > pt.y)
{
// crossings++;
iPtYs.push(iptY);
}
}
}
return iPtYs;
}

@ -0,0 +1,38 @@
import { app } from "../../ApplicationServices/Application";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { AsVector2, AsVector3, equalv3 } from "../../Geometry/GeUtils";
import { TestDraw } from "../test/TestUtil";
import { LargestInteriorRectangle } from "./LargestInteriorRectangle";
export class Command_TestLIR implements Command
{
async exec()
{
let ssRes = await app.Editor.GetSelection({
Msg: "选择多边形进行余料归方分析:(我们会忽略圆弧),请在俯视图下选择多边形,我们忽略三维多边形,请不要绘制大于2440大小的多边形",
Filter: { filterTypes: [Polyline] }
});
if (ssRes.Status !== PromptStatus.OK) return;
let ents = ssRes.SelectSet.SelectEntityList as Polyline[];
for (let pl of ents)
{
let pts = pl.GetStretchPoints();
if (equalv3(pts[0], pts[pts.length - 1]))
pts.pop();
let lir = new LargestInteriorRectangle;
let rects = lir.ParseLIR(pts.map(AsVector2));
for (let rect of rects)
{
let pl = new Polyline().RectangleFrom2Pt(AsVector3(rect.min), AsVector3(rect.max));
TestDraw(pl, 6);
}
}
}
}

@ -1,7 +1,4 @@
import { app } from "../../ApplicationServices/Application";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { Command } from "../../Editor/CommandMachine"; import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { HotCMD } from "../../Hot/HotCommand"; import { HotCMD } from "../../Hot/HotCommand";
@HotCMD @HotCMD
@ -9,10 +6,5 @@ export class Test implements Command
{ {
async exec() async exec()
{ {
let enRes = await app.Editor.GetEntity({ Filter: { filterTypes: [Entity] } });
if (enRes.Status !== PromptStatus.OK) return;
let pl = enRes.Entity as Entity;
console.log(pl);
} }
} }

@ -208,7 +208,7 @@ export function IsPointInPolygon(pt: Vec2, pts: Vec2[])
/* Calculate the equation of the line */ /* Calculate the equation of the line */
let dx = ptn.x - pti.x; let dx = ptn.x - pti.x;
let dy = ptn.y - pti.y; let dy = ptn.y - pti.y;
let k; let k: number;
if (Math.abs(dx) < eps) if (Math.abs(dx) < eps)
k = 1e300; k = 1e300;

@ -246,6 +246,7 @@ import { TestTargeOnCurve } from "../Add-on/testEntity/TestCurve";
import { Command_TestDrawEdgeGeometry } from "../Add-on/testEntity/TestDrawEdgeGeometry"; import { Command_TestDrawEdgeGeometry } from "../Add-on/testEntity/TestDrawEdgeGeometry";
import { Command_TestLoadFbx } from "../Add-on/testEntity/TestFbx"; import { Command_TestLoadFbx } from "../Add-on/testEntity/TestFbx";
import { TestFillet } from "../Add-on/testEntity/TestFilletCode"; import { TestFillet } from "../Add-on/testEntity/TestFilletCode";
import { Command_TestLIR } from "../Add-on/testEntity/TestLIR";
import { Command_SimplifyPolyline, Command_TestPolyline2PointsPolyline } from "../Add-on/testEntity/TestPolyline2PointsPolyline"; import { Command_SimplifyPolyline, Command_TestPolyline2PointsPolyline } from "../Add-on/testEntity/TestPolyline2PointsPolyline";
import { Command_TestRegionParse } from "../Add-on/testEntity/TestRegionParse"; import { Command_TestRegionParse } from "../Add-on/testEntity/TestRegionParse";
import { Command_TestSweepMaxLength } from "../Add-on/testEntity/TestSweepMaxLength"; import { Command_TestSweepMaxLength } from "../Add-on/testEntity/TestSweepMaxLength";
@ -687,6 +688,9 @@ export function registerCommand()
{ {
commandMachine.RegisterCommand("DebugTemplateAssocCount", new Command_DebugTemplateAssocCount()); commandMachine.RegisterCommand("DebugTemplateAssocCount", new Command_DebugTemplateAssocCount());
commandMachine.RegisterCommand("testlir", new Command_TestLIR());
commandMachine.RegisterCommand("testNFP", new Command_TestNFP()); commandMachine.RegisterCommand("testNFP", new Command_TestNFP());
commandMachine.RegisterCommand("testSimply", new Command_TestSimply()); commandMachine.RegisterCommand("testSimply", new Command_TestSimply());
commandMachine.RegisterCommand("testSimply2", new Command_TestPolylin2Points()); commandMachine.RegisterCommand("testSimply2", new Command_TestPolylin2Points());

@ -19,6 +19,8 @@ export * from "./DatabaseServices/Contour";
export * from "./DatabaseServices/Shape"; export * from "./DatabaseServices/Shape";
export * from "./DatabaseServices/ShapeManager"; export * from "./DatabaseServices/ShapeManager";
export * from "./Add-on/testEntity/LargestInteriorRectangle";//余料归方算法
// //
export * from "./Nest/Converter/Curves2Points"; export * from "./Nest/Converter/Curves2Points";
export * from "./Nest/Converter/CurveWrap"; export * from "./Nest/Converter/CurveWrap";

Loading…
Cancel
Save