diff --git a/src/DatabaseServices/PointInPolyline.ts b/src/DatabaseServices/PointInPolyline.ts index 77a4a6cf2..b0cdd5ba2 100644 --- a/src/DatabaseServices/PointInPolyline.ts +++ b/src/DatabaseServices/PointInPolyline.ts @@ -1,4 +1,4 @@ -import { Vector2, Vector3 } from 'three'; +import { Vec2, Vector3 } from 'three'; import { angle, equaln, equalv3 } from '../Geometry/GeUtils'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Arc } from './Entity/Arc'; @@ -8,9 +8,9 @@ import { Polyline } from './Entity/Polyline'; /** * 点在扇形内部,提供一个简单实现的版本. * 优化版本请参照:http://www.cnblogs.com/miloyip/archive/2013/04/19/3029852.html - * + * * @param arc 二维圆弧 - * @param pt + * @param pt * @returns 点在扇形内部. */ function IsPointInCircularSector(arc: Arc, pt: Vector3): boolean @@ -25,7 +25,7 @@ function IsPointInCircularSector(arc: Arc, pt: Vector3): boolean /** * 点在弓型内部 - * + * * @param arc 二维圆弧 * @param pt 点 * @param isInChrodIsTrue 当点在弦上也认为在弓形内部 @@ -156,12 +156,12 @@ export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean /** * 点在区域内部 - * - * @param pt - * @param pts - * @returns + * + * @param pt + * @param pts + * @returns */ -function IsPointInPolygon(pt: Vector3, pts: Vector2[]) +export function IsPointInPolygon(pt: Vec2, pts: Vec2[]) { let crossings = 0; //int let [px, py] = [pt.x, pt.y]; diff --git a/src/DatabaseServices/Text/FontExt.ts b/src/DatabaseServices/Text/FontExt.ts index 349ea15e1..4f63d3269 100644 --- a/src/DatabaseServices/Text/FontExt.ts +++ b/src/DatabaseServices/Text/FontExt.ts @@ -1,4 +1,7 @@ -import { Font, ShapePath } from "three"; +import { Font, Path, Shape, ShapePath, Vector2 } from "three"; +import { arrayPushArray } from "../../Common/ArrayExt"; +import { Area } from "../../Nest/Core/Path"; +import { IsPointInPolygon } from "../PointInPolyline"; //修改threejs源代码,支持空格. @@ -6,12 +9,10 @@ export class FontExt extends Font { generateShapes(text: string, size: number = 100) { - let shapes = []; + let shapes: Shape[] = []; let paths = createPaths(text, size, this.data); - for (let p = 0, pl = paths.length; p < pl; p++) - { - Array.prototype.push.apply(shapes, paths[p].toShapes()); - } + for (let p of paths) + arrayPushArray(shapes, p.toShapes(false)); return shapes; } } @@ -20,7 +21,7 @@ function createPaths(text: string, size: number, data: any) let scale = size / data.resolution; let line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale; - let paths = []; + let paths: ShapePath[] = []; let offsetX = 0, offsetY = 0; @@ -47,13 +48,13 @@ function createPaths(text: string, size: number, data: any) } return paths; } -function createPath(char: string, scale: number, offsetX: number, offsetY: number, data: any) +function createPath(char: string, scale: number, offsetX: number, offsetY: number, data: any): { offsetX: number, path: ShapePath; } { let glyph = data.glyphs[char] || data.glyphs['?']; if (!glyph) return; - let path = new ShapePath(); + let path = new ShapePathExt(); let x: number, y: number, cpx: number, cpy: number, cpx1: number, cpy1: number, cpx2: number, cpy2: number; @@ -120,3 +121,92 @@ function createPath(char: string, scale: number, offsetX: number, offsetY: numbe return { offsetX: glyph.ha * scale, path: path }; } + +class PathData extends Path +{ + area: number; + area2: number;//正 + pts: Vector2[]; + + parent: PathData; + children: PathData[]; +} + +function GetPathDepth(p: PathData): number +{ + let depth = 0; + let parent = p.parent; + while (parent) + { + depth++; + parent = parent.parent; + } + return depth; +} + +function GetPathIsHole(p: PathData): boolean +{ + return GetPathDepth(p) % 2 === 1; +} + +/** + * 重载这个类 以便我们能正确的分析层级关系 修复在yahei字体中 "图圆" 渲染错误的问题 + */ +class ShapePathExt extends ShapePath +{ + toShapes(isCCW = false, noHoles = false): Shape[] + { + let paths = this.subPaths as PathData[]; + for (let path of paths) + { + let pts = path.getPoints(); + let area = Area(pts); + let area2 = Math.abs(area); + + path.area = area; + path.area2 = area2; + path.pts = pts; + } + + paths.sort((p1, p2) => p1.area2 - p2.area2);//从小到大 + + let count = paths.length; + for (let i = 0; i < count; i++) + { + let p1 = paths[i]; + for (let j = i + 1; j < count; j++) + { + let p2 = paths[j]; + if (IsPointInPolygon(p1.pts[0], p2.pts)) + { + p1.parent = p2; + if (!p2.children) p2.children = []; + p2.children.push(p1); + break; + } + } + } + + let shapes: Shape[] = []; + + for (let p of paths) + { + if (GetPathIsHole(p)) continue; + + let s = new Shape(); + s.curves = p.curves; + + if (p.children) + for (let pc of p.children) + { + let sc = new Shape(); + sc.curves = pc.curves; + + s.holes.push(sc); + } + + shapes.push(s); + } + return shapes; + } +} diff --git a/src/Editor/SelectBase.ts b/src/Editor/SelectBase.ts index ce7a70c3a..c80bed6ff 100644 --- a/src/Editor/SelectBase.ts +++ b/src/Editor/SelectBase.ts @@ -176,7 +176,7 @@ export class SelectSetBase { pts.push(pt.clone().applyMatrix4(obj.matrixWorld)); } - faces.push(...geo.faces); + arrayPushArray(faces, geo.faces);//例如:在选择Text对象时(Text里面有非常多的文字,选择时崩溃) 经过测试 .prototype.push.apply 这个也崩 } else if (geo instanceof BufferGeometry) {