!230 fix #IQ937 修正面域差集在特殊相交时的结果

pull/230/MERGE
ChenX 6 years ago
parent 4410d7c4a8
commit 33d85acd70

@ -134,6 +134,29 @@ test("有交点时", () =>
expect(regs[1].Explode().length).toBe(2);
});
//#IQ937
test.only('特殊相交', () =>
{
testSubtract(
[2, "Region", 1, 1, 13, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2147.1101515831265, -2428.922411894075, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2147.1101515831265, -2428.922411894075, 0, 1], 2, 8, [286.3247863247866, -182.3361823361823], 0, [5.698005698005659, -192.3076923076923], 0, [-207.97720797720808, -166.66666666666663], 0, [-215.09971509971524, 45.584045584045604], 0, [-215.09971509971524, 313.39031339031345], 0, [52.70655270655277, 274.92877492877494], 0, [293.44729344729353, 250.71225071225066], 0, [286.3247863247866, 18.518518518518544], 0, true, 0, "Region", 1, 1, 12, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2147.1101515831265, -2428.922411894075, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2147.1101515831265, -2428.922411894075, 0, 1], 2, 4, [286.3247863247866, 18.518518518518544], 0, [5.698005698005659, -192.3076923076923], 0, [-215.09971509971524, 45.584045584045604], 0, [52.70655270655277, 274.92877492877494], 0, true, 0]
, 4);
testSubtract(
[2, "Region", 1, 1, 7, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -165.24216524216527, -477.2079772079772, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -165.24216524216527, -477.2079772079772, 0, 1], 2, 4, [0, 0], 0, [600, 0], 0, [600, 1200], 0, [0, 1200], 0, true, 0, "Region", 1, 1, 8, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -165.24216524216527, -477.2079772079772, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -165.24216524216527, -477.2079772079772, 0, 1], 2, 17, [260.68452291480645, 694.8814057850639], 0, [268.61637170569537, 691.99444892248], 0, [569.9719350514073, 582.3099939341178], 0, [563.8155724715452, 565.3955267599715], 0, [262.46000912583327, 675.0799817483337], 0, [244.5953021712127, 681.582203323704], 0, [234.37028331333872, 685.3038058327808], 0, [-5.684341886080802e-14, 599.9999989101887], 0, [-6.156362579862105, 616.9144660843351], 0, [208.05604371187087, 694.881405785064], 0, [0, 770.6076127553729], 0, [6.156362579862048, 787.5220799295191], 0, [234.37028331333858, 704.4590057373472], 0, [245.7073243841179, 708.5853512317643], 0, [247.65394027111975, 709.2938614721828], 0, [557.659209066764, 822.1265517794905], 0, [563.815571646626, 805.212084605344], 0, true, 0]
, 2);
testSubtract(
[2, "Region", 1, 1, 63, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 2, 5, [4456.332258552945, -1732.8363833524356], 0, [4915.293761397059, -1732.8363833524356], 0, [4915.293761397059, -1334.2078480183466], 0, [4456.332258552945, -1334.2078480183466], 0, [4456.332258552945, -1732.8363833524356], 0, true, 0, "Region", 1, 1, 64, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, 1, 1, 1, "Polyline", 1, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 2, 4, [4456.332258552945, -1533.522115685391], 0, [4685.8130099750015, -1334.2078480183466], 0, [4915.293761397059, -1533.522115685391], 0, [4685.8130099750015, -1732.8363833524356], 0, true, 0]
, 4);
});
function testSubtract(data, count)
{
let regs = LoadRegionsFromFileData(data);
regs[0].BooleanOper(regs[1], BoolOpeartionType.Subtract);
let expregs = regs[0].Explode();
expect(expregs.length).toBe(count);
}
function testRegion(reg)
{
if (reg)
@ -200,5 +223,4 @@ function testRegionsBool(regs, uShapeCount, uHoleCount, iShapeCount, iHoleCount,
expect(holeCount2).toBe(iHoleCount);
expect(shapeCount3).toBe(sShapeCount);
expect(holeCount3).toBe(sHoleCount);
}

@ -86,7 +86,7 @@ export function arrayRemoveDuplicateBySort<T>(arr: Array<T>, checkFuction: (e1:
if (arr.length < 2) return arr;
let j = 1;
for (let i = 1, l = arr.length; i < l; i++)
if (!checkFuction(arr[i], arr[j - 1]))
if (!checkFuction(arr[j - 1], arr[i]))
arr[j++] = arr[i];
arr.length = j;
return arr;
@ -108,7 +108,7 @@ export function arrayRemoveDuplicateBySort2<T>(arr: Array<T>, checkFuction: (e1:
for (let i = 1, len = arr.length; i < len; i++)
{
now = arr[i];
if (!checkEqual(now, pre))
if (!checkFuction(pre, now))
{
newArr.push(now);
pre = now;
@ -143,7 +143,17 @@ function checkEqual(e1, e2): boolean
* @param arr
* @param index //将index位置以后的值放到起始位置
*/
export function changeArrayStartIndex(arr: any[], index: number)
export function changeArrayStartIndex<T>(arr: T[], index: number): T[]
{
arr.unshift(...arr.splice(index))
arr.unshift(...arr.splice(index));
return arr;
}
export function equalArray<T>(a: T[], b: T[], checkF = checkEqual)
{
if (a === b) return true;
if (a.length !== b.length) return false;
for (var i = 0; i < a.length; ++i)
if (!checkF(a[i], b[i])) return false;
return true;
}

@ -12,6 +12,7 @@ import { Stand } from '../Geometry/RegionParse';
import { FixIndex } from './Utils';
import { PlaneExt } from '../Geometry/Plane';
import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { arrayLast, changeArrayStartIndex, equalArray } from './ArrayExt';
//3点获取圆心
export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3)
@ -178,31 +179,41 @@ export function curveLinkGroup(cus: Curve[]): Array<Array<Curve>>
export function equalCurveAndCurve(cu1: Curve, cu2: Curve)
{
if (cu1.EndParam !== cu2.EndParam || !equaln(cu1.Length, cu2.Length)) return false;
let parAtPl2 = cu2.GetParamAtPoint(cu1.StartPoint);
if ((cu1 instanceof Polyline) && (cu2 instanceof Polyline))
{
let ptsAndBuls1 = cu1.PtsBuls;
let ptsAndBuls2 = cu2.PtsBuls;
// 判断凸度是否相等
let buls2 = ptsAndBuls2.buls.slice(parAtPl2);
buls2.push(...ptsAndBuls2.buls.slice(0, parAtPl2));
let isEqual = ptsAndBuls1.buls.every((bul, i) =>
{
return equaln(bul, buls2[i])
})
if (!isEqual) return false;
if (cu1.IsClose !== cu2.IsClose)
return false;
let ptsBuls1 = cu1.PtsBuls;
let ptsBuls2 = cu2.PtsBuls;
let pts2 = ptsAndBuls2.pts.slice(parAtPl2);
pts2.push(...ptsAndBuls2.pts.slice(0, parAtPl2));
let pts1 = ptsBuls1.pts;
let pts2 = ptsBuls2.pts;
let buls1 = ptsBuls1.buls;
let buls2 = ptsBuls2.buls;
return ptsAndBuls1.pts.every((pt, i) =>
if (cu1.IsClose && equalv2(pts1[0], arrayLast(pts1)))
{
pts1.pop();
buls1.pop();
}
if (cu2.IsClose && equalv2(pts2[0], arrayLast(pts2)))
{
return equalv3(
Vec2DTo3D(pt).applyMatrix4(cu1.OCS),
Vec2DTo3D(pts2[i]).applyMatrix4(cu2.OCS));
})
pts2.pop();
buls2.pop();
}
let parAtPl2 = cu2.GetParamAtPoint(cu1.StartPoint);
changeArrayStartIndex(buls2, parAtPl2);
changeArrayStartIndex(pts2, parAtPl2);
return equalArray(buls1, buls2, equaln) &&
equalArray(pts1, pts2, (p1: Vector2, p2: Vector2) =>
equalv3(
Vec2DTo3D(p1).applyMatrix4(cu1.OCS),
Vec2DTo3D(p2).applyMatrix4(cu2.OCS)
)
);
}
else if (cu1 instanceof Circle && cu2 instanceof Circle)
{
@ -211,7 +222,10 @@ export function equalCurveAndCurve(cu1: Curve, cu2: Curve)
else if (cu1 instanceof Arc && cu2 instanceof Arc)
{
if (!equalv3(cu1.StartPoint, cu2.EndPoint)) cu1.Reverse();
return equalv3(cu1.Center, cu2.Center) && equaln(cu1.Radius, cu2.Radius, 1e-6) && equaln(cu1.StartAngle, cu2.StartAngle) && equaln(cu1.EndAngle, cu2.EndAngle)
return equalv3(cu1.Center, cu2.Center)
&& equaln(cu1.Radius, cu2.Radius, 1e-6)
&& equaln(cu1.StartAngle, cu2.StartAngle)
&& equaln(cu1.EndAngle, cu2.EndAngle);
}
return false;
}

@ -1,14 +1,19 @@
import * as THREE from "three";
import { Vector3 } from "three";
import { curveLinkGroup, equalCurveAndCurve, Vec3DTo2D } from "../Common/CurveUtils";
import { FixIndex } from "../Common/Utils";
import { equaln, rotatePoint } from "../Geometry/GeUtils";
import { RegionParse, Route } from "../Geometry/RegionParse";
import { isTargetCurInOrOnSourceCur } from "../GraphicsSystem/BoolOperateUtils";
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
import { Arc } from "./Arc";
import { Circle } from "./Circle";
import { Curve } from "./Curve";
import { Polyline } from "./Polyline";
import { Vector3 } from "three";
import { FixIndex } from "../Common/Utils";
import { arrayRemoveDuplicateBySort } from "../Common/ArrayExt";
import { Status } from "../Common/Status";
let cache = new WeakMap();
export class Contour
{
@ -113,7 +118,29 @@ export class Contour
SubstactBoolOperation(target: Contour): Contour[]
{
let subtractList = this.getSubtractList(target);
//纯网洞
if (subtractList.every(c => c.IsClose))
return Contour.GetAllContour(subtractList);
let cuGroups: Curve[][] = [];
let regParse = new RegionParse(subtractList);
//分析封闭包围区域
const parseRoute = (routeSet: Set<Route>[]) =>
{
for (let routes of routeSet)
{
let cs: Curve[] = [];
for (let r of routes)
cs.push(r.curve);
let c = Contour.Combine(cs, false);
if (!equalCurveAndCurve(c, this.Curve) && !equalCurveAndCurve(c, target.Curve))
cuGroups.push(cs);
}
}
parseRoute(regParse.m_RegionsOutline);
parseRoute(regParse.m_RegionsInternal);
return Contour.GetAllContour(cuGroups);
}
/**
* 线.
@ -299,44 +326,44 @@ export class Contour
let contours: Contour[] = []
cuGroups.forEach(c =>
{
contours.push(Contour.CreateContour(c, false));
})
for (let g of cuGroups)
contours.push(Contour.CreateContour(g, false));
return contours.filter(c => c !== undefined && !equaln(c.Area, 0, 1e-6));
}
/**
* 线
*
* @param {Curve[]} cus
* @returns
* @memberof Polyline
* 线线
* @param cus 线
* @param [needLink=true]
* @returns 线,1,.
*/
static Combine(cus: Curve[], needLink = true): Curve
{
if (cus.length === 0) return undefined;
let groups = needLink ? curveLinkGroup(cus) : [cus];
let joinCus: Curve[] = [];
for (let g of groups)
{
if (g.length === 1)
{
joinCus.push(g[0].Clone() as Curve);
}
return g[0].Clone();
else
{
if (cache.has(g))
return cache.get(g)
let pl = new Polyline();
for (let cu of g)
{
let gclone = g.map(c => c.Clone());
arrayRemoveDuplicateBySort(gclone, (cu1: Curve, cu2: Curve) => cu1.Join(cu2) === Status.True);
for (let cu of gclone)
pl.Join(cu);
}
joinCus.push(pl);
cache.set(g, pl);
return pl;
}
}
return joinCus[0];
}
get Shape(): THREE.Shape
{

Loading…
Cancel
Save