暴露CurveWrap

This commit is contained in:
ChenX 2023-11-02 15:15:50 +08:00
parent 78b1c316da
commit 063a010609
11 changed files with 336 additions and 5 deletions

View File

@ -22972,6 +22972,151 @@ function PolylineFilletMinArc(pl, radius = 30) {
}
}
/** 点p到线段P1P2 的最短距离的平方,线段不延伸 */
function GetSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) //不是0长度线
{
let t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
}
else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function CrossVector2(a, b) {
return a.x * b.y - a.y * b.x;
}
//Ramer-Douglas-Peucker algorithm
function SimplifyDPStep(points, first, last, sqTolerance, simplified, offset) {
let maxSqDist = 0;
let index;
let fp = points[first];
let lp = points[last];
for (let i = first + 1; i < last; i++) {
let p = points[i];
let sqDist = GetSqSegDist(p, fp, lp);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
SimplifyDPStep(points, first, index, sqTolerance, simplified, offset);
simplified.push(points[index]);
if (last - index > 1)
SimplifyDPStep(points, index, last, sqTolerance, simplified, offset);
}
else {
//记录偏移
let v = new Vector2(lp.x - fp.x, lp.y - fp.y).normalize();
for (let i = first + 1; i < last; i++) {
let p = points[i];
let offsetDist = -CrossVector2(v, { x: p.x - fp.x, y: p.y - fp.y });
offset.positiveOffset = Math.max(offset.positiveOffset, offsetDist);
offset.negativeOffset = Math.min(offset.negativeOffset, offsetDist);
}
}
}
// Ramer-Douglas-Peucker 算法
function SimplifyDouglasPeucker(points, sqTolerance) {
let last = points.length - 1;
let simplified = [points[0]];
let offset = { negativeOffset: 0, positiveOffset: 0 };
SimplifyDPStep(points, 0, last, sqTolerance, simplified, offset);
simplified.push(points[last]);
return [simplified, offset];
}
/**
* 运用此代码将曲线转换为点,并且精简它.
* @class CurveWrap
*/
class CurveWrap {
constructor(Curve, KnifRadius = 3, IsOutside = true) {
this.Curve = Curve;
this.KnifRadius = KnifRadius;
this.IsOutside = IsOutside;
this.Used = false;
this.Holes = [];
this.BoundingBox = Curve.BoundingBox;
if (Curve instanceof exports.Polyline) {
let pts = Polyline2Points(Curve, IsOutside, 0)[1];
let [spts, offset] = SimplifyDouglasPeucker(pts, KnifRadius ** 2 + KnifRadius);
if (spts.length !== pts.length) {
this.SimplyOffset = offset;
this.SimplyPolyline = Path2Polyline(spts);
this.Curve = this.SimplyPolyline; //保险起见,也更新它
this.Area = this.SimplyPolyline.Area;
}
else //此处更新多段线
this.Curve = Path2Polyline(pts);
this.Points = spts;
}
if (this.Area === undefined)
this.Area = this.Curve.Area;
}
ContainsCurve(curve) {
if (this.SimplyPolyline)
return this.SimplyPolyline.PtInCurve(curve.Curve.StartPoint);
return this.Curve.PtInCurve(curve.Curve.StartPoint);
}
GetOutsidePoints() {
if (this.Curve instanceof exports.Circle) {
let pts = Circle2Points(this.Curve, this.KnifRadius, 10, true);
return pts;
}
else {
let pl = this.SimplyPolyline || this.Curve;
let offset = this.KnifRadius;
if (this.SimplyOffset)
offset += this.SimplyOffset.positiveOffset;
if (offset > 0) {
let pts = pl.GetStretchPoints();
pts = clipperCpp.lib.offsetToPaths({
delta: offset * 10000,
offsetInputs: [{ data: PathScale(pts, 10000), joinType: clipperLib.JoinType.Miter, endType: clipperLib.EndType.ClosedPolygon }]
})[0];
PathScale(pts, 0.0001);
return pts;
}
else
return this.Points;
}
}
GetInsidePoints() {
if (this.Curve instanceof exports.Circle) {
let pts = Circle2Points(this.Curve, this.KnifRadius, 10, false);
return pts;
}
else {
let pl = this.SimplyPolyline || this.Curve;
let offset = -this.KnifRadius;
if (this.SimplyOffset) {
offset += this.SimplyOffset.negativeOffset;
}
if (offset < -0.01) {
let pls = pl.GetOffsetCurves(offset);
if (pls.length)
return pls[0].GetStretchPoints();
}
else
return this.Points;
}
}
}
exports.BUL_IS_LINE_FUZZ = BUL_IS_LINE_FUZZ;
exports.CADFiler = CADFiler;
exports.Circle2Points = Circle2Points;
@ -22979,6 +23124,7 @@ exports.ComputeBiarc = ComputeBiarc;
exports.Contour = Contour;
exports.ConverToPolylineAndSplitArc = ConverToPolylineAndSplitArc;
exports.CurveContainerCurve = CurveContainerCurve;
exports.CurveWrap = CurveWrap;
exports.Curves2Points = Curves2Points;
exports.FeedingToolPath = FeedingToolPath;
exports.IsPtsAllOutOrOnReg = IsPtsAllOutOrOnReg;

File diff suppressed because one or more lines are too long

View File

@ -22963,5 +22963,150 @@ function PolylineFilletMinArc(pl, radius = 30) {
}
}
export { Arc, BUL_IS_LINE_FUZZ, BoolOpeartionType, CADFiler, Circle, Circle2Points, ComputeBiarc, Contour, ConverToPolylineAndSplitArc, CurveContainerCurve, Curves2Points, DuplicateRecordCloning, FeedingToolPath, IsPtsAllOutOrOnReg, IsRect, Line, ParseRegionTextPos, PointsSimplify2PolylineAndParseArc, Polyline, Polyline2Points, PolylineFilletMinArc, Production, Shape, ShapeManager, SmartPointsSimply2Polyline, SmartPolylineSimply2Polyline, SplineConver2Polyline, Status, TEXT_BOX, TempPolyline, UpdateDraw, VData2Curve, VKnifToolPath, fastCurveInCurve2, isTargetCurInOrOnSourceCur };
/** 点p到线段P1P2 的最短距离的平方,线段不延伸 */
function GetSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) //不是0长度线
{
let t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
}
else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function CrossVector2(a, b) {
return a.x * b.y - a.y * b.x;
}
//Ramer-Douglas-Peucker algorithm
function SimplifyDPStep(points, first, last, sqTolerance, simplified, offset) {
let maxSqDist = 0;
let index;
let fp = points[first];
let lp = points[last];
for (let i = first + 1; i < last; i++) {
let p = points[i];
let sqDist = GetSqSegDist(p, fp, lp);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
SimplifyDPStep(points, first, index, sqTolerance, simplified, offset);
simplified.push(points[index]);
if (last - index > 1)
SimplifyDPStep(points, index, last, sqTolerance, simplified, offset);
}
else {
//记录偏移
let v = new Vector2(lp.x - fp.x, lp.y - fp.y).normalize();
for (let i = first + 1; i < last; i++) {
let p = points[i];
let offsetDist = -CrossVector2(v, { x: p.x - fp.x, y: p.y - fp.y });
offset.positiveOffset = Math.max(offset.positiveOffset, offsetDist);
offset.negativeOffset = Math.min(offset.negativeOffset, offsetDist);
}
}
}
// Ramer-Douglas-Peucker 算法
function SimplifyDouglasPeucker(points, sqTolerance) {
let last = points.length - 1;
let simplified = [points[0]];
let offset = { negativeOffset: 0, positiveOffset: 0 };
SimplifyDPStep(points, 0, last, sqTolerance, simplified, offset);
simplified.push(points[last]);
return [simplified, offset];
}
/**
* 运用此代码将曲线转换为点,并且精简它.
* @class CurveWrap
*/
class CurveWrap {
constructor(Curve, KnifRadius = 3, IsOutside = true) {
this.Curve = Curve;
this.KnifRadius = KnifRadius;
this.IsOutside = IsOutside;
this.Used = false;
this.Holes = [];
this.BoundingBox = Curve.BoundingBox;
if (Curve instanceof Polyline) {
let pts = Polyline2Points(Curve, IsOutside, 0)[1];
let [spts, offset] = SimplifyDouglasPeucker(pts, KnifRadius ** 2 + KnifRadius);
if (spts.length !== pts.length) {
this.SimplyOffset = offset;
this.SimplyPolyline = Path2Polyline(spts);
this.Curve = this.SimplyPolyline; //保险起见,也更新它
this.Area = this.SimplyPolyline.Area;
}
else //此处更新多段线
this.Curve = Path2Polyline(pts);
this.Points = spts;
}
if (this.Area === undefined)
this.Area = this.Curve.Area;
}
ContainsCurve(curve) {
if (this.SimplyPolyline)
return this.SimplyPolyline.PtInCurve(curve.Curve.StartPoint);
return this.Curve.PtInCurve(curve.Curve.StartPoint);
}
GetOutsidePoints() {
if (this.Curve instanceof Circle) {
let pts = Circle2Points(this.Curve, this.KnifRadius, 10, true);
return pts;
}
else {
let pl = this.SimplyPolyline || this.Curve;
let offset = this.KnifRadius;
if (this.SimplyOffset)
offset += this.SimplyOffset.positiveOffset;
if (offset > 0) {
let pts = pl.GetStretchPoints();
pts = clipperCpp.lib.offsetToPaths({
delta: offset * 10000,
offsetInputs: [{ data: PathScale(pts, 10000), joinType: JoinType.Miter, endType: EndType.ClosedPolygon }]
})[0];
PathScale(pts, 0.0001);
return pts;
}
else
return this.Points;
}
}
GetInsidePoints() {
if (this.Curve instanceof Circle) {
let pts = Circle2Points(this.Curve, this.KnifRadius, 10, false);
return pts;
}
else {
let pl = this.SimplyPolyline || this.Curve;
let offset = -this.KnifRadius;
if (this.SimplyOffset) {
offset += this.SimplyOffset.negativeOffset;
}
if (offset < -0.01) {
let pls = pl.GetOffsetCurves(offset);
if (pls.length)
return pls[0].GetStretchPoints();
}
else
return this.Points;
}
}
}
export { Arc, BUL_IS_LINE_FUZZ, BoolOpeartionType, CADFiler, Circle, Circle2Points, ComputeBiarc, Contour, ConverToPolylineAndSplitArc, CurveContainerCurve, CurveWrap, Curves2Points, DuplicateRecordCloning, FeedingToolPath, IsPtsAllOutOrOnReg, IsRect, Line, ParseRegionTextPos, PointsSimplify2PolylineAndParseArc, Polyline, Polyline2Points, PolylineFilletMinArc, Production, Shape, ShapeManager, SmartPointsSimply2Polyline, SmartPolylineSimply2Polyline, SplineConver2Polyline, Status, TEXT_BOX, TempPolyline, UpdateDraw, VData2Curve, VKnifToolPath, fastCurveInCurve2, isTargetCurInOrOnSourceCur };
//# sourceMappingURL=api.esm.js.map

File diff suppressed because one or more lines are too long

26
types/Nest/Converter/CurveWrap.d.ts vendored Normal file
View File

@ -0,0 +1,26 @@
import { Box3 } from "three";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Point } from "../Common/Point";
import { IOffset } from "./Simplify2";
/**
* 线,.
* @class CurveWrap
*/
export declare class CurveWrap {
Curve: Polyline | Circle;
KnifRadius: number;
IsOutside: boolean;
BoundingBox: Box3;
Area: number;
SimplyPolyline: Polyline;
SimplyOffset: IOffset;
Used: boolean;
Holes: CurveWrap[];
Points: Point[];
constructor(Curve: Polyline | Circle, KnifRadius?: number, IsOutside?: boolean);
ContainsCurve(curve: CurveWrap): boolean;
GetOutsidePoints(): Point[];
GetInsidePoints(): Point[];
}
//# sourceMappingURL=CurveWrap.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"CurveWrap.d.ts","sourceRoot":"","sources":["../../../../src/Nest/Converter/CurveWrap.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAElE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAIxC,OAAO,EAAE,OAAO,EAA0B,MAAM,aAAa,CAAC;AAG9D;;;GAGG;AACH,qBAAa,SAAS;IAaC,KAAK,EAAE,QAAQ,GAAG,MAAM;IAAS,UAAU;IAAa,SAAS,EAAE,OAAO;IAX7F,WAAW,EAAE,IAAI,CAAC;IAElB,IAAI,EAAE,MAAM,CAAC;IAEb,cAAc,EAAE,QAAQ,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,UAAS;IACb,KAAK,EAAE,SAAS,EAAE,CAAM;IAExB,MAAM,EAAE,KAAK,EAAE,CAAC;gBAEG,KAAK,EAAE,QAAQ,GAAG,MAAM,EAAS,UAAU,SAAI,EAAS,SAAS,GAAE,OAAc;IAwBpG,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAOxC,gBAAgB,IAAI,KAAK,EAAE;IA+B3B,eAAe,IAAI,KAAK,EAAE;CA2B7B"}

View File

@ -9,7 +9,7 @@ export declare function Circle2Points(circle: Circle, knifRadius: number, splitS
export declare function Curves2Points(cu: Circle | Polyline, outside: boolean, knifeRadius: number): [(Circle | Polyline), Point[]];
export declare function Polyline2Points(pl: Polyline, outside: boolean, knifeRadius: number): [Polyline, Point[]];
/**
* ,使
* ,使( )
* @param pl 线(线, )
* @param [radius=30]
*/

11
types/Nest/Converter/Simplify2.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
interface P {
x: number;
y: number;
}
export interface IOffset {
negativeOffset: number;
positiveOffset: number;
}
export declare function SimplifyDouglasPeucker(points: P[], sqTolerance: number): [P[], IOffset];
export {};
//# sourceMappingURL=Simplify2.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Simplify2.d.ts","sourceRoot":"","sources":["../../../../src/Nest/Converter/Simplify2.ts"],"names":[],"mappings":"AAEA,UAAU,CAAC;IAEP,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,OAAO;IAEpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CAC1B;AA0ED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAQvF"}

1
types/api.d.ts vendored
View File

@ -15,5 +15,6 @@ export * from "./DatabaseServices/Contour";
export * from "./DatabaseServices/Shape";
export * from "./DatabaseServices/ShapeManager";
export * from "./Nest/Converter/Curves2Points";
export * from "./Nest/Converter/CurveWrap";
export * from "./Common/Status";
//# sourceMappingURL=api.d.ts.map

View File

@ -1 +1 @@
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,cAAc,yCAAyC,CAAC;AACxD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yDAAyD,CAAC;AACxE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC"}
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,cAAc,yCAAyC,CAAC;AACxD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wCAAwC,CAAC;AACvD,cAAc,yDAAyD,CAAC;AACxE,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC"}