优化点在多段线内部的算法,使算法更健壮,避免圆弧切线问题.

pull/68/head
ChenX 6 years ago
parent 91dc5f8a01
commit 32f8807a59

@ -1,12 +1,9 @@
import { Vector2, Vector3 } from 'three'; import { Vector2, Vector3 } from 'three';
import { angle, equal, equaln, greater } from '../Geometry/GeUtils'; import { angle, equaln } from '../Geometry/GeUtils';
import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { Arc } from './Arc'; import { Arc } from './Arc';
import { Circle } from './Circle';
import { Line } from './Line'; import { Line } from './Line';
import { Polyline } from './Polyline'; import { Polyline } from './Polyline';
import { Contour } from './Contour';
/** /**
* ,. * ,.
@ -73,33 +70,72 @@ export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean
for (let i = 0; i < pl.EndParam; i++) for (let i = 0; i < pl.EndParam; i++)
{ {
let cu = pl.GetCurveAtIndex(i); if (equaln(pl.GetBuilgeAt(i), 0))//直线
let inpts = cu.IntersectWith(insLine, IntersectOption.ExtendArg);
for (let pti of inpts)
{ {
if (pti.y < pt.y) let sp = pl.GetPointAtParam(i);
let ep = pl.GetPointAtParam(i + 1);
//点位于线上面
if (pt.y > Math.max(sp.y, ep.y))
continue;
//线垂直Y轴
let derX = ep.x - sp.x;
if (equaln(derX, 0))
continue; continue;
if (equal(pti, cu.StartPoint)) //起点
if (equaln(sp.x, pt.x))
{ {
let der = cu.GetFistDeriv(0); if (sp.y > pt.y && derX < 0) crossings++;
if (equaln(der.x, 0) && cu instanceof Arc) continue;
der = cu.GetFistDeriv(0.1);
if (der.x < -1e-4) //左边+ 右边0
crossings++;
} }
else if (equal(pti, cu.EndPoint)) //终点
if (equaln(ep.x, pt.x))
{
if (ep.y > pt.y && derX > 0) crossings++;
continue;
}
//快速求交,只验证有没有交点
let [x1, x2] = sp.x > ep.x ? [ep.x, sp.x] : [sp.x, ep.x];
if (pt.x > x1 && pt.x < x2)
{ {
let der = cu.GetFistDeriv(1); let derY = ep.y - sp.y;
if (equaln(der.x, 0) && cu instanceof Arc) let k = derY / derX;
der = cu.GetFistDeriv(0.9);
if (der.x > 1e-4) //左边+ 右边0 if ((pt.x - sp.x) * k + sp.y > pt.y)
crossings++; crossings++;
} }
else }
else //圆弧
{
let arc = pl.GetCurveAtIndex(i);
let sp = arc.StartPoint;
let ep = arc.EndPoint;
//当点和起点或者终点和点相切时
if (equaln(sp.x, pt.x) && sp.y > pt.y)
{
let der = arc.GetFistDeriv(0);
if (equaln(der.x, 0))
{
if (ep.x - sp.x < 0) crossings++;
continue;
}
}
if (equaln(ep.x, pt.x) && ep.y > pt.y)
{
let der = arc.GetFistDeriv(1);
if (equaln(der.x, 0))
{
if (ep.x - sp.x > 0) crossings++;
continue;
}
}
for (let pti of arc.IntersectWith(insLine, IntersectOption.ExtendArg))
{ {
let der = cu.GetFistDeriv(pti); if (pti.y < pt.y)
continue;
let der = arc.GetFistDeriv(pti);
if (!equaln(der.x, 0)) //相切. if (!equaln(der.x, 0)) //相切.
crossings++; crossings++;
} }

Loading…
Cancel
Save