diff --git a/src/DatabaseServices/PointInPolyline.ts b/src/DatabaseServices/PointInPolyline.ts index b13a62e62..b3e4bf2a7 100644 --- a/src/DatabaseServices/PointInPolyline.ts +++ b/src/DatabaseServices/PointInPolyline.ts @@ -1,12 +1,9 @@ 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 { Arc } from './Arc'; -import { Circle } from './Circle'; import { Line } from './Line'; 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++) { - let cu = pl.GetCurveAtIndex(i); - let inpts = cu.IntersectWith(insLine, IntersectOption.ExtendArg); - - for (let pti of inpts) + if (equaln(pl.GetBuilgeAt(i), 0))//直线 { - 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; - if (equal(pti, cu.StartPoint)) + //起点 + if (equaln(sp.x, pt.x)) { - let der = cu.GetFistDeriv(0); - if (equaln(der.x, 0) && cu instanceof Arc) - der = cu.GetFistDeriv(0.1); - if (der.x < -1e-4) //左边+ 右边0 - crossings++; + if (sp.y > pt.y && derX < 0) crossings++; + continue; } - 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); - if (equaln(der.x, 0) && cu instanceof Arc) - der = cu.GetFistDeriv(0.9); - if (der.x > 1e-4) //左边+ 右边0 + let derY = ep.y - sp.y; + let k = derY / derX; + + if ((pt.x - sp.x) * k + sp.y > pt.y) 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)) //相切. crossings++; }