优化:重新实现面域算法

pull/912/head
ChenX 5 years ago
parent 13a0a1be8d
commit 6081b35a9e

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -1,240 +1,20 @@
import { Vector3 } from 'three';
import { Line } from '../../src/DatabaseServices/Entity/Line';
import { LoadCurvesFromFileData } from '../Utils/LoadEntity.util';
import { RegionParse } from './../../src/Geometry/RegionParse';
import { LoadCurvesFromFileData } from "../Utils/LoadEntity.util";
import { RegionParse } from "../../src/Geometry/RegionParse";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import "../Utils/jest.util";
function expectReg(alg: RegionParse)
test('面域分析测试', () =>
{
let data1 = alg.RegionsInternal.map(o =>
{
let res = [];
o.forEach(r => { res.push(r.to.position.toArray()); });
return res;
});
let data2 = alg.RegionsOutline.map(o =>
{
let res = [];
o.forEach(r => { res.push(r.to.position.toArray()); });
return res;
});
expect(data1).toMatchSnapshot();
expect(data2).toMatchSnapshot();
}
test('两个相连的区域', () =>
{
let culist = [];
let l1 = new Line(new Vector3(0, 0, 0), new Vector3(5, 5, 0));
let l2 = new Line(new Vector3(0, 0, 0), new Vector3(3, 2, 0));
let l3 = new Line(new Vector3(5, 5, 0), new Vector3(5, 25, 0));
let l4 = new Line(new Vector3(5, 25, 0), new Vector3(0, 0, 0));
let l5 = new Line(new Vector3(3, 2, 0), new Vector3(4, 3, 0));
let l6 = new Line(new Vector3(4, 3, 0), new Vector3(20, 5, 0));
let l7 = new Line(new Vector3(20, 5, 0), new Vector3(3, 2, 0));
culist.push(l1, l2, l3, l4, l5, l6, l7);
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(2);
expect(g.RegionsInternal.length).toBe(0);
expectReg(g);
});
test('区域内有分割-三角形', () =>
{
let culist = [];
let l1 = new Line(new Vector3(0, 0, 0), new Vector3(5, 0, 0));
let l2 = new Line(new Vector3(5, 0, 0), new Vector3(0, 5, 0));
let l3 = new Line(new Vector3(0, 5, 0), new Vector3(0, 0, 0));
let l4 = new Line(new Vector3(0, 0, 0), new Vector3(0, -5, 0));
let l5 = new Line(new Vector3(5, 0, 0), new Vector3(0, -5, 0));
culist.push(l1, l2, l3, l4, l5);
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(1);
expect(g.RegionsInternal.length).toBe(2);
expectReg(g);
});
test('区域有延长线', () =>
{
let culist = [];
let l1 = new Line(new Vector3(0, 0, 0), new Vector3(5, 0, 0));
let l2 = new Line(new Vector3(5, 0, 0), new Vector3(0, 5, 0));
let l3 = new Line(new Vector3(0, 5, 0), new Vector3(0, 0, 0));
let l4 = new Line(new Vector3(0, 0, 0), new Vector3(0, -5, 0));
let l5 = new Line(new Vector3(5, 0, 0), new Vector3(0, -5, 0));
let l6 = new Line(new Vector3(5, 0, 0), new Vector3(7, 0, 0));
culist.push(l1, l2, l3, l4, l5, l6);
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(1);
expect(g.RegionsInternal.length).toBe(2);
expectReg(g);
});
test('区域内多条线', () =>
{
let culist = [];
let l1 = new Line(new Vector3(0, 0, 0), new Vector3(5, 0, 0));
let l2 = new Line(new Vector3(5, 0, 0), new Vector3(0, 5, 0));
let cus = LoadCurvesFromFileData(require("./curves.json"));
let l3 = new Line(new Vector3(0, 4, 0), new Vector3(0, 0, 0));
let l4 = new Line(new Vector3(0, 0, 0), new Vector3(0, -5, 0));
let reg = new RegionParse(cus);
let l5 = new Line(new Vector3(5, 0, 0), new Vector3(0, -5, 0));
let l6 = new Line(new Vector3(0, 4, 0), new Vector3(5, 0, 0));
let l7 = new Line(new Vector3(0, 4, 0), new Vector3(0, 5, 0));
expect(reg.RegionsOutline.length).toMatchSnapshot();
expect(reg.RegionsInternal.length).toMatchSnapshot();
culist.push(l1, l2, l3, l4, l5, l6, l7);
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(1);
expect(g.RegionsInternal.length).toBe(3);
expectReg(g);
});
test('包含区域', () =>
{
let culist = [];
let l1 = new Line(new Vector3(0, 0, 0), new Vector3(5, 0, 0));
let l2 = new Line(new Vector3(5, 0, 0), new Vector3(5, 5, 0));
let l3 = new Line(new Vector3(5, 5, 0), new Vector3(0, 5, 0));
let l4 = new Line(new Vector3(0, 5, 0), new Vector3(0, 0, 0));
let l5 = new Line(new Vector3(1, 1, 0), new Vector3(2, 1, 0));
let l6 = new Line(new Vector3(2, 1, 0), new Vector3(2, 2, 0));
let l7 = new Line(new Vector3(2, 2, 0), new Vector3(1, 2, 0));
let l8 = new Line(new Vector3(1, 2, 0), new Vector3(1, 1, 0));
culist.push(l1, l2, l3, l4, l5, l6, l7, l8);
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(2);
expect(g.RegionsInternal.length).toBe(0);
expectReg(g);
});
test('测试复杂形状', () =>
{
let culist = [
new Line(new Vector3().fromArray([3.9668615984405444, -1.042884990253411, 0]), new Vector3().fromArray([2.553606237816763, -2.3391812865497075, 0])),
new Line(new Vector3().fromArray([2.553606237816763, -2.3391812865497075, 0]), new Vector3().fromArray([4.912280701754386, -2.7777777777777777, 0])),
new Line(new Vector3().fromArray([4.912280701754386, -2.7777777777777777, 0]), new Vector3().fromArray([3.011695906432749, -3.469785575048733, 0])),
new Line(new Vector3().fromArray([3.011695906432749, -3.469785575048733, 0]), new Vector3().fromArray([1.306042884990254, -0.30214424951267027, 0])),
new Line(new Vector3().fromArray([2.348927875243664, -1.042884990253411, 0]), new Vector3().fromArray([2.553606237816763, -2.3391812865497075, 0])),
new Line(new Vector3().fromArray([2.553606237816763, -2.3391812865497075, 0]), new Vector3().fromArray([3.011695906432749, -3.469785575048733, 0])),
new Line(new Vector3().fromArray([3.011695906432749, -3.469785575048733, 0]), new Vector3().fromArray([4.844054580896684, -3.898635477582846, 0])),
new Line(new Vector3().fromArray([4.844054580896684, -3.898635477582846, 0]), new Vector3().fromArray([4.912280701754386, -2.7777777777777777, 0])),
new Line(new Vector3().fromArray([4.912280701754386, -2.7777777777777777, 0]), new Vector3().fromArray([3.9668615984405444, -1.042884990253411, 0])),
new Line(new Vector3().fromArray([2.465886939571151, 1.939571150097466, 0]), new Vector3().fromArray([1.306042884990254, -0.30214424951267027, 0])),
new Line(new Vector3().fromArray([1.306042884990254, -0.30214424951267027, 0]), new Vector3().fromArray([3.586744639376219, 0.253411306042885, 0])),
new Line(new Vector3().fromArray([3.586744639376219, 0.253411306042885, 0]), new Vector3().fromArray([2.348927875243664, -1.042884990253411, 0])),
new Line(new Vector3().fromArray([2.348927875243664, -1.042884990253411, 0]), new Vector3().fromArray([3.9668615984405444, -1.042884990253411, 0])),
new Line(new Vector3().fromArray([1.306042884990254, -0.30214424951267027, 0]), new Vector3().fromArray([2.348927875243664, -1.042884990253411, 0])),
new Line(new Vector3().fromArray([3.9668615984405444, -1.042884990253411, 0]), new Vector3().fromArray([3.586744639376219, 0.253411306042885, 0])),
new Line(new Vector3().fromArray([3.586744639376219, 0.253411306042885, 0]), new Vector3().fromArray([2.465886939571151, 1.939571150097466, 0])),
];
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(1);
expect(g.RegionsInternal.length).toBe(8);
expectReg(g);
});
test('矩形套矩形', () =>
{
let culist = [
new Line(new Vector3().fromArray([12.781615108958839, -0.7407480871670697, 0]), new Vector3().fromArray([12.781615108958837, -5.947836900726392, 0])),
new Line(new Vector3().fromArray([12.781615108958837, -5.947836900726392, 0]), new Vector3().fromArray([19.5123215496368, -5.947836900726394, 0])),
new Line(new Vector3().fromArray([19.5123215496368, -5.947836900726394, 0]), new Vector3().fromArray([19.5123215496368, -0.7407480871670714, 0])),
new Line(new Vector3().fromArray([19.5123215496368, -0.7407480871670714, 0]), new Vector3().fromArray([12.781615108958839, -0.7407480871670697, 0])),
new Line(new Vector3().fromArray([12.781615108958839, -0.7407480871670697, 0]), new Vector3().fromArray([14.054086973365617, -2.0467060532687644, 0])),
new Line(new Vector3().fromArray([14.054086973365617, -2.0467060532687644, 0]), new Vector3().fromArray([18.54122460048426, -2.0467060532687653, 0])),
new Line(new Vector3().fromArray([18.54122460048426, -2.0467060532687653, 0]), new Vector3().fromArray([18.54122460048426, -5.026969104116222, 0])),
new Line(new Vector3().fromArray([18.54122460048426, -5.026969104116222, 0]), new Vector3().fromArray([14.054086973365617, -5.026969104116221, 0])),
new Line(new Vector3().fromArray([14.054086973365617, -5.026969104116221, 0]), new Vector3().fromArray([14.054086973365617, -2.0467060532687644, 0])),
new Line(new Vector3().fromArray([18.54122460048426, -5.026969104116222, 0]), new Vector3().fromArray([19.5123215496368, -5.947836900726394, 0])),
new Line(new Vector3().fromArray([14.054086973365617, -2.0467060532687644, 0]), new Vector3().fromArray([18.54122460048426, -5.026969104116222, 0]))
];
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(1);
expect(g.RegionsInternal.length).toBe(4);
expectReg(g);
});
test('保护伞', () =>
{
let culist = [
new Line(new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0]), new Vector3().fromArray([-4.01985111662531, -0.7196029776674939, 0])),
new Line(new Vector3().fromArray([-4.01985111662531, -0.7196029776674939, 0]), new Vector3().fromArray([-1.4640198511166256, -0.7196029776674939, 0])),
new Line(new Vector3().fromArray([-1.4640198511166256, -0.7196029776674939, 0]), new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0])),
new Line(new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0]), new Vector3().fromArray([-4.156327543424318, 2.7171215880893302, 0])),
new Line(new Vector3().fromArray([-4.156327543424318, 2.7171215880893302, 0]), new Vector3().fromArray([-1.7121588089330027, 4.094292803970223, 0])),
new Line(new Vector3().fromArray([-1.7121588089330027, 4.094292803970223, 0]), new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0])),
new Line(new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0]), new Vector3().fromArray([-0.33498759305210907, 2.7543424317617866, 0])),
new Line(new Vector3().fromArray([-0.33498759305210907, 2.7543424317617866, 0]), new Vector3().fromArray([-0.33498759305210946, 0.5583126550868487, 0])),
new Line(new Vector3().fromArray([-0.33498759305210946, 0.5583126550868487, 0]), new Vector3().fromArray([-2.0843672456575684, 1.9106699751861045, 0])),
];
let g = new RegionParse(culist);
g.RegionsOutline.length; //?
g.RegionsInternal.length; //?
expect(g.RegionsOutline.length).toBe(3);
expect(g.RegionsInternal.length).toBe(0);
expectReg(g);
});
test('带圆弧的复杂图形测试', () =>
{
let cus = LoadCurvesFromFileData(
[23, "Line", 1, 1, -1, false, 0, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [135.10332884629918, 7.41153204925861, 0], [141.2013396407662, -3.6141642356868466, 0], "Line", 1, 1, -1, false, 1, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [141.2013396407662, -3.6141642356868466, 0], [129.0669141204631, -3.614164235686845, 0], "Line", 1, 1, -1, false, 2, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [129.0669141204631, -3.614164235686845, 0], [118.90356279635137, 9.936970863128803, 0], "Line", 1, 1, -1, false, 3, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [118.90356279635137, 9.936970863128803, 0], [129.25170232635605, 16.219769863488786, 0], "Line", 1, 1, -1, false, 4, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [129.25170232635605, 16.219769863488786, 0], [131.77714114022623, 24.28885485414719, 0], "Line", 1, 1, -1, false, 5, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [131.77714114022623, 24.28885485414719, 0], [121.09714288582433, 18.21968481731883, 0], "Line", 1, 1, -1, false, 6, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [121.09714288582433, 18.21968481731883, 0], [115.57737509027845, 20.531494667657398, 0], "Line", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [115.57737509027845, 20.531494667657398, 0], [118.90356279635137, 9.936970863128803, 0], "Line", 1, 1, -1, false, 0, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [129.25170232635605, 16.219769863488786, 0], [135.10332884629918, 7.41153204925861, 0], "Line", 1, 1, -1, false, 1, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [135.10332884629918, 7.41153204925861, 0], [141.07814750350425, 7.411532049258609, 0], "Line", 1, 1, -1, false, 2, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [141.07814750350425, 7.411532049258609, 0], [150.9951145530921, 6.9187635002107655, 0], "Line", 1, 1, -1, false, 3, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [150.9951145530921, 6.9187635002107655, 0], [146.62179368029246, 22.625761001110725, 0], "Line", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [115.57737509027845, 20.531494667657398, 0], [122.16815443379333, 33.2818808742703, 0], "Line", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [122.16815443379333, 33.2818808742703, 0], [131.77714114022623, 24.28885485414719, 0], "Line", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [131.77714114022623, 24.28885485414719, 0], [140.3389946799325, 29.339732481887566, 0], "Line", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [140.3389946799325, 29.339732481887566, 0], [146.62179368029246, 22.625761001110725, 0], "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 151.10541370131332, 26.821442121699068, 0, 1], 2, 6.14056907448819, 3.8938276244846772, 6.018122149019185, false, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 161.1393080144557, 24.097737845466003, 0, 1], 2, 4.256430496141867, 2.8765294954293896, 5.103001249079749, true, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 164.0426698023552, 17.04682100167833, 0, 1], 2, 3.368852318904628, 1.9614085954899536, 5.109952481560101, false, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 168.0577082733428, 7.485478534075631, 0, 1], 2, 7.001287685275334, 1.9683598279703076, 3.2491377039705007, true, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 156.0343039466818, 6.18741259702873, 0, 1], 2, 5.091984278064126, 0.10754505038070734, 2.997466317295445, false, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 146.05997836303806, 7.635012886374687, 0, 1], 2, 4.986840923627034, 6.139058970885238, 3.1864217771069283, true, "Arc", 1, 1, -1, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 138.09073817490173, 7.277519322534491, 0, 1], 2, 2.9904136682983347, 0.04482912351713572, 3.0967635300726575, false]
);
let g = new RegionParse(cus);
expect(g.RegionsInternal.length).toBe(7);
expect(g.RegionsOutline.length).toBe(1);
for (let routes of [...reg.RegionsOutline, ...reg.RegionsInternal])
{
let pl = Polyline.Combine(routes.map(r => r.curve), 1e-3);
expect(pl.Length).toMatchNumberSnapshot();
}
});

@ -11,7 +11,7 @@
"build": "webpack --config ./config/webpack.prod.ts && ts-node ./utils/log.ts && ts-node ./utils/publish.ts",
"test": "jest",
"testu": "jest -u",
"testw": "jest --watch",
"testw": "jest --watchAll",
"ser": "node ./utils/server.js",
"type": "ts-node ./utils/copy_type.ts",
"publish": "ts-node ./utils/publish.ts"

@ -7,7 +7,8 @@ import { Region } from '../DatabaseServices/Entity/Region';
import { Spline } from '../DatabaseServices/Spline';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
import { RegionParse, Route } from '../Geometry/RegionParse';
import { Route } from '../Geometry/CurveMap';
import { RegionParse } from '../Geometry/RegionParse';
export class DrawRegion implements Command
{
@ -79,11 +80,9 @@ export class DrawRegion implements Command
}
}
}
DrawRegion(routeS: Set<Route>)
DrawRegion(routeS: Array<Route>)
{
let cus: Curve[] = [];
for (let r of routeS)
cus.push(r.curve);
let cus: Curve[] = routeS.map(r => r.curve);
let reg = Region.CreateFromCurves(cus);
if (reg)
{

@ -6,7 +6,8 @@ import { Line } from '../DatabaseServices/Entity/Line';
import { Region } from '../DatabaseServices/Entity/Region';
import { Command } from '../Editor/CommandMachine';
import { MoveMatrix } from '../Geometry/GeUtils';
import { RegionParse, Route } from '../Geometry/RegionParse';
import { RegionParse } from '../Geometry/RegionParse';
import { Route } from '../Geometry/CurveMap';
export class DrawRegTest implements Command
{
@ -203,10 +204,9 @@ export class DrawRegTest implements Command
// }
}
}
function createReg(r: Set<Route>)
function createReg(routes: Array<Route>)
{
let cus: Curve[] = [];
r.forEach(route => cus.push(route.curve.Clone() as Curve));
let cus: Curve[] = routes.map(r => r.curve);
let re = Region.CreateFromCurves(cus);
app.Database.ModelSpace.Append(re);
}

@ -4,9 +4,10 @@ import { app } from "../ApplicationServices/Application";
import { Vector3, Object3D } from "three";
import { Board } from "../DatabaseServices/Entity/Board";
import { PromptStatus } from "../Editor/PromptResult";
import { Entity } from "../DatabaseServices/Entity/Entity";
const MOVEDIS = 10;
const MOVECOUNT = 70;
const MOVECOUNT = 300;
const STOPCOUNT = MOVECOUNT * 2 + 1;
export class Command_ExplosionMap implements Command
@ -17,7 +18,7 @@ export class Command_ExplosionMap implements Command
async exec()
{
let view = app.Viewer;
if (this.timer)
if (this.timer)
{
clearInterval(this.timer);
let moveDis = (MOVEDIS) * (this.count < MOVECOUNT ? this.count : (STOPCOUNT - this.count));
@ -35,7 +36,7 @@ export class Command_ExplosionMap implements Command
UseSelect: true,
Msg: "请选择需要展示爆炸图的板件",
Filter: {
filterTypes: [Board],
filterTypes: [Entity],
},
AllowNone: false,
});
@ -46,7 +47,7 @@ export class Command_ExplosionMap implements Command
let cen = box.getCenter(new Vector3());
for (let obj of brs.SelectSet.SelectObjectList)
{
if (obj.userData && obj.userData.Entity instanceof Board)
if (obj.userData && obj.userData.Entity)
{
let objCen = GetBox(obj).getCenter(new Vector3());
let v = objCen.clone().sub(cen);

@ -7,11 +7,10 @@ import { Line } from '../DatabaseServices/Entity/Line';
import { Polyline } from '../DatabaseServices/Entity/Polyline';
import { IsPointInBowArc } from '../DatabaseServices/PointInPolyline';
import { Count } from '../Geometry/Count';
import { CurveMap } from '../Geometry/CurveMap';
import { CurveMap, Vertice } from '../Geometry/CurveMap';
import { AsVector2, AsVector3, equaln, equalv2, equalv3, isParallelTo, ZeroVec } from '../Geometry/GeUtils';
import { Orbit } from '../Geometry/Orbit';
import { PlaneExt } from '../Geometry/Plane';
import { Stand } from '../Geometry/RegionParse';
import { IntersectOption, IntersectResult } from '../GraphicsSystem/IntersectWith';
import { OffsetPolyline } from '../GraphicsSystem/OffsetPolyline';
import { arrayLast, changeArrayStartIndex, equalArray } from './ArrayExt';
@ -115,12 +114,11 @@ export function curveLinkGroup(cus: Curve[]): Array<Array<Curve>>
/**
* 线,线.
*
* @param {Stand} stand
* @param {Curve[]} cus 线
* @param {boolean} isEndSeach true:,false:
* @returns {Stand} 线,,undefined
*/
function linkCurve(stand: Stand, cus: Curve[], isEndSeach: boolean): Stand | undefined
function linkCurve(stand: Vertice, cus: Curve[], isEndSeach: boolean): Vertice | undefined
{
for (let route of stand.routes)
{

@ -3,8 +3,9 @@ import { arrayLast, arrayRemoveDuplicateBySort } from "../Common/ArrayExt";
import { curveLinkGroup, equalCurve } from "../Common/CurveUtils";
import { Status } from "../Common/Status";
import { FixIndex } from "../Common/Utils";
import { Route } from "../Geometry/CurveMap";
import { equaln, equalv3 } from "../Geometry/GeUtils";
import { RegionParse, Route } from "../Geometry/RegionParse";
import { RegionParse } from "../Geometry/RegionParse";
import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils";
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
import { Arc } from "./Entity/Arc";
@ -162,13 +163,11 @@ export class Contour
let contours: Contour[] = [];
//分析封闭包围区域
const parseRoute = (routeSet: Set<Route>[]) =>
const parseRoute = (routeSet: Array<Route>[]) =>
{
for (let routes of routeSet)
{
let cs: Curve[] = [];
for (let r of routes)
cs.push(r.curve);
let cs: Curve[] = routes.map(r => r.curve);
let c = Contour.CreateContour(cs, false);
if (c
&& !equalCurve(c.Curve, this.Curve)
@ -270,7 +269,7 @@ export class Contour
}
return { intersectionList, unionList };
}
GetSubtractList(target: Contour)
GetSubtractList(target: Contour): Polyline[]
{
let sourceOutline = this._Curve as Polyline;
let targetOutline = target.Curve as Polyline;
@ -292,32 +291,29 @@ export class Contour
}
//相交
let subtractList: Curve[] = [];
let subtractList: Polyline[] = [];
let sourceCus = sourceOutline.GetSplitCurves(interPts.map(r => r.thisParam)) as Polyline[];
let targetCus = targetOutline.GetSplitCurves(interPts.map(r => r.argParam)) as Polyline[];
for (let pl of sourceCus)
{
let hasEqualCus = false;
for (let i = 0; i < targetCus.length; i++)
let plMidParam = pl.MidParam;
let plDir = pl.GetFistDeriv(plMidParam).normalize();
let index = targetCus.findIndex(cu => fastEqualCurve(cu, pl));
if (index !== -1)
{
let cu = targetCus[i];
hasEqualCus = fastEqualCurve(cu, pl);
if (hasEqualCus &&
(!equalv3(cu.GetFistDeriv(cu.EndParam * 0.5).normalize(), pl.GetFistDeriv(pl.EndParam * 0.5).normalize(), 1e-3))
=== isEqualNormal)
{
let cu = targetCus[index];
let cuMidParam = cu.MidParam;
let cuDir = cu.GetFistDeriv(cuMidParam).normalize();
if (isEqualNormal === !equalv3(cuDir, plDir, 1e-3))//不同向
subtractList.push(pl);
targetCus.splice(i, 1);
}
if (hasEqualCus)
break;
}
targetCus.splice(index, 1);
if (hasEqualCus)
continue;
}
if (!fastCurveInCurve(targetOutline, pl))
subtractList.push(pl);
}

@ -52,7 +52,19 @@ export abstract class Curve extends Entity
set EndPoint(v: Vector3) { return; }
/** 曲线中点 */
get Midpoint() { return this.GetPointAtParam(0.5); }
get Midpoint()
{
return this.GetPointAtParam(this.MidParam);
}
get MidParam()
{
if (this.EndParam === 1)
return 0.5;
else
return this.GetParamAtDist(this.Length * 0.5);
}
get EndParam(): number { return; }
get Area(): number { return 0; }
/**

@ -350,13 +350,6 @@ export class Polyline extends Curve
this.SetPointAt(this.EndParam, AsVector2(p));
}
get Midpoint()
{
if (this.EndParam === 1)
return this.GetPointAtParam(0.5);
return this.GetPointAtDistance(this.Length * 0.5);
}
get CurveCount(): number
{
return this.EndParam;
@ -420,7 +413,7 @@ export class Polyline extends Curve
//曲线是否闭合
get IsClose(): boolean
{
return this.CloseMark || (equalv3(this.StartPoint, this.EndPoint, 1e-4)) && this.EndParam > 1;
return this.CloseMark || (this.EndParam > 1 && (equalv3(this.StartPoint, this.EndPoint, 1e-4)));
}
set CloseMark(v: boolean)
{

@ -1,94 +1,152 @@
import { Vector3 } from "three";
import { ToFixed } from "../Common/Utils";
import { Arc } from "../DatabaseServices/Entity/Arc";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { angle, equalv3 } from "./GeUtils";
import { Route, Stand } from "./RegionParse";
import { angle, clampRad, equalv3 } from "./GeUtils";
//顶点
export interface Vertice
{
//位置
position: Vector3;
//路径
routes: Route[];
}
//路线
export interface Route
{
curve: Curve; //路线的曲线
from: Vertice;
to: Vertice; //终点的点
length: number;
isReverse: boolean;
an?: number; //角度
s: Vector3;
e: Vector3;
}
/**
* 线,使.
*/
export class CurveMap
{
constructor(public fractionDigits = 4)
{
}
constructor(
public numdimensions = 4,
public _RemoveSortLine = false,
private multiplier = 10 ^ numdimensions,
) { }
/*
.
线.
使,使x.
*/
m_NodeMap = new Map<Vector3, Stand>();
_NodeMap = new Map<Vector3, Vertice>();
/**
*
* @type {Stand[]}
*/
get Stands(): Stand[]
get Stands(): Vertice[]
{
let stands = [];
this.m_NodeMap.forEach(s => stands.push(s));
let stands: Vertice[] = [];
this._NodeMap.forEach(s => stands.push(s));
return stands;
}
AddCurveToMap(cu: Curve)
AddCurveToMap(curve: Curve, isArc: boolean = curve instanceof Arc, removeDuplicate: boolean = false)
{
cu.TempData = 0;
let sp = cu.StartPoint;
let ep = cu.EndPoint;
let sp = curve.StartPoint;
let ep = curve.EndPoint;
let startS = this.GetStand(sp);
let endS = this.GetStand(ep);
let routeS2E: Route = { curve: cu, to: endS, s: sp, e: ep };
CalcRouteAngle(routeS2E, startS.position);
let routeE2S: Route = { curve: cu, to: startS, s: ep, e: sp };
CalcRouteAngle(routeE2S, endS.position);
//在面域分析中,路线指向同一个顶点已经没有意义了
if (this._RemoveSortLine && startS === endS)
return;
if (removeDuplicate)//删除重复
{
let index = startS.routes.findIndex(r =>
{
if (r.to === endS && r.curve.constructor.name === curve.constructor.name)
{
if (isArc)
return equalv3(curve.GetPointAtParam(0.5), r.curve.GetPointAtParam(0.5));
return true;
}
});
if (index !== -1) return;
}
let length = curve.Length;
curve.TempData = 0;
let routeS2E: Route = { curve, isReverse: false, length, from: startS, to: endS, s: sp, e: ep };
let routeE2S: Route = { curve, isReverse: true, length, from: endS, to: startS, e: sp, s: ep };
if (!isArc)
{
let an = angle(ep.clone().sub(sp));
routeS2E.an = an;
routeE2S.an = clampRad(an + Math.PI);
}
startS.routes.push(routeS2E);
endS.routes.push(routeE2S);
}
/**
* .
*
* @private
* @param {Vector3} p
* @returns {Stand}
* @memberof RegionAlg
*
*/
GetStand(p: Vector3): Stand
GetStand(p: Vector3): Vertice
{
let gp = this.GenerateP(p);
if (this.m_NodeMap.has(gp))
return this.m_NodeMap.get(gp);
if (this._NodeMap.has(gp))
return this._NodeMap.get(gp);
let stand = { position: gp, routes: [] };
this.m_NodeMap.set(p, stand);
this._NodeMap.set(p, stand);
return stand;
}
private m_vecMap = new Map<string, Vector3>();
_LookupTable: { [key: string]: Vector3; } = {};
/**
* .
*
* @param {Vector3} v
* @returns {Vector3}
* @memberof RegionAlg
*/
private GenerateP(v: Vector3): Vector3
GenerateP(v: Vector3): Vector3
{
let str = v.toArray().map(v => ToFixed(v, this.fractionDigits)).join(",");
if (this.m_vecMap.has(str))
return this.m_vecMap.get(str);
this.m_vecMap.set(str, v);
let key = "";
let els = v.toArray();
for (let n of els)
{
let valueQuantized = Math.round(n * this.multiplier);
key += valueQuantized + '/';
}
if (key in this._LookupTable)
return this._LookupTable[key];
let hashparts = els.map((el) =>
{
let q0 = Math.floor(el * this.multiplier);
let q1 = q0 + 1;
return ['' + q0 + '/', '' + q1 + '/'];
});
let numelements = els.length;
let numhashes = 1 << numelements;
for (let hashmask = 0; hashmask < numhashes; ++hashmask)
{
let hashmaskShifted = hashmask;
key = '';
hashparts.forEach(function (hashpart)
{
key += hashpart[hashmaskShifted & 1];
hashmaskShifted >>= 1;
});
this._LookupTable[key] = v;
}
return v;
}
}
function CalcRouteAngle(r: Route, standPoint: Vector3)
{
if (equalv3(r.curve.StartPoint, standPoint))
r.an = angle(r.curve.GetFistDeriv(0));
else
r.an = angle(r.curve.GetFistDeriv(r.curve.EndParam).negate());
}

@ -1,34 +1,14 @@
import { Vector3 } from 'three';
import { arrayRemoveDuplicateBySort, arrayRemoveIf } from '../Common/ArrayExt';
import { Arc } from '../DatabaseServices/Entity/Arc';
import { Curve } from '../DatabaseServices/Entity/Curve';
import { Polyline } from '../DatabaseServices/Entity/Polyline';
import { equaln } from '../Nest/Util';
import { CurveMap } from './CurveMap';
import { equalv3 } from './GeUtils';
//路线
export interface Route
{
curve: Curve; //路线的曲线
to: Stand; //终点的点
s: Vector3;
e: Vector3;
an?: number;
}
//站台
export interface Stand
{
//位置
position: Vector3;
//路径
routes: Array<Route>;
}
import { Vector3 } from "three";
import { arrayLast, arrayRemove, arrayRemoveIf } from "../Common/ArrayExt";
import { Arc } from "../DatabaseServices/Entity/Arc";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { FixIndex } from "../Nest/Util";
import { CurveMap, Route, Vertice } from "./CurveMap";
import { angle } from "./GeUtils";
//区域的路线表 表示了一个区域
type RegionRouteS = Array<Set<Route>>;
type RegionRouteS = Route[][];
//区域搜索算法
export class RegionParse
@ -41,152 +21,126 @@ export class RegionParse
//碎线 曲线进入到这里会被炸开.
ExpLineMap: Map<Curve, Curve[]> = new Map();
private _CurveCount: number;
/**
* @param {Curve[]} cuList .
*/
constructor(cuList: Curve[], public fractionDigits = 3)
constructor(cuList: Curve[], public numDimensions = 3, private removeDuplicate = true)
{
//需要搜索的站
let needFinds = this.GenerateNodeMap(cuList);
let vertices = this.GenerateNodeMap(cuList);
//搜索大轮廓.
while (needFinds.size > 0)
//移除细丝
while (true)
{
//找到最小的站.
let lowerLeftStand = this.FindLowerLeftStand(needFinds);
needFinds.delete(lowerLeftStand);
//逆时针+逆时针
for (let i = lowerLeftStand.routes.length; i--;)
let v = vertices.find(v => v.routes.length < 2);
if (v) vertices = this.RemoveFilamentAt(v, vertices);
else break;
}
let lowerVertice: Vertice;
while (vertices.length > 0)
{
lowerVertice = lowerVertice?.routes.length > 1 ? lowerVertice : this.FindLowerLeftStand(vertices);
let minWalk = ClosedWalkFrom(lowerVertice, this._CurveCount, WalkType.Min);
let maxWalk = ClosedWalkFrom(lowerVertice, this._CurveCount, WalkType.Max);
this.RemoveEdge(minWalk[0]);
vertices = this.RemoveFilamentAt(minWalk[0].from, vertices);
vertices = this.RemoveFilamentAt(minWalk[0].to, vertices);
minWalk = ReduceWalk(minWalk);
maxWalk = ReduceWalk(maxWalk);
if (maxWalk.length > 1)
{
let wayS = new Set<Stand>();
let routeS = new Set<Route>();
let isFind = this.FindRegion(lowerLeftStand, lowerLeftStand, undefined, wayS, routeS, 1);
if (isFind)
this.RegionsOutline.push(maxWalk);
if (minWalk.length === maxWalk.length && minWalk.every((w1, index) => w1 === maxWalk[index]))//大小重叠
{
this.RegionsOutline.push(routeS);
//计数增加
for (let route of routeS)
route.curve.TempData += 1;
this.FindInternalRegion(wayS);
//直接remove,不用计算引用个数
for (let w of minWalk)
{
this.RemoveEdge(w);
this.RemoveFilamentAt(w.from, vertices);
this.RemoveFilamentAt(w.to, vertices);
}
continue;//继续循环
}
else
for (let w of maxWalk)
w.curve.TempData = 1;
}
}
}
/**
* 线使
* @param cu
* @returns true if cueve used
*/
GetCueveUsed(cu: Curve): boolean
{
if (this.ExpLineMap.has(cu))
{
let use = this.ExpLineMap.get(cu).some(c => c.TempData > 0);
if (!use)
this.ExpLineMap.delete(cu);
return use;
if (minWalk.length > 1)// && minWalk.every(w => <number>(w.curve.TempData) < 2) 没有重复线应该不会被用2次
{
this.RegionsInternal.push(minWalk);
for (let w of minWalk)
{
w.curve.TempData++;
if (w.curve.TempData === 2)
{
this.RemoveEdge(w);
this.RemoveFilamentAt(w.from, vertices);
this.RemoveFilamentAt(w.to, vertices);
}
}
}
}
else
return cu.TempData > 0;
}
/**
* 使,,.
* .
* @param {Set<Stand>} standS
*/
FindInternalRegion(standS: Set<Stand>)
RemoveFilamentAt(v: Vertice, vertices: Vertice[])
{
//需要搜索的.
let needFinds = new Set<Stand>();
standS.forEach(w => needFinds.add(w));
//已经走过的
let passingStands = new Set<Stand>();
let regs: RegionRouteS = [];
while (needFinds.size > 0)
let current = v;
while (current && current.routes.length < 2)
{
//找到最下方最左边的站点yx
let lowerLeftStand = this.FindLowerLeftStand(needFinds);
//添加为已经计算
passingStands.add(lowerLeftStand);
needFinds.delete(lowerLeftStand);
//顺时针搜索
for (let j = lowerLeftStand.routes.length; j--;)
vertices = arrayRemove(vertices, current);
let r = current.routes[0];
if (r)
{
let route = lowerLeftStand.routes[j];
if (!needFinds.has(route.to))
continue;
if (route.curve.TempData === 2)
continue;
let wayS = new Set<Stand>();
let routeS = new Set<Route>();
routeS.add(route);
wayS.add(route.to);
let isFindMin = this.FindRegion(lowerLeftStand, route.to, route.curve, wayS, routeS, 2);
if (isFindMin)
{
regs.push(routeS);
wayS.forEach(w =>
{
//站点拓展,如果该地点没有被走过,那么加入到需要搜寻的站点表
if (!passingStands.has(w))
needFinds.add(w);
});
for (let route of routeS)
route.curve.TempData += 1;
}
this.RemoveEdge(r);
current = r.to;
}
else
current = undefined;
}
return vertices;
}
if (regs.length > 1)
this.RegionsInternal.push(...regs);
RemoveEdge(r: Route)
{
let index = r.from.routes.findIndex(rr => rr.curve === r.curve);
if (index !== -1)
r.from.routes.splice(index, 1);
index = r.to.routes.findIndex(rr => rr.curve === r.curve);
if (index !== -1)
r.to.routes.splice(index, 1);
}
/**
* yx
* @param {Set<Stand>} standS
*/
private FindLowerLeftStand(standS: Set<Stand>): Stand
private FindLowerLeftStand(vertices: Vertice[]): Vertice
{
let minStand: Stand;
for (let stand of standS)
return vertices.reduce((m, v) =>
{
if (!minStand)
{
minStand = stand;
continue;
}
if (minStand.position.y > stand.position.y)
minStand = stand;
else if (minStand.position.y === stand.position.y && minStand.position.x > stand.position.x)
minStand = stand;
}
return minStand;
let dy = v.position.y - m.position.y;
if (dy < 0) return v;
if (dy > 0) return m;
return v.position.x - m.position.x < 0 ? v : m;
});
}
/**
* 线. 线. 使,使x.
* @param {Curve[]} cuList
* @returns {Set<Stand>}
* @returns
*/
private GenerateNodeMap(cuList: Curve[]): Set<Stand>
private GenerateNodeMap(curveList: Curve[]): Array<Vertice>
{
let curveMap = new CurveMap(this.fractionDigits);
let curveMap = new CurveMap(this.numDimensions, true);
//将多段线炸开
let plcus: Curve[] = [];
arrayRemoveIf(cuList, c =>
arrayRemoveIf(curveList, c =>
{
if (c instanceof Polyline)
{
@ -216,9 +170,11 @@ export class RegionParse
}
return false;
});
cuList.push(...plcus);
curveList.push(...plcus);
this._CurveCount = curveList.length;
for (let cu of cuList)
for (let cu of curveList)
{
//由于圆弧可能导致最低点计算错误的问题.
if (cu instanceof Arc)
@ -226,36 +182,35 @@ export class RegionParse
let arcs = this.BreakArc(cu);
if (arcs.length > 1)
{
arcs.forEach(a => curveMap.AddCurveToMap(a));
arcs.forEach(a => curveMap.AddCurveToMap(a, true, this.removeDuplicate));
this.ExpLineMap.set(cu, arcs);
continue;
}
else
curveMap.AddCurveToMap(cu, true, this.removeDuplicate);
}
curveMap.AddCurveToMap(cu);
else
curveMap.AddCurveToMap(cu, false, this.removeDuplicate);
}
//排序,根据角度逆时针排序.
curveMap.m_NodeMap.forEach(s =>
curveMap._NodeMap.forEach(s =>
{
s.routes.sort((r1, r2) =>
{
return r1.an - r2.an;
});
//移除重复的线
arrayRemoveDuplicateBySort(s.routes, (r1, r2) =>
let minLength = Infinity;
for (let r of s.routes)
{
let isEqual = r1.to === r2.to && r1.curve.constructor.name === r2.curve.constructor.name;
if (isEqual && r1.curve instanceof Arc)
return equalv3(r1.curve.GetPointAtParam(0.5), r2.curve.GetPointAtParam(0.5));
return isEqual;
});
if (r.length < minLength)
minLength = r.length;
}
for (let r of s.routes)
CalcRouteAngle(r, minLength * 0.2);
s.routes.sort((r1, r2) => r1.an - r2.an);
});
return new Set(curveMap.Stands);
return curveMap.Stands;
}
private BreakArc(arc: Arc)
private BreakArc(arc: Arc): Arc[]
{
let underPt = arc.Center.add(new Vector3(0, -arc.Radius));
let param = arc.GetParamAtPoint(underPt);
@ -265,73 +220,98 @@ export class RegionParse
return [arc];
}
//寻找闭合轮廓,下一站总是使用逆时针规划.
private FindRegion(firstS: Stand, //起点
nowStand: Stand, //当前站
lastCurve: Curve, //上一条线索引
wayStands: Set<Stand>, //走过的站
routeS: Set<Route>, //走过的路
cuMaximumCount: number, //允许最大的行走次数
)
/**
* 线使
* @param cu
* @returns true if cueve used
*/
GetCueveUsed(cu: Curve): boolean
{
let routeCount = nowStand.routes.length;
//查找上一条线的索引.
let lastIndex = -1;
if (lastCurve)
if (this.ExpLineMap.has(cu))
{
for (let i = routeCount; i--;)//顺时针搜索.
{
if (nowStand.routes[i].curve === lastCurve)
{
lastIndex = i;
break;
}
}
let use = this.ExpLineMap.get(cu).some(c => c.TempData > 0);
if (!use)
this.ExpLineMap.delete(cu);
return use;
}
else
return cu.TempData > 0;
}
}
for (let i = 0; i < routeCount - 1; i++)
{
let index = lastIndex + i + 1;//转弯,逆时针
if (index >= routeCount) index -= routeCount;
//下一站
let route = nowStand.routes[index];
function CalcRouteAngle(r: Route, length: number)
{
if (r.an !== undefined) return;
let cu = r.curve;
let p = r.isReverse ?
cu.GetPointAtParam(cu.GetParamAtDist(r.length - length))
: cu.GetPointAtParam(cu.GetParamAtDist(length));
r.an = angle(p.sub(r.from.position));
}
let usedCount = route.curve.TempData;
if (usedCount >= cuMaximumCount)
continue;
enum WalkType
{
Min = 1,
Max = -1,
}
//如果发现这条路已经走回去,中途回路
if (wayStands.has(route.to))
{
return false;
// for (let stand of wayStands)
// {
// if (stand === route.to)
// break;
// wayStands.delete(stand);//删除不是回路的部分
// }
// return true;
}
function ClosedWalkFrom(startVertice: Vertice, maxRoute: number, type = WalkType.Min): Route[]
{
let walk: Route[] = [];
let curVertice: Vertice = startVertice;
let preRoute: Route;
// console.log("start", type, startVertice.position.toArray());
do
{
let route = GetNextRoute(curVertice, preRoute, type);
if (type === WalkType.Max && route.curve.TempData > 0)
return [];
// console.log(route.to.position.toArray());
walk.push(route);
[curVertice, preRoute] = [route.to, route];
if (walk.length > maxRoute * 2)
throw "超过计算次数限制";
}
while (curVertice !== startVertice);
//加入到已经走过的道路.
wayStands.add(route.to);
routeS.add(route);
return walk;
}
//已经回原地,此处不验证该轮廓的正确性.
if (route.to === firstS)
return true;
/**
*
*/
function ReduceWalk(w: Route[]): Route[]
{
if (w.length === 0) return w;
//未构成回路,直接回家
if (w[0].curve === arrayLast(w).curve) return [];
//在下个路口试着往前走
let isFind = this.FindRegion(firstS, route.to, route.curve, wayStands, routeS, cuMaximumCount);
if (isFind)
return true;
else
for (let i = 0; i < w.length; i++)
{
let r1 = w[i];
for (let j = w.length; j--;)
{
if (i === j) break;
let r2 = w[j];
if (r1.to === r2.to)
{
wayStands.delete(route.to);//不走这条路
routeS.delete(route);
if (j > i)
w.splice(i + 1, j - i);
break;
}
}
return false;
}
return w;
}
function GetNextRoute(v: Vertice, prev?: Route, type: WalkType = WalkType.Min): Route
{
if (!prev)
return arrayLast(v.routes); //顺时针 cw \|/ 从左往右
//逆时针 ccw 往左
let index = v.routes.findIndex(r => r.curve === prev.curve);
let newIndex = FixIndex(index + 1 * type, v.routes);
return v.routes[newIndex];
}

@ -1,9 +1,8 @@
import { Vector3 } from "three";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { CurveIntersection } from "../Geometry/CurveIntersection";
import { CurveMap } from "../Geometry/CurveMap";
import { equalv3, equaln } from "../Geometry/GeUtils";
import { Stand } from "../Geometry/RegionParse";
import { CurveMap, Vertice } from "../Geometry/CurveMap";
import { equaln, equalv3 } from "../Geometry/GeUtils";
export class LinkSelf
{
@ -92,7 +91,7 @@ export class LinkSelf
for (let route of stand.routes)
{
//缓存走过的节点
let ways: Stand[] = [];
let ways: Vertice[] = [];
ways.push(cuMap.GetStand(cu.StartPoint));
if (equalv3(route.curve.EndPoint, stand.position))
@ -187,7 +186,7 @@ export class LinkSelf
}
}
//寻找最小索引的路线
private FindMinRoute(nowStand: Stand, nowIndex: number, cs: Curve[], routes: Curve[]): { minIndex: number, routes: Curve[]; }
private FindMinRoute(nowStand: Vertice, nowIndex: number, cs: Curve[], routes: Curve[]): { minIndex: number, routes: Curve[]; }
{
//和当前索引一样的 搜索结果
let curIndex: { minIndex: number, routes: Curve[]; } = undefined;
@ -238,7 +237,7 @@ export class LinkSelf
}
//搜索闭合的区域
private FindCloseCurve(nowStand: Stand, cuIndex: number, ways: Stand[], routes: Set<Curve>, cuMap: CurveMap)
private FindCloseCurve(nowStand: Vertice, cuIndex: number, ways: Vertice[], routes: Set<Curve>, cuMap: CurveMap)
{
for (let route of nowStand.routes)
{
@ -280,8 +279,8 @@ export class LinkSelf
{
let cuMap = new CurveMap();
breakCus.forEach(c => cuMap.AddCurveToMap(c));
//所有的站点 逆序排序.
for (let [, stand] of cuMap.m_NodeMap)
//所有的站点 逆序排序.
for (let [, stand] of cuMap._NodeMap)
{
stand.routes.sort((r1, r2) =>
{

@ -10,9 +10,8 @@ import { Curve } from "../DatabaseServices/Entity/Curve";
import { Line } from "../DatabaseServices/Entity/Line";
import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { IntersectsBox } from "../Geometry/Box";
import { CurveMap } from "../Geometry/CurveMap";
import { CurveMap, Vertice, Route } from "../Geometry/CurveMap";
import { angle, equaln, equalv2, equalv3, IdentityMtx4, SelectNearP } from "../Geometry/GeUtils";
import { Route, Stand } from "../Geometry/RegionParse";
import { SortEntityByBox } from "../Geometry/SortEntityByBox";
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
@ -611,7 +610,7 @@ export class OffsetPolyline
let preP: Vector3;
let searchNext = (s: Stand, pl: Polyline): Stand =>
let searchNext = (s: Vertice, pl: Polyline): Vertice =>
{
let minDist = Infinity;
let minR: Route;
@ -651,10 +650,10 @@ export class OffsetPolyline
preP = undefined;
let pl = new Polyline();
let ss = s;
while (ss)
while (ss && !pl.IsClose)
ss = searchNext(ss, pl);
ss = s;
while (ss)
while (ss && !pl.IsClose)
ss = searchNext(ss, pl);
if (pl.NumberOfVertices > 0)

@ -1,24 +1,25 @@
import { Matrix4, Vector3 } from "three";
import { equalCurve, IsRect } from "../../Common/CurveUtils";
import { Singleton } from "../../Common/Singleton";
import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole";
import { Contour } from "../../DatabaseServices/Contour";
import { Board, IModeling } from "../../DatabaseServices/Entity/Board";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Line } from "../../DatabaseServices/Entity/Line";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { HardwareCompositeEntity } from '../../DatabaseServices/Hardware/HardwareCompositeEntity';
import { Shape } from "../../DatabaseServices/Shape";
import { ShapeManager } from "../../DatabaseServices/ShapeManager";
import { Route } from "../../Geometry/CurveMap";
import { GetSideFaceMtx } from "../../Geometry/DrillParse/BoardGetFace";
import { isParallelTo, angleTo, XAxis, MoveMatrix } from "../../Geometry/GeUtils";
import { RegionParse, Route } from "../../Geometry/RegionParse";
import { angleTo, isParallelTo, MoveMatrix, XAxis } from "../../Geometry/GeUtils";
import { RegionParse } from "../../Geometry/RegionParse";
import { Production } from "../../Production/Product";
import { FaceDirection } from "../../UI/Store/BoardInterface";
import { BoolOpeartionType, isTargetCurInOrOnSourceCur } from "../BoolOperateUtils";
import { OptimizeToolPath, GetCurveToInDir, GetOffsetCurves } from "./OptimizeToolPath";
import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole";
import { Production } from "../../Production/Product";
import { HardwareCompositeEntity } from '../../DatabaseServices/Hardware/HardwareCompositeEntity';
import { GetSealedBoardContour } from "../CalcEdgeSealing";
import { GetCurveToInDir, GetOffsetCurves, OptimizeToolPath } from "./OptimizeToolPath";
/**
*
@ -292,13 +293,11 @@ export class FeedingToolPath extends Singleton
let regParse = new RegionParse(expCus);
//分析封闭包围区域
const parseRoute = (routeSet: Set<Route>[]) =>
const parseRoute = (routeSet: Array<Route>[]) =>
{
for (let routes of routeSet)
{
let cs: Curve[] = [];
for (let r of routes)
cs.push(r.curve);
let cs: Curve[] = routes.map(r => r.curve);
let c = Contour.CreateContour(cs, false);
if (c && c.Area > 1e-3)
cons.push(c);

Loading…
Cancel
Save