fix #IR8AN 直线Join允许更高的容差值,轮廓布尔移除0面积的轮廓,

pull/240/MERGE
ChenX 6 years ago
parent d0ed94884d
commit df5ed02401

@ -17,3 +17,19 @@ test("#IRFL2面域消失", () =>
reg.BooleanOper(regs[1], BoolOpeartionType.Intersection);
expect(reg.ShapeManager.ShapeList.length).toBe(1);
});
test('#IR8AN交集错误', () =>
{
let data =
[2, "Region", 2, 1, 104, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 111.34512004857766, 13.95089482226993, 0, 1], 0, 1, 1, 1, 1, "Polyline", 2, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 111.34512004857766, 13.95089482226993, 0, 1], 0, 2, 4, [-97.39422719143477, -0.0000019651270122267306], 0, [674.3281411676799, -0.0000019651270122267306], 0, [674.3281421679894, 1199.9999984537135], 0, [-97.3942261911252, 1199.9999984537135], 0, true, 0, "Region", 2, 1, 105, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 13.95089285714289, 113.95089285714292, 0, 1], 0, 1, 1, 1, 1, "Polyline", 2, 1, 0, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 13.95089285714289, 113.95089285714292, 0, 1], 0, 2, 13, [314.3387826639938, -99.99999883531063], 0, [318, -100], 0, [318, 0], 0, [579.5436603415255, 67.84500522108829], 0, [530.3246820683962, 361.2662670472655], 0, [446.27460696874186, 251.38290037066872], 0, [495.4935852418712, 1057.9616385444915], 0, [151.43841386299755, 1055.5264270248226], 0, [151.43841386299755, 155.52640117119142], 0, [0, 200], 0, [0, 0], 0, [140.39432277924786, -16.215571265653125], 0, [140.3943227792479, -100], 0, true, 0]
let regs: Region[] = LoadRegionsFromFileData(data);
expect(regs.length).toBe(2);
let reg = regs[0].Clone();
reg.BooleanOper(regs[1], BoolOpeartionType.Subtract);
expect(reg.ShapeManager.ShapeList.length).toBe(2);
reg = regs[0].Clone();
reg.BooleanOper(regs[1], BoolOpeartionType.Intersection);
expect(reg.ShapeManager.ShapeList.length).toBe(1);
});

@ -1,6 +1,7 @@
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
import { Polyline } from "../../src/DatabaseServices/Polyline";
import { equaln } from "../../src/Geometry/GeUtils";
import { Line } from "../../src/DatabaseServices/Line";
test('多段线与多段线Join', () =>
{
@ -40,3 +41,11 @@ test('多段线与多段线Join', () =>
expect(pl1.Join(pl2)).toBe(1);
expect(equaln(pl1.Length, length)).toBeTruthy();
});
test('一定精度容差内的直线Join', () =>
{
let data =
[2, "Line", 2, 1, 168, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -97.39422719143477, 40.30682517259278, 0, 1], 1, 1, [140.3943227792479, -100, 0], [314.3387826639938, -99.99999883531063, 0], "Line", 2, 1, 169, false, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -97.39422719143477, 40.30682517259278, 0, 1], 1, 1, [314.3387826639938, -99.99999883531063, 0], [318, -100, 0]]
let lines = LoadEntityFromFileData(data) as Line[];
expect(lines[0].Join(lines[1])).toBe(1);
});

@ -145,7 +145,7 @@ export class Contour
for (let r of routes)
cs.push(r.curve);
let c = Contour.Combine(cs, false);
if (!equalCurve(c, this.Curve) && !equalCurve(c, target.Curve))
if (!equalCurve(c, this.Curve) && !equalCurve(c, target.Curve) && c.Area > 1e-3)
cuGroups.push(cs);
}
}

@ -227,9 +227,9 @@ export class Line extends Curve
{
let sp = this.StartPoint;
let ep = this.EndPoint;
if (equalv3(pt, sp, 1e-12))
if (equalv3(pt, sp, 1e-8))
return { closestPt: sp, param: 0 };
else if (equalv3(pt, ep, 1e-12))
else if (equalv3(pt, ep, 1e-8))
return { closestPt: ep, param: 1 };
let direction = this.GetFistDeriv(0);
@ -238,7 +238,7 @@ export class Line extends Curve
if (length === 0)
{
let param = NaN;
if (equalv3(pt, this.StartPoint, 1e-7))
if (equalv3(pt, this.StartPoint, 1e-6))
param = 0;
return { closestPt: sp, param: param };
}
@ -292,11 +292,22 @@ export class Line extends Curve
{
if (cu instanceof Line)
{
//如果不平行
if (!isParallelTo(this.GetFistDeriv(0), cu.GetFistDeriv(0)))
//平行
if (!isParallelTo(this.GetFistDeriv(0).normalize(), cu.GetFistDeriv(0).normalize()))
return Status.False;
let [param1, param2] = arraySortByNumber([this.GetParamAtPoint(cu.StartPoint), this.GetParamAtPoint(cu.EndPoint)]);
let sp = cu.StartPoint;
let { closestPt: cp1, param: param1 } = this.GetClosestAtPoint(sp, true);
if (!equalv3(sp, cp1, 1e-5))//点在曲线上,允许较低的精度
return;
let ep = cu.EndPoint;
let { closestPt: cp2, param: param2 } = this.GetClosestAtPoint(ep, true);
if (!equalv3(ep, cp2, 1e-5))
return;
if (param1 > param2)
[param1, param2] = [param2, param1];
if (allowGap || Math.max(0, param1) < Math.min(1, param2) + 1e-5)
{

@ -1,7 +1,6 @@
import { Box3, Vector3 } from "three";
import { Curve } from "../DatabaseServices/Curve";
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
import { greater } from "./GeUtils";
/**
*
@ -46,9 +45,9 @@ export class CurveIntersection
//过滤掉不需要计算的曲线
let c2b = this.boxMap.get(c2);
if (greater(c2b.min.x, c1b.max.x, 1e-6))
if (c2b.min.x - c1b.max.x > 1e-6)
break;
if (greater(c2b.min.y, c1b.max.y, 1e-6))
if (c2b.min.y - c1b.max.y > 1e-6)
continue;
let pts = c1.IntersectWith(c2, IntersectOption.OnBothOperands);

@ -1,7 +1,6 @@
import * as THREE from 'three';
import { Box3, BufferGeometry, Geometry, Matrix4, Vector, Vector2, Vector3, BufferAttribute } from 'three';
import { Matrix2 } from './Matrix2';
import { Box3, BufferGeometry, Geometry, Matrix4, Object3D, Vector, Vector2, Vector3, Line, Mesh } from 'three';
import { ToFixed } from '../Common/Utils';
import { Matrix2 } from './Matrix2';
export const cZeroVec = new Vector3();
export const cXAxis = new Vector3(1, 0, 0);
@ -35,15 +34,6 @@ export function equalv2(v1: Vector2, v2: Vector2, fuzz = 1e-8)
return equaln(v1.x, v2.x, fuzz) && equaln(v1.y, v2.y, fuzz);
}
export function less(v1, v2, fuzz = 0)
{
return v1 - v2 < fuzz;
}
export function greater(v1, v2, fuzz = 0)
{
return v1 - v2 > fuzz;
}
/**
*
*
@ -72,21 +62,21 @@ export function angle(v: Vector3 | Vector2)
/**
* ,,
*
* @param {THREE.Vector3} v1
* @param {THREE.Vector3} v2
* @param {THREE.Vector3} [ref] ,0,0,1
* @param {Vector3} v1
* @param {Vector3} v2
* @param {Vector3} [ref] ,0,0,1
* @returns
*/
export function angleTo(v1: THREE.Vector3, v2: THREE.Vector3, ref: THREE.Vector3 = new THREE.Vector3(0, 0, 1))
export function angleTo(v1: Vector3, v2: Vector3, ref: Vector3 = new Vector3(0, 0, 1))
{
if (!ref.equals(new Vector3(0, 0, 1)))
{
//任意轴坐标系. 使用相机的构造矩阵.
ref.multiplyScalar(-1);
let up = getLoocAtUpVec(ref);
let refOcs = new THREE.Matrix4();
let refOcs = new Matrix4();
refOcs.lookAt(cZeroVec, ref, up);
let refOcsInv = new THREE.Matrix4().getInverse(refOcs);
let refOcsInv = new Matrix4().getInverse(refOcs);
v1.applyMatrix4(refOcsInv);
v2.applyMatrix4(refOcsInv);
v1.z = 0;
@ -98,7 +88,7 @@ export function angleTo(v1: THREE.Vector3, v2: THREE.Vector3, ref: THREE.Vector3
return cv.z === 0 ? v1.angleTo(v2) : v1.angleTo(v2) * cv.z;
}
export function getLoocAtUpVec(dir: THREE.Vector3): THREE.Vector3
export function getLoocAtUpVec(dir: Vector3): Vector3
{
if (dir.equals(cZeroVec))
{
@ -107,53 +97,49 @@ export function getLoocAtUpVec(dir: THREE.Vector3): THREE.Vector3
let norm = dir.clone().normalize();
if (norm.equals(cZAxis))
{
return new THREE.Vector3(0, 1, 0);
return new Vector3(0, 1, 0);
}
else if (norm.equals(cZAxis.clone().negate()))
{
return new THREE.Vector3(0, -1, 0);
return new Vector3(0, -1, 0);
}
else
{
let xv: THREE.Vector3 = new THREE.Vector3();
let xv: Vector3 = new Vector3();
xv.crossVectors(cZAxis, norm);
let up = new THREE.Vector3();
let up = new Vector3();
up.crossVectors(norm, xv);
return up;
}
}
export function createLookAtMat4(dir: THREE.Vector3): THREE.Matrix4
export function createLookAtMat4(dir: Vector3): Matrix4
{
let up = getLoocAtUpVec(dir);
let mat = new THREE.Matrix4();
let mat = new Matrix4();
mat.lookAt(cZeroVec, dir, up);
return mat;
}
/**
* 2.
* @export
* @param {THREE.Vector3} v1
* @param {THREE.Vector3} v2
* @returns
* 2,,
*/
export function isParallelTo(v1: THREE.Vector3, v2: THREE.Vector3): boolean
export function isParallelTo(v1: Vector3, v2: Vector3): boolean
{
return v1.clone().cross(v2).lengthSq() < 1e-9;
return v1.clone().cross(v2).lengthSq() < 1e-8;
}
export function ptToString(v: THREE.Vector3, fractionDigits: number = 3): string
export function ptToString(v: Vector3, fractionDigits: number = 3): string
{
return v.toArray().map(o => ToFixed(o, fractionDigits)).join(",");
}
export function midPoint(v1: THREE.Vector3, v2: THREE.Vector3): THREE.Vector3
export function midPoint(v1: Vector3, v2: Vector3): Vector3
{
return v1.clone().add(v2).multiplyScalar(0.5);
}
export function midPoint2(v1: THREE.Vector2, v2: THREE.Vector2): THREE.Vector2
export function midPoint2(v1: Vector2, v2: Vector2): Vector2
{
return v1.clone().add(v2).multiplyScalar(0.5);
}
@ -164,7 +150,7 @@ export function midPoint2(v1: THREE.Vector2, v2: THREE.Vector2): THREE.Vector2
* @param [updateMatrix]
* @returns box
*/
export function GetBox(obj: THREE.Object3D, updateMatrix?: boolean): THREE.Box3
export function GetBox(obj: Object3D, updateMatrix?: boolean): Box3
{
let box = new Box3();
if (updateMatrix) obj.updateMatrixWorld(false);
@ -189,7 +175,7 @@ export function GetBox(obj: THREE.Object3D, updateMatrix?: boolean): THREE.Box3
return box;
}
export function GetBoxArr(arr: Array<THREE.Object3D>): THREE.Box3
export function GetBoxArr(arr: Array<Object3D>): Box3
{
let box = new Box3();
for (let o of arr)
@ -257,9 +243,9 @@ export function angleTo2Pi(an: number)
if (an < 0) an += Math.PI * 2
return an;
}
export function updateGeometry(l: THREE.Line | THREE.Mesh, geometry: Geometry | BufferGeometry)
export function updateGeometry(l: Line | Mesh, geometry: Geometry | BufferGeometry)
{
let geo = l.geometry as THREE.Geometry;
let geo = l.geometry as Geometry;
geo.dispose();
l.geometry = geometry;
geometry.computeBoundingSphere();

Loading…
Cancel
Save