!737 相交输出交点和参数

pull/737/MERGE
ZoeLeeFZ 5 years ago committed by ChenX
parent 0c58a2da7d
commit cad71af247

@ -15,7 +15,14 @@ function testBrSealing(br: Board, sealingSize: number[])
for (let i = 0; i < calcCus.length; i++)
{
let cu = calcCus[i];
offsetCus.push(...cu.GetOffsetCurves(sealingSize[i] * dir));
let cs = cu.GetOffsetCurves(sealingSize[i] * dir);
for (let c of cs)
{
if (c instanceof Polyline)
offsetCus.push(...c.Explode());
else
offsetCus.push(c);
}
}
CalcEdgeSealing(offsetCus);
let pl = new Polyline();

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`丢失线段板件 1`] = `538651.2759963807`;
exports[`丢失线段板件 1`] = `554052.5007766786`;
exports[`丢失线段板件 2`] = `398758.87896958226`;
@ -16,13 +16,13 @@ exports[`异型板件,常规坐标系 2`] = `2682243.4048994216`;
exports[`异型板件,常规坐标系 3`] = `2660261.4833081043`;
exports[`异型板件,常规坐标系 4`] = `2628158.6443366623`;
exports[`异型板件,常规坐标系 4`] = `2628158.6443366613`;
exports[`异型板件,常规坐标系 5`] = `2603082.551922609`;
exports[`异型板件,常规坐标系 5`] = `2603082.551922608`;
exports[`异型板件,非常规坐标系 1`] = `75939516.39226122`;
exports[`异型板件,非常规坐标系 1`] = `75939516.39226124`;
exports[`异型板件,非常规坐标系 2`] = `75863286.03232267`;
exports[`异型板件,非常规坐标系 2`] = `75863286.03232269`;
exports[`异型板件,非常规坐标系 3`] = `75694680.60847881`;

@ -2,61 +2,93 @@
exports[`三维空间圆圆相交测试 1`] = `
Array [
Vector3 {
Object {
"argParam": 0.4536333241402826,
"pt": Vector3 {
"x": 3.8465654731285666,
"y": -0.48984005103149847,
"z": 0.3777515851723183,
},
Vector3 {
"thisParam": 0.7716603782612834,
},
Object {
"argParam": 0.24200297426269035,
"pt": Vector3 {
"x": 4.518686772594938,
"y": -2.26435797895917,
"z": -0.09066385360916496,
},
"thisParam": 0.9239759201416895,
},
]
`;
exports[`三维空间圆圆相交测试 2`] = `
Array [
Vector3 {
Object {
"argParam": 0.7097846883724168,
"pt": Vector3 {
"x": 1.25,
"y": -4.841229182759271,
"z": 0,
},
Vector3 {
"thisParam": 0.7902153116275832,
},
Object {
"argParam": 0.29021531162758313,
"pt": Vector3 {
"x": 1.25,
"y": 4.841229182759271,
"z": 0,
},
"thisParam": 0.2097846883724169,
},
]
`;
exports[`三维空间圆圆相交测试 3`] = `
Array [
Vector3 {
Object {
"argParam": 0.7097846883724168,
"pt": Vector3 {
"x": 1.25,
"y": 0,
"z": -4.841229182759271,
},
Vector3 {
"thisParam": 0.7902153116275832,
},
Object {
"argParam": 0.29021531162758313,
"pt": Vector3 {
"x": 1.25,
"y": 0,
"z": 4.841229182759271,
},
"thisParam": 0.2097846883724169,
},
]
`;
exports[`三维空间圆圆相交测试 4`] = `
Array [
Vector3 {
Object {
"argParam": -0.6390032202422545,
"pt": Vector3 {
"x": 0,
"y": -11.313088368701884,
"z": -9.556275638274851,
},
Vector3 {
"thisParam": 1.734018071788813,
},
Object {
"argParam": 0.27309309551812694,
"pt": Vector3 {
"x": 0,
"y": -9.579281670837858,
"z": -2.8986776905615708,
},
"thisParam": 0.8053579264405307,
},
]
`;

@ -81,9 +81,9 @@ export class TestIntersect implements Command
{
cus[0].ColorIndex = 7;
cus[1].ColorIndex = 7;
pt.forEach(p =>
pt.forEach(({ pt }) =>
{
let cir = new Circle(p, 0.1);
let cir = new Circle(pt, 0.1);
cir.ColorIndex = 2;
app.Database.ModelSpace.Append(cir);
});

@ -11,7 +11,7 @@ import { CurveMap } from '../Geometry/CurveMap';
import { ZeroVec, equaln, equalv2, equalv3, isParallelTo, AsVector3, AsVector2 } from '../Geometry/GeUtils';
import { PlaneExt } from '../Geometry/Plane';
import { Stand } from '../Geometry/RegionParse';
import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { IntersectOption, IntersectResult } from '../GraphicsSystem/IntersectWith';
import { arrayLast, changeArrayStartIndex, equalArray } from './ArrayExt';
import { OffsetPolyline } from '../GraphicsSystem/OffsetPolyline';
import { FixIndex } from './Utils';
@ -585,3 +585,14 @@ export function MergeCurvelist(cus: Curve[])
}
return cus;
}
export function SwapParam(res: IntersectResult[])
{
for (let r of res)
{
let p = r.thisParam;
r.thisParam = r.argParam;
r.argParam = p;
}
return res;
}

@ -192,7 +192,7 @@ export class Contour
let sourceOutline = this._Curve;
let targetOutline = target.Curve;
let interPts = sourceOutline.IntersectWith(targetOutline, IntersectOption.OnBothOperands);
let interPts = sourceOutline.IntersectWith2(targetOutline, IntersectOption.OnBothOperands);
let sourceContainerTarget = this.CuInOutline(targetOutline);
let targetContainerSource = target.CuInOutline(sourceOutline);
@ -214,8 +214,8 @@ export class Contour
}
else//相交 interPts.length > 0
{
let pars1 = interPts.map(p => sourceOutline.GetParamAtPoint(p));
let pars2 = interPts.map(p => targetOutline.GetParamAtPoint(p));
let pars1 = interPts.map(r => r.thisParam);
let pars2 = interPts.map(r => r.argParam);
let sourceCus: Array<Polyline | Arc> = sourceOutline.GetSplitCurves(pars1);
let targetCus: Array<Polyline | Arc> = targetOutline.GetSplitCurves(pars2);
@ -285,7 +285,7 @@ export class Contour
let sourceOutline = this._Curve as Polyline;
let targetOutline = target.Curve as Polyline;
let interPts = sourceOutline.IntersectWith(targetOutline, IntersectOption.OnBothOperands, 1e-3);
let interPts = sourceOutline.IntersectWith2(targetOutline, IntersectOption.OnBothOperands, 1e-3);
if (interPts.length <= 1)
{
@ -301,8 +301,8 @@ export class Contour
//相交
let subtractList: Curve[] = [];
let sourceCus = sourceOutline.GetSplitCurvesByPts(interPts) as Polyline[];
let targetCus = targetOutline.GetSplitCurvesByPts(interPts) as 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)
{

@ -15,6 +15,7 @@ import { Curve } from './Curve';
import { Line } from './Line';
import { Polyline } from './Polyline';
import { Ellipse } from './Ellipse';
import { SwapParam } from './../../Common/CurveUtils';
/**
*
@ -447,7 +448,7 @@ export class Arc extends Curve
return this;
}
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[]
IntersectWith2(curve: Curve, intType: IntersectOption)
{
if (curve instanceof Arc)
{
@ -455,17 +456,17 @@ export class Arc extends Curve
}
if (curve instanceof Line)
{
return IntersectLineAndArc(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectLineAndArc(curve, this, reverseIntersectOption(intType)));
}
if (curve instanceof Circle)
{
return IntersectCircleAndArc(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectCircleAndArc(curve, this, reverseIntersectOption(intType)));
}
if (curve instanceof Polyline)
return IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType)));
if (curve instanceof Ellipse)
return IntersectEllipseAndCircleOrArc(curve, this, intType);
return SwapParam(IntersectEllipseAndCircleOrArc(curve, this, intType));
return [];
}

@ -17,6 +17,7 @@ import { DragPointType } from './DragPointType';
import { Ellipse } from './Ellipse';
import { Line } from './Line';
import { Polyline } from './Polyline';
import { SwapParam } from './../../Common/CurveUtils';
let circleGeometry: BufferGeometry;
function GetCircleGeometry()
@ -199,7 +200,7 @@ export class Circle extends Curve
{
return equaln(pt.distanceToSquared(this.Center), this._Radius * this._Radius, 1e-5);
}
GetOffsetCurves(offsetDist: number)
GetOffsetCurves(offsetDist: number): Curve[]
{
if ((offsetDist + this._Radius) > 0)
{
@ -210,7 +211,7 @@ export class Circle extends Curve
return [];
}
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[]
IntersectWith2(curve: Curve, intType: IntersectOption)
{
if (curve instanceof Arc)
{
@ -218,7 +219,7 @@ export class Circle extends Curve
}
if (curve instanceof Line)
{
return IntersectLineAndCircle(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectLineAndCircle(curve, this, reverseIntersectOption(intType)));
}
if (curve instanceof Circle)
{
@ -226,10 +227,10 @@ export class Circle extends Curve
}
if (curve instanceof Ellipse)
{
return IntersectEllipseAndCircleOrArc(curve, this, intType);
return SwapParam(IntersectEllipseAndCircleOrArc(curve, this, intType));
}
if (curve instanceof Polyline)
return IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType)));
return [];
}
//******************** Curve function end*****************//

@ -3,7 +3,7 @@ import { arrayRemoveDuplicateBySort, arraySortByNumber } from '../../Common/Arra
import { ColorMaterial } from '../../Common/ColorPalette';
import { Status } from '../../Common/Status';
import { equaln, equalv3 } from '../../Geometry/GeUtils';
import { IntersectOption } from '../../GraphicsSystem/IntersectWith';
import { IntersectOption, IntersectResult } from '../../GraphicsSystem/IntersectWith';
import { RenderType } from '../../GraphicsSystem/RenderType';
import { Factory } from '../CADFactory';
import { DragPointType } from './DragPointType';
@ -153,13 +153,18 @@ export abstract class Curve extends Entity
GetClosestPointTo(pt: Vector3, extend: boolean): Vector3 { return; }
/**
* 线
*
* @param {Curve} curve
* @returns {Vector3[]}
* @memberof Curve
* 线
*/
IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-6): Vector3[]
{
return this.IntersectWith2(curve, intType, tolerance).map(r => r.pt);
}
/**
* 线
*/
IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-6): Vector3[] { return []; }
IntersectWith2(curve: Curve, intType: IntersectOption, tolerance = 1e-6): IntersectResult[] { return []; }
/**
*

@ -14,6 +14,7 @@ import { Circle } from './Circle';
import { Curve } from './Curve';
import { Line } from './Line';
import { Polyline } from './Polyline';
import { SwapParam } from './../../Common/CurveUtils';
@Factory
export class Ellipse extends Curve
@ -449,12 +450,12 @@ export class Ellipse extends Curve
return [];
}
}
IntersectWith(curve: Curve, intType: IntersectOption): Vector3[]
IntersectWith2(curve: Curve, intType: IntersectOption)
{
//TODO:优化椭圆和椭圆,椭圆和圆相交
if (curve instanceof Line)
{
return IntersectEllipseAndLine(curve, this, reverseIntersectOption(intType));
return SwapParam(IntersectEllipseAndLine(curve, this, reverseIntersectOption(intType)));
}
else if (curve instanceof Circle || curve instanceof Arc)
{
@ -462,7 +463,7 @@ export class Ellipse extends Curve
}
else if (curve instanceof Polyline)
{
return IntersectPolylineAndCurve(curve, this, intType);
return SwapParam(IntersectPolylineAndCurve(curve, this, intType));
}
else if (curve instanceof Ellipse)
{

@ -15,6 +15,7 @@ import { Circle } from './Circle';
import { Curve } from './Curve';
import { Polyline } from './Polyline';
import { Ellipse } from './Ellipse';
import { SwapParam } from './../../Common/CurveUtils';
@Factory
export class Line extends Curve
@ -155,7 +156,7 @@ export class Line extends Curve
return this.EndPoint.sub(this.StartPoint);
}
IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-4): Vector3[]
IntersectWith2(curve: Curve, intType: IntersectOption, tolerance = 1e-4)
{
if (curve instanceof Line)
{
@ -171,7 +172,7 @@ export class Line extends Curve
}
if (curve instanceof Polyline)
{
return IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType), tolerance);
return SwapParam(IntersectPolylineAndCurve(curve, this, reverseIntersectOption(intType), tolerance));
}
if (curve instanceof Ellipse)

@ -1067,7 +1067,7 @@ export class Polyline extends Curve
return curve;
}
IntersectWith(curve: Curve, intType: IntersectOption, tolerance = 1e-5): Vector3[]
IntersectWith2(curve: Curve, intType: IntersectOption, tolerance = 1e-5)
{
return IntersectPolylineAndCurve(this, curve, intType, tolerance);
}

@ -33,6 +33,14 @@ export enum IntersectOption
*/
ExtendBoth = 3,
}
export interface IntersectResult
{
pt: Vector3,
thisParam: number,
argParam: number,
}
//延伸自身还是参数反转
export function reverseIntersectOption(intType: IntersectOption)
{
@ -46,28 +54,27 @@ export function reverseIntersectOption(intType: IntersectOption)
*
* 线,
*
* @param {Vector3[]} intPts .线
* @param {Vector3[]} intRes .线
* @param {Curve} c1 线1 this
* @param {Curve} c2 线2 arg
* @param {Intersect} extType .
* @returns {Array<Vector3>}
*/
function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: IntersectOption, tolerance = 1e-6): Array<Vector3>
function CheckPointOnCurve(intRes: IntersectResult[], c1: Curve, c2: Curve, extType: IntersectOption, tolerance = 1e-6): Array<IntersectResult>
{
return intPts.filter(p =>
return intRes.filter(r =>
{
if (!(extType & IntersectOption.ExtendThis))
if (!c1.PtOnCurve3(p, tolerance))
if (!c1.PtOnCurve3(r.pt, tolerance))
return false;
if (!(extType & IntersectOption.ExtendArg))
if (!c2.PtOnCurve3(p, tolerance))
if (!c2.PtOnCurve3(r.pt, tolerance))
return false;
return true;
});
}
export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc): IntersectResult[]
{
if (!cu1.IsCoplaneTo(cu2)) return [];
@ -79,7 +86,7 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
let radius1 = cu1.Radius;
let radius2 = cu2.Radius;
let pts: Vector3[] = [];
let pts: IntersectResult[] = [];
let dist = center2.distanceTo(center1);
if (dist < Math.abs(radius1 - radius2)
@ -111,9 +118,17 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
p1.applyMatrix4(c1Ocs);
p2.applyMatrix4(c1Ocs);
pts.push(p1);
pts.push({
pt: p1,
thisParam: cu1.GetParamAtPoint(p1),
argParam: cu2.GetParamAtPoint(p1),
});
if (!equalv3(p1, p2))//防止点重复
pts.push(p2);
pts.push({
pt: p2,
thisParam: cu1.GetParamAtPoint(p2),
argParam: cu2.GetParamAtPoint(p2),
});
return pts;
}
@ -161,12 +176,12 @@ export function IntersectEllipseAndLine(l: Line, el: Ellipse, extType: Intersect
* @param {(Circle | Arc)} circle
* @returns
*/
function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc): IntersectResult[]
{
let lineOrg = line.StartPoint;
let lineDirection = line.EndPoint.sub(lineOrg);
let dirLen = lineDirection.length();
if (dirLen === 0) return [];
if (equaln(dirLen, 0)) return [];
lineDirection.divideScalar(dirLen);
let diff = lineOrg.clone().sub(circle.Center);
@ -176,14 +191,30 @@ function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
if (equaln(discr, 0, 1e-7))
{
return [lineOrg.add(lineDirection.multiplyScalar(-a1))];
let pt = lineOrg.add(lineDirection.multiplyScalar(-a1));
return [{
pt,
thisParam: -a1 / dirLen,
argParam: circle.GetParamAtPoint(pt)
}];
}
else if (discr > 0)
{
let root = Math.sqrt(discr);
let p1 = lineOrg.clone().add(lineDirection.clone().multiplyScalar(-a1 + root));
let p2 = lineOrg.add(lineDirection.multiplyScalar(-a1 - root));
return [
lineOrg.clone().add(lineDirection.clone().multiplyScalar(-a1 + root)),
lineOrg.add(lineDirection.multiplyScalar(-a1 - root))
{
pt: p1,
thisParam: (-a1 + root) / dirLen,
argParam: circle.GetParamAtPoint(p1)
}, {
pt: p2,
thisParam: (-a1 - root) / dirLen,
argParam: circle.GetParamAtPoint(p2)
}
];
}
return [];
@ -287,7 +318,7 @@ function ShortestLine3AndLine3(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector
}
//直线和直线
export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption, fuzz = 1e-4): Vector3[]
export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption, fuzz = 1e-4): IntersectResult[]
{
// if (l1.Is2D && l2.Is2D)
// {
@ -321,20 +352,23 @@ export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOptio
))
return [];
return [pt];
return [{
pt,
thisParam: param1,
argParam: param2
}];
}
export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption, tolerance = 1e-6): Vector3[]
export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: IntersectOption, tolerance = 1e-6): IntersectResult[]
{
let cus: Curve[] = pl.Explode();
let cus2: Curve[];
if (cu instanceof Polyline)
cus2 = cu.Explode();
else
cus2 = [cu];
let pts: Vector3[] = [];
let intRes: IntersectResult[] = [];
for (let i = 0; i < cus.length; i++)
{
@ -356,7 +390,7 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2))
ext = ext & ~IntersectOption.ExtendArg;
let ipts = cu1.IntersectWith(cu2, ext, tolerance).filter(p1 => pts.every(p2 => !equalv3(p1, p2)));
let ptPars = cu1.IntersectWith2(cu2, ext, tolerance).filter(r1 => intRes.every(r2 => !equalv3(r1.pt, r2.pt)));
//校验延伸
if (IntersectOption.ExtendThis & ext)
@ -367,11 +401,11 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
}
else if (isStart)
{
ipts = ipts.filter(p => cu1.GetParamAtPoint(p) <= 1);
ptPars = ptPars.filter(res => res.thisParam <= 1);
}
else if (isEnd)
{
ipts = ipts.filter(p => cu1.GetParamAtPoint(p) >= 0);
ptPars = ptPars.filter(res => res.thisParam >= 0);
}
}
if (IntersectOption.ExtendArg & ext)
@ -382,20 +416,27 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte
}
else if (isStart2)
{
ipts = ipts.filter(p => cu2.GetParamAtPoint(p) <= cu2.EndParam);
ptPars = ptPars.filter(res => res.argParam + j <= cu2.EndParam);
}
else if (isEnd2)
{
ipts = ipts.filter(p => cu2.GetParamAtPoint(p) >= 0);
ptPars = ptPars.filter(res => res.argParam + j >= 0);
}
}
pts.push(...ipts);
intRes.push(...ptPars.map(r =>
{
return {
pt: r.pt,
thisParam: pl.GetParamAtPoint(r.pt),
argParam: cu.GetParamAtPoint(r.pt),
}
}));
}
pts.sort(comparePoint("xyz"));
arrayRemoveDuplicateBySort(pts, equalv3);
return pts;
}
intRes.sort((r1, r2) => comparePoint("xyz")(r1.pt, r2.pt));
arrayRemoveDuplicateBySort(intRes, (r1, r2) => equalv3(r1.pt, r2.pt));
return intRes;
}
export function IntersectLineAndEllipseFor2D(l: Line, el: Ellipse)
@ -455,7 +496,15 @@ export function IntersectLineAndEllipseFor2D(l: Line, el: Ellipse)
}
let matInv = new Matrix4().getInverse(mat);
return pts.map(p => p.applyMatrix4(matInv));
return pts.map(p =>
{
let pt = p.applyMatrix4(matInv);
return {
pt,
thisParam: l.GetParamAtPoint(pt),
argParam: el.GetParamAtPoint(pt)
}
});
}
export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, type: IntersectOption)
{
@ -506,8 +555,16 @@ export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, t
];
}
let ro = new Matrix4().makeRotationZ(el.Rotation);
pts = pts.map(p => p.applyMatrix4(ro).applyMatrix4(el.OCS));
return CheckPointOnCurve(pts, el, cir, type);
let res = pts.map(p =>
{
let pt = p.applyMatrix4(ro).applyMatrix4(el.OCS)
return {
pt,
thisParam: el.GetParamAtPoint(pt),
argParam: cir.GetParamAtPoint(pt)
}
});
return CheckPointOnCurve(res, el, cir, type);
}
else
{
@ -525,7 +582,8 @@ export function IntersectEllipseAndCircleOrArc(el: Ellipse, cir: Circle | Arc, t
type = IntersectOption.OnBothOperands;
let intPts = IntersectPolylineAndCurve(pl, cirClone, type);
return intPts.map(p => p.applyMatrix4(el.OCS));
intPts.forEach(r => r.pt.applyMatrix4(el.OCS));
return intPts;
}
}
export function IntersectEllipse(el1: Ellipse, el2: Ellipse, type: IntersectOption)
@ -568,6 +626,7 @@ export function IntersectEllipse(el1: Ellipse, el2: Ellipse, type: IntersectOpti
let pl1 = new Polyline(lineData1);
let pl2 = new Polyline(lineData2).ApplyMatrix(diffMat);
let intPts = pl1.IntersectWith(pl2, 0);
return intPts.map(p => p.applyMatrix4(el1.OCS));
let intPts = pl1.IntersectWith2(pl2, 0);
intPts.forEach(r => r.pt.applyMatrix4(el1.OCS));
return intPts;
}

Loading…
Cancel
Save