mirror of https://gitee.com/cf-fz/WebCAD.git
parent
3e62adc4ce
commit
4d424fba59
@ -0,0 +1,144 @@
|
|||||||
|
import { Vector2, Vector3 } from 'three';
|
||||||
|
|
||||||
|
import { IsPointInPolyLine } from '../../src/DatabaseServices/PointInPolyline';
|
||||||
|
import { Polyline } from '../../src/DatabaseServices/Polyline';
|
||||||
|
|
||||||
|
|
||||||
|
test('点在多段线内', () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
let pl = new Polyline([
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(8, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(8, 5),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(4, 5),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(4, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
pl.CloseMark = true;
|
||||||
|
|
||||||
|
let bIn = IsPointInPolyLine(pl, new Vector3(8, 3));//?
|
||||||
|
|
||||||
|
expect(bIn).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("", () =>
|
||||||
|
{
|
||||||
|
test('退化', () =>
|
||||||
|
{
|
||||||
|
let pl = new Polyline(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(5, 5),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
pl.CloseMark = true;
|
||||||
|
|
||||||
|
expect(IsPointInPolyLine(pl, new Vector3(5, 2))).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('退化2', () =>
|
||||||
|
{
|
||||||
|
//右边中间 <
|
||||||
|
let pl = new Polyline(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(5, 5),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
pl.CloseMark = true;
|
||||||
|
|
||||||
|
expect(IsPointInPolyLine(pl, new Vector3(5, 2))).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('左边中间', () =>
|
||||||
|
{
|
||||||
|
//左边中间
|
||||||
|
let pl = new Polyline([
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 0),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(10, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 10),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pt: new Vector2(0, 8),
|
||||||
|
bul: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
pt: new Vector2(5, 5),
|
||||||
|
bul: 0
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
pl.CloseMark = true;
|
||||||
|
|
||||||
|
expect(IsPointInPolyLine(pl, new Vector3(5, 2))).toBeTruthy();
|
||||||
|
});
|
||||||
|
})
|
@ -0,0 +1,39 @@
|
|||||||
|
import { Command } from "../Editor/CommandMachine";
|
||||||
|
import { app } from '../ApplicationServices/Application';
|
||||||
|
import { PromptStatus } from "../Editor/PromptResult";
|
||||||
|
import { Box3, Vector3 } from "three";
|
||||||
|
import { Circle } from '../DatabaseServices/Circle';
|
||||||
|
import { IsPointInPolyLine } from "../DatabaseServices/PointInPolyline";
|
||||||
|
import { Polyline } from '../DatabaseServices/Polyline';
|
||||||
|
|
||||||
|
|
||||||
|
export class Command_PtInCu implements Command
|
||||||
|
{
|
||||||
|
async exec()
|
||||||
|
{
|
||||||
|
let cuRes = await app.m_Editor.GetEntity();
|
||||||
|
if (cuRes.Status != PromptStatus.OK)
|
||||||
|
return;
|
||||||
|
if (!(cuRes.Entity instanceof Polyline))
|
||||||
|
{ return }
|
||||||
|
|
||||||
|
let p1Res = await app.m_Editor.GetPoint();
|
||||||
|
if (p1Res.Status != PromptStatus.OK) return;
|
||||||
|
let p2Res = await app.m_Editor.GetPoint({ BasePoint: p1Res.Value });
|
||||||
|
if (p2Res.Status != PromptStatus.OK) return;
|
||||||
|
|
||||||
|
let box = new Box3().setFromPoints([p1Res.Value, p2Res.Value]);
|
||||||
|
let size = box.getSize();
|
||||||
|
for (let i = 0; i < size.x; i++)
|
||||||
|
{
|
||||||
|
for (let j = 0; j < size.y; j++)
|
||||||
|
{
|
||||||
|
let c = new Circle(box.min.clone().add(new Vector3(i, j)), 0.5);
|
||||||
|
|
||||||
|
c.ColorIndex = IsPointInPolyLine(cuRes.Entity as Polyline, c.Center) ? 1 : 2;
|
||||||
|
|
||||||
|
app.m_Database.ModelSpace.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,154 @@
|
|||||||
|
import { Vector2, Vector3 } from 'three';
|
||||||
|
|
||||||
|
import { angle, equal, equaln } from '../Geometry/GeUtils';
|
||||||
|
import { IntersectOption } from '../GraphicsSystem/IntersectWith';
|
||||||
|
import { Arc } from './Arc';
|
||||||
|
import { Line } from './Line';
|
||||||
|
import { Polyline } from './Polyline';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点在扇形内部,提供一个简单实现的版本.
|
||||||
|
* 优化版本请参照:http://www.cnblogs.com/miloyip/archive/2013/04/19/3029852.html
|
||||||
|
*
|
||||||
|
* @param {Arc} arc 二维圆弧
|
||||||
|
* @param {Vector3} pt
|
||||||
|
* @returns {boolean} 点在扇形内部.
|
||||||
|
*/
|
||||||
|
function IsPointInCircularSector(arc: Arc, pt: Vector3): boolean
|
||||||
|
{
|
||||||
|
let center = arc.Center;
|
||||||
|
let disSq = center.distanceTo(pt);
|
||||||
|
if (disSq > arc.Radius * arc.Radius) return false;
|
||||||
|
let an = angle(pt.clone().sub(center));
|
||||||
|
let param = arc.GetParamAtAngle(an);
|
||||||
|
return arc.ParamOnCurve(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点在弓型内部
|
||||||
|
*
|
||||||
|
* @param {Arc} arc 二维圆弧
|
||||||
|
* @param {Vector3} pt 点
|
||||||
|
* @returns {boolean} 点在内部
|
||||||
|
*/
|
||||||
|
export function IsPointInBowArc(arc: Arc, pt: Vector3): boolean
|
||||||
|
{
|
||||||
|
let pv = pt.clone().sub(arc.StartPoint);
|
||||||
|
let av = arc.EndPoint.sub(arc.StartPoint);
|
||||||
|
|
||||||
|
pv.cross(av);
|
||||||
|
|
||||||
|
//未优化的代码
|
||||||
|
// if (pv.z > 0 && arc.IsClockWise)
|
||||||
|
// return false;
|
||||||
|
// else if (pv.z < 0 && !arc.IsClockWise)
|
||||||
|
// return false;
|
||||||
|
// else
|
||||||
|
// return arc.Center.distanceToSquared(pt) < arc.Radius * arc.Radius;
|
||||||
|
|
||||||
|
//简化的代码
|
||||||
|
if ((pv.z > 0) !== arc.IsClockWise)
|
||||||
|
{
|
||||||
|
return arc.Center.distanceToSquared(pt) < arc.Radius * arc.Radius;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断点在多段线内外
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {Polyline} pl 多段线
|
||||||
|
* @param {Vector3} pt 点
|
||||||
|
* @returns {boolean} 点在多段线内部
|
||||||
|
*/
|
||||||
|
export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean
|
||||||
|
{
|
||||||
|
let crossings = 0;
|
||||||
|
|
||||||
|
let insLine = new Line(pt, pt.clone().add(new Vector3(0, 10, 0)));
|
||||||
|
|
||||||
|
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 (pti.y < pt.y)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (equal(pti, cu.StartPoint))
|
||||||
|
{
|
||||||
|
let der = cu.GetFistDeriv(0);
|
||||||
|
if (der.x < 1e-3) //左边+ 右边0
|
||||||
|
crossings++;
|
||||||
|
}
|
||||||
|
else if (equal(pti, cu.EndPoint))
|
||||||
|
{
|
||||||
|
let der = cu.GetFistDeriv(1);
|
||||||
|
if (der.x > 1e-3) //左边+ 右边0
|
||||||
|
crossings++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let der = cu.GetFistDeriv(pti);
|
||||||
|
if (!equaln(der.x, 0)) //相切.
|
||||||
|
crossings++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (crossings % 2) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点在区域内部
|
||||||
|
*
|
||||||
|
* @param {Vector3} pt
|
||||||
|
* @param {Vector2[]} pts
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function IsPointInPolygon(pt: Vector3, pts: Vector2[])
|
||||||
|
{
|
||||||
|
let crossings = 0; //int
|
||||||
|
let [px, py] = [pt.x, pt.y];
|
||||||
|
|
||||||
|
let ptCout = pts.length;
|
||||||
|
for (let i = 0; i < ptCout; i++)
|
||||||
|
{
|
||||||
|
let pti = pts[i];
|
||||||
|
let ptn = pts[(i + 1) % ptCout];
|
||||||
|
|
||||||
|
let [x1, x2] = [pti.x, ptn.x];
|
||||||
|
|
||||||
|
/* This is done to ensure that we get the same result when
|
||||||
|
the line goes from left to right and right to left */
|
||||||
|
if (x1 > x2)[x1, x2] = [x2, x1];
|
||||||
|
|
||||||
|
/* First check if the ray is possible to cross the line */
|
||||||
|
if (px > x1 && px <= x2 && (py < pti.y || py <= ptn.y))
|
||||||
|
{
|
||||||
|
const eps = 0.000001;
|
||||||
|
|
||||||
|
/* Calculate the equation of the line */
|
||||||
|
let dx = ptn.x - pti.x;
|
||||||
|
let dy = ptn.y - pti.y;
|
||||||
|
let k;
|
||||||
|
|
||||||
|
if (Math.abs(dx) < eps)
|
||||||
|
k = 1e300;
|
||||||
|
else
|
||||||
|
k = dy / dx;
|
||||||
|
|
||||||
|
let m = pti.y - k * pts[i].x;
|
||||||
|
|
||||||
|
/* Find if the ray crosses the line */
|
||||||
|
let y2 = k * px + m;
|
||||||
|
if (py <= y2)
|
||||||
|
crossings++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crossings % 2 === 1;
|
||||||
|
}
|
Loading…
Reference in new issue