!67 三维空间相交和切割

Merge pull request !67 from ZoeLeeFZ/3DTo2D_pr
pull/767481/MERGE
ChenX 6 years ago
parent 6cbe7a5d39
commit 50aaabeed9

@ -1,5 +1,151 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`三维空间圆圆相交测试 1`] = `
Array [
Vector3 {
"x": 3.8465654731285666,
"y": -0.4898400510314999,
"z": 0.3777515851723181,
},
Vector3 {
"x": 4.518686772594937,
"y": -2.2643579789591692,
"z": -0.09066385360916451,
},
]
`;
exports[`三维空间圆圆相交测试 2`] = `
Array [
Vector3 {
"x": 1.25,
"y": -4.841229182759271,
"z": 0,
},
Vector3 {
"x": 1.25,
"y": 4.841229182759271,
"z": 0,
},
]
`;
exports[`三维空间圆圆相交测试 3`] = `
Array [
Vector3 {
"x": 1.25,
"y": 0,
"z": -4.841229182759271,
},
Vector3 {
"x": 1.25,
"y": 0,
"z": 4.841229182759271,
},
]
`;
exports[`三维空间圆圆相交测试 4`] = `
Array [
Vector3 {
"x": 0,
"y": -11.313088368701884,
"z": -9.556275638274851,
},
Vector3 {
"x": 0,
"y": -9.579281670837858,
"z": -2.8986776905615708,
},
]
`;
exports[`三维空间圆圆相交测试 5`] = `Array []`;
exports[`三维空间直线和圆相交测试 1`] = `
Array [
Vector3 {
"x": 7.265045456946408,
"y": 0,
"z": 1.514708484572001,
},
Vector3 {
"x": 3.93574588263578,
"y": 0,
"z": 4.789429377336553,
},
]
`;
exports[`三维空间直线和圆相交测试 2`] = `
Array [
Vector3 {
"x": -3.622627029705465,
"y": -3.4462404738565997,
"z": 0,
},
Vector3 {
"x": -3.622627029705464,
"y": 3.4462404738566006,
"z": 0,
},
]
`;
exports[`三维空间直线和圆相交测试 3`] = `
Array [
Vector3 {
"x": 9.796270630192112,
"y": -13.16305455920182,
"z": 4.841809080303142,
},
Vector3 {
"x": 9.796270630192113,
"y": -6.270573611488618,
"z": 4.841809080303142,
},
]
`;
exports[`三维空间直线和圆相交测试 4`] = `
Array [
Vector3 {
"x": 12.384261138056765,
"y": -13.163054559201814,
"z": 6.346016491847222,
},
Vector3 {
"x": 12.384261138056765,
"y": -6.270573611488626,
"z": 6.346016491847221,
},
]
`;
exports[`三维空间直线相交测试 1`] = `
Vector3 {
"x": 5,
"y": 5,
"z": 5,
}
`;
exports[`三维空间直线相交测试 2`] = `
Vector3 {
"x": 4.75,
"y": 4.75,
"z": 4.75,
}
`;
exports[`三维空间直线相交测试 3`] = `
Vector3 {
"x": 5,
"y": 5,
"z": 5,
}
`;
exports[`相交测试 1`] = ` exports[`相交测试 1`] = `
Vector3 { Vector3 {
"x": 0.5, "x": 0.5,

@ -1,6 +1,12 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { IntersectLAndL } from '../../src/GraphicsSystem/IntersectWith'; import { IntersectLAndLFor3D, IntersectCircleAndCircle, IntersectOption } from '../../src/GraphicsSystem/IntersectWith';
import { Vector3 } from 'three';
import { CADFile } from '../../src/DatabaseServices/CADFile';
import { Curve } from '../../src/DatabaseServices/Curve';
import { Circle } from '../../src/DatabaseServices/Circle';
import { Arc } from '../../src/DatabaseServices/Arc';
import { Line } from '../../src/DatabaseServices/Line';
test('相交测试', () => test('相交测试', () =>
{ {
@ -12,19 +18,102 @@ test('相交测试', () =>
let p5 = new THREE.Vector3(3, 0, 0); let p5 = new THREE.Vector3(3, 0, 0);
let p6 = new THREE.Vector3(6, 0, 0); let p6 = new THREE.Vector3(6, 0, 0);
let res = IntersectLAndL(p1, p2, p3, p4);/*?*/ let res = IntersectLAndLFor3D(p1, p2, p3, p4);/*?*/
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
res = IntersectLAndL(p1, p2, p5, p6);/*?*/ res = IntersectLAndLFor3D(p1, p2, p5, p6);/*?*/
expect(res).toMatchSnapshot(); expect(res).toMatchSnapshot();
let ins = IntersectLAndL( let ins = IntersectLAndLFor3D(
new THREE.Vector3(0, 5), new THREE.Vector3(0, 5),
new THREE.Vector3(5, 5), new THREE.Vector3(5, 5),
new THREE.Vector3(0.5, 1), new THREE.Vector3(0.5, 1),
new THREE.Vector3(0.5, 8)); new THREE.Vector3(0.5, 8));
expect(ins).toMatchSnapshot(); expect(ins).toMatchSnapshot();
} })
test('三维空间直线相交测试', () =>
{
let p1 = new THREE.Vector3();
let p2 = new THREE.Vector3(10, 10, 10);
let p3 = new THREE.Vector3(5, 5, 5);
let p4 = new THREE.Vector3(5, 10, 5);
let p5 = new THREE.Vector3(3, 3, 3);
let p6 = new THREE.Vector3(6, 6, 6);
let res = IntersectLAndLFor3D(p1, p2, p3, p4);/*?*/
expect(res).toMatchSnapshot();
res = IntersectLAndLFor3D(p1, p2, p5, p6);/*?*/
expect(res).toMatchSnapshot();
res = IntersectLAndLFor3D(p2, p6, p3, p4);/*?*/
expect(res).toMatchSnapshot();
res = IntersectLAndLFor3D(
new Vector3(1, 1, 1),
new Vector3(1, 1, 4),
new Vector3(2, 2, 2),
new Vector3(2, 2, 10)
) )
expect(res).toBeUndefined();
res = IntersectLAndLFor3D(
new Vector3(1, 0, 1),
new Vector3(1, 0, 4),
new Vector3(0.5, 0, 3),
new Vector3(0.5, 0, 10)
)
expect(res).toBeUndefined();
})
test('三维空间圆圆相交测试', () =>
{
let data = [["Circle", 1, 1, 3, false, 7, -1, [-0.1485675258840154, -0.98346692600856, 0.10353982663678746, 0, 0.8068528994682419, -0.18108783903750572, -0.5623127183093208, 0, 0.5717657639911589, 0, 0.8204169129946106, 0, 5.585923427922135, -0.5874251796993211, -0.834443475807827, 1], 1, 2.1223349919617873], ["Circle", 1, 1, 9, false, 7, -1, [-0.1485675258840154, -0.98346692600856, 0.10353982663678746, 0, 0.8068528994682419, -0.18108783903750572, -0.5623127183093208, 0, 0.5717657639911589, 0, 0.8204169129946106, 0, 3.2540542870196947, -1.8996318241962369, 0.7906850652516981, 1], 1, 1.5840127550993974]]
testCirAndCirIntersect(data);
data = [["Circle", 1, 1, 3, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, 5], ["Circle", 1, 1, 4, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2.5, 0, 0, 1], 1, 5]];
testCirAndCirIntersect(data);
data = [["Circle", 1, 1, 5, false, 7, -1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 1, 5], ["Circle", 1, 1, 6, false, 7, -1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 2.5, 0, 0, 1], 1, 5]];
testCirAndCirIntersect(data);
data = [["Arc", 1, 1, 10, false, 7, -1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -7.223901135674274, -7.066640793063616, 1], 2, 4.787455889013074, 2.4468553886273967, 0.7203768859081977, true], ["Arc", 1, 1, 11, false, 7, -1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, -12.887397630639091, -5.59172322768673, 1], 2, 4.265691675276281, 3.020045238916937, 0.9631807673370143, true]]
testCirAndCirIntersect(data);
data = [["Circle", 1, 1, 4, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2.5, 0, 0, 1], 1, 5], ["Circle", 1, 1, 6, false, 7, -1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 2.5, 0, 0, 1], 1, 5]];
testCirAndCirIntersect(data);
})
test('三维空间直线和圆相交测试', () =>
{
let data = [["Circle", 1, 1, 6, false, 7, -1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 2.5, 0, 0, 1], 1, 5], ["Line", 1, 1, 12, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [2.4219301113484804, 0, 6.278428496635537], [9.19486541121855, 0, -0.38347507700715716]]]
testLineAndCirIntersect(data);
data = [["Circle", 1, 1, 3, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, 5], ["Line", 1, 1, 13, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [-3.6226270297054635, 5.273119429622456, 0], [-3.6226270297054652, -5.297100907223948, 0]]];
testLineAndCirIntersect(data);
data = [["Circle", 1, 1, 3, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 13.418897659897576, -9.71681408534522, 4.841809080303142, 1], 1, 5], ["Line", 1, 1, 13, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [9.796270630192113, -4.443694655722764, 4.841809080303142], [9.796270630192112, -15.013914992569168, 4.841809080303142]]];
testLineAndCirIntersect(data);
data = [["Circle", 1, 1, 3, false, 7, -1, [0.8517840265050032, 0, -0.5238930923298417, 0, 0, 1, 0, 0, 0.5238930923298417, 0, 0.8517840265050032, 0, 15.469956975945145, -9.71681408534522, 4.4481472148971575, 1], 1, 5], ["Line", 1, 1, 13, false, 7, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 1, [12.384261138056765, -4.443694655722764, 6.346016491847221], [12.384261138056765, -15.013914992569168, 6.346016491847222]]];
testLineAndCirIntersect(data);
})
function loadFile(data)
{
let file = new CADFile();
file.Data = data;
let cus: Curve[] = [];
for (let i = 0; i < file.Data.length; i++)
{
cus.push(file.ReadObject(undefined) as Curve);
}
return cus;
}
function testCirAndCirIntersect(data)
{
let cus = loadFile(data) as Array<Circle | Arc>;
let pts = IntersectCircleAndCircle(cus[0], cus[1]);
expect(pts).toMatchSnapshot();
}
function testLineAndCirIntersect(data)
{
let cus = loadFile(data);
let [cu1, cu2] = cus[0] instanceof Line ? cus : cus.reverse();
let pts = cu1.IntersectWith(cu2, IntersectOption.ExtendBoth);
expect(pts).toMatchSnapshot();
}

@ -34,7 +34,7 @@ Vector3 {
exports[`最近点 1`] = ` exports[`最近点 1`] = `
Vector3 { Vector3 {
"x": -2.5, "x": -2.499999999999999,
"y": -2.499999999999999, "y": -2.499999999999999,
"z": 0, "z": 0,
} }

@ -277,131 +277,6 @@ Array [
] ]
`; `;
exports[`单刀 6`] = `
Array [
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 0,
},
},
Object {
"bul": 1,
"pt": Vector2 {
"x": 5,
"y": 0,
},
},
Object {
"bul": -0.41421356237309503,
"pt": Vector2 {
"x": 5,
"y": 5,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 2.5,
"y": 7.5,
},
},
]
`;
exports[`单刀 7`] = `
Array [
Object {
"bul": -0.41421356237309503,
"pt": Vector2 {
"x": 2.5,
"y": 7.5,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 5,
"y": 10,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 10,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 0,
},
},
]
`;
exports[`单刀 8`] = `
Array [
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 0,
},
},
Object {
"bul": 1,
"pt": Vector2 {
"x": 5,
"y": 0,
},
},
Object {
"bul": -1,
"pt": Vector2 {
"x": 5,
"y": 5,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 5,
"y": 10,
},
},
]
`;
exports[`单刀 9`] = `
Array [
Object {
"bul": 0,
"pt": Vector2 {
"x": 5,
"y": 10,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 10,
},
},
Object {
"bul": 0,
"pt": Vector2 {
"x": 0,
"y": 0,
},
},
]
`;
exports[`单刀闭合 1`] = ` exports[`单刀闭合 1`] = `
Array [ Array [
Object { Object {

@ -1,55 +1,44 @@
import * as THREE from 'three';
import { Vector3, Vector2 } from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { Arc } from '../DatabaseServices/Arc';
import { Command } from '../Editor/CommandMachine'; import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus } from '../Editor/PromptResult';
import { RenderType } from '../GraphicsSystem/Enum';
import { Arc } from '../DatabaseServices/Arc';
export class DrawArc implements Command export class DrawArc implements Command
{ {
async exec() async exec()
{ {
let pt1 = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone();
let pt2 = pt1;
let pt3 = pt2;
app.m_Editor.UpdateScreen();
let ptRes = await app.m_Editor.GetPoint({ Msg: "请输入第一个点:" }); let ptRes = await app.m_Editor.GetPoint({ Msg: "请输入第一个点:" });
if (ptRes.Status != PromptStatus.OK) if (ptRes.Status != PromptStatus.OK)
{
return; return;
} let pt1 = ptRes.Value;
pt1 = ptRes.Value;
let ptRes2 = await app.m_Editor.GetPoint({ Msg: "请输入第二个点:", BasePoint: pt1, AllowDrawRubberBand: true }); let ptRes2 = await app.m_Editor.GetPoint({ Msg: "请输入第二个点:", BasePoint: pt1, AllowDrawRubberBand: true });
if (ptRes2.Status != PromptStatus.OK) if (ptRes2.Status != PromptStatus.OK)
{
return; return;
} let pt2 = ptRes2.Value;
pt2 = ptRes2.Value;
let arc = new Arc(); let arc = new Arc();
arc.ApplyMatrix(app.m_Editor.UCSMatrix);
app.m_Database.ModelSpace.Append(arc);
app.m_Editor.AddNoSnapEntity(arc); app.m_Editor.AddNoSnapEntity(arc);
let ptRes3 = await app.m_Editor.GetPoint({ const updateArc = (p) =>
Msg: "请输入第三个点:", Callback: (p) =>
{ {
if (!p.equals(pt2) && !p.equals(pt1)) if (!p.equals(pt2) && !p.equals(pt1))
{ {
arc.FromThreePoint(pt1, pt2, p); arc.FromThreePoint(pt1, pt2, p);
arc.Update(); arc.Update();
if (!arc.Id)
{
app.m_Database.ModelSpace.Append(arc);
}
} }
} }
let ptRes3 = await app.m_Editor.GetPoint({
Msg: "请输入第三个点:",
Callback: updateArc
}); });
if (ptRes.Status != PromptStatus.OK)
{ if (ptRes3.Status != PromptStatus.OK)
return; arc.Erase();
} else
app.m_Database.hm.EndCmd(); updateArc(ptRes3.Value);
} }
} }

@ -1,11 +1,9 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Box3, Vector3 } from 'three'; import { Vector3 } from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { Vec3DTo2D } from '../Common/CurveUtils';
import { Arc } from '../DatabaseServices/Arc'; import { Arc } from '../DatabaseServices/Arc';
import { Circle } from '../DatabaseServices/Circle'; import { Circle } from '../DatabaseServices/Circle';
import { Line } from '../DatabaseServices/Line'; import { Line } from '../DatabaseServices/Line';
import { Polyline } from '../DatabaseServices/Polyline';
import { Command } from '../Editor/CommandMachine'; import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus } from '../Editor/PromptResult';
import { midPoint } from '../Geometry/GeUtils'; import { midPoint } from '../Geometry/GeUtils';
@ -134,56 +132,6 @@ void main() {
} }
*/ */
export class DrawRect implements Command
{
async exec()
{
let ptRes = await app.m_Editor.GetPoint();
if (ptRes.Status != PromptStatus.OK)
{
return;
}
let p1: THREE.Vector3;
let p2: THREE.Vector3;
p1 = ptRes.Value;
let rec = new Polyline();
rec.CloseMark = true;
app.m_Database.ModelSpace.Append(rec);
app.m_Editor.AddNoSnapEntity(rec);
let box = new Box3();
let updateRect = (p1, p2) =>
{
box.setFromPoints([p2, p1]);
let px1 = Vec3DTo2D(box.min);
let px3 = Vec3DTo2D(box.max);
let px2 = new THREE.Vector2(px3.x, px1.y);
let px4 = new THREE.Vector2(px1.x, px3.y);
rec.LineData = [{ pt: px1, bul: 0 },
{ pt: px2, bul: 0 },
{ pt: px3, bul: 0 },
{ pt: px4, bul: 0 }];
}
ptRes = await app.m_Editor.GetPoint({
Callback: (p) =>
{
updateRect(p, p1);
}
});
if (ptRes.Status == PromptStatus.OK)
updateRect(ptRes.Value, p1);
else
rec.Erase();
}
}
export class DrawCircle implements Command export class DrawCircle implements Command
{ {
async exec() async exec()
@ -192,7 +140,6 @@ export class DrawCircle implements Command
Msg: "指定圆的圆心", Msg: "指定圆的圆心",
KeyWordList: [{ key: "3P", msg: "三点" }, { key: "2P", msg: "二点" }, { key: "T", msg: "切点、切点、半径" }] KeyWordList: [{ key: "3P", msg: "三点" }, { key: "2P", msg: "二点" }, { key: "T", msg: "切点、切点、半径" }]
}); });
switch (ptRes.Status) switch (ptRes.Status)
{ {
case PromptStatus.Cancel: case PromptStatus.Cancel:
@ -228,7 +175,10 @@ export class DrawCircle implements Command
async DrawCircleUseRadious(val: Vector3) async DrawCircleUseRadious(val: Vector3)
{ {
let cir = new Circle(val, 1e-3); let cir = new Circle();
cir.ApplyMatrix(app.m_Editor.UCSMatrix);
cir.Center = val;
app.m_Database.ModelSpace.Append(cir); app.m_Database.ModelSpace.Append(cir);
app.m_Editor.AddNoSnapEntity(cir); app.m_Editor.AddNoSnapEntity(cir);
@ -246,22 +196,25 @@ export class DrawCircle implements Command
async DrawCicleUseTwoPoint() async DrawCicleUseTwoPoint()
{ {
let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 1e-3);
let ptRes1 = await app.m_Editor.GetPoint({ let ptRes1 = await app.m_Editor.GetPoint({
Msg: "指定圆直径的第一个端点:", Msg: "指定圆直径的第一个端点:",
}); });
if (ptRes1.Status != PromptStatus.OK) if (ptRes1.Status != PromptStatus.OK)
return; return;
let cir = new Circle();
app.m_Database.ModelSpace.Append(cir); app.m_Database.ModelSpace.Append(cir);
app.m_Editor.AddNoSnapEntity(cir); app.m_Editor.AddNoSnapEntity(cir);
let ptRes2 = await app.m_Editor.GetPoint({ let ptRes2 = await app.m_Editor.GetPoint({
Msg: "指定圆直径的第二个端点:", Msg: "指定圆直径的第二个端点:",
BasePoint: ptRes1.Value, BasePoint: ptRes1.Value,
AllowDrawRubberBand: true, AllowDrawRubberBand: true,
Callback: (v) => { cir.Radius = v.distanceTo(ptRes1.Value) / 2; cir.Center = midPoint(v, ptRes1.Value) }, Callback: (v) =>
{
cir.Radius = v.distanceTo(ptRes1.Value) / 2;
cir.Center = midPoint(v, ptRes1.Value)
},
}); });
if (ptRes2.Status === PromptStatus.OK) if (ptRes2.Status === PromptStatus.OK)
{ {
@ -269,22 +222,19 @@ export class DrawCircle implements Command
cir.Center = midPoint(ptRes2.Value, ptRes1.Value); cir.Center = midPoint(ptRes2.Value, ptRes1.Value);
} }
else else
{
cir.Erase(); cir.Erase();
} }
app.m_Editor.ClearSnapEntity();
}
async DrawCicleUseThreePoint() async DrawCicleUseThreePoint()
{ {
let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 1e-3);
let ar = new Arc();
let ptRes1 = await app.m_Editor.GetPoint({ let ptRes1 = await app.m_Editor.GetPoint({
Msg: "指定圆上第一个点:" Msg: "指定圆上第一个点:"
}); });
if (ptRes1.Status != PromptStatus.OK) if (ptRes1.Status != PromptStatus.OK)
return; return;
let cir = new Circle();
let ar = new Arc();
app.m_Database.ModelSpace.Append(cir); app.m_Database.ModelSpace.Append(cir);
let ptRes2 = await app.m_Editor.GetPoint({ let ptRes2 = await app.m_Editor.GetPoint({
@ -300,7 +250,12 @@ export class DrawCircle implements Command
Msg: "指定圆上第三个点:", Msg: "指定圆上第三个点:",
BasePoint: ptRes2.Value, BasePoint: ptRes2.Value,
AllowDrawRubberBand: true, AllowDrawRubberBand: true,
Callback: (v) => { ar.FromThreePoint(ptRes1.Value, ptRes2.Value, v); cir.Radius = ar.Radius; cir.Center = ar.Center }, Callback: (v) =>
{
ar.FromThreePoint(ptRes1.Value, ptRes2.Value, v);
cir.Radius = ar.Radius;
cir.Center = ar.Center
},
}); });
if (ptRes3.Status === PromptStatus.OK) if (ptRes3.Status === PromptStatus.OK)
{ {
@ -309,12 +264,8 @@ export class DrawCircle implements Command
cir.Center = ar.Center; cir.Center = ar.Center;
} }
else else
{
cir.Erase(); cir.Erase();
} }
app.m_Editor.ClearSnapEntity();
}
async DrawCicleUseCutoffPointAndRadious() async DrawCicleUseCutoffPointAndRadious()
{ {
// let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 1e-3); // let cir = new Circle(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone(), 1e-3);

@ -1,9 +1,11 @@
import { Vector3 } from 'three'; import { Matrix4, Vector3, Vector2 } from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { Vec2DTo3D, Vec3DTo2D, getCirAngleByChordAndTangent, rotateLine } from '../Common/CurveUtils'; import { Vec2DTo3D, Vec3DTo2D, getCirAngleByChordAndTangent } from '../Common/CurveUtils';
import { Polyline, PolylineProps } from '../DatabaseServices/Polyline'; import { Polyline, PolylineProps } from '../DatabaseServices/Polyline';
import { Command } from '../Editor/CommandMachine'; import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus, PromptSsgetResult } from '../Editor/PromptResult';
import { rotatePoint } from '../Geometry/GeUtils';
import { GetPointPrompt } from '../Common/InputState';
enum PolylineModel enum PolylineModel
{ {
@ -11,157 +13,121 @@ enum PolylineModel
Line = 1 Line = 1
} }
export class DrawPolyline implements Command export class DrawPolyline
{ {
private m_Model; model: PolylineModel = PolylineModel.Line;
async exec() async exec()
{ {
app.m_Editor.m_CommandStore.Prompt("请输入一个点:"); this.model = PolylineModel.Line;
let ptRes = await app.m_Editor.GetPoint({ Msg: "请输入第一个点:" });
if (ptRes.Status != PromptStatus.OK)
{
return;
}
this.m_Model = PolylineModel.Line;
let basePt = ptRes.Value; let pl = new Polyline();
//存储基点 pl.ApplyMatrix(app.m_Editor.UCSMatrix);
let BasePts = [basePt]; app.m_Database.ModelSpace.Append(pl);
//多段线最终点 app.m_Editor.AddNoSnapEntity(pl);
let data: PolylineProps = {
pt: Vec3DTo2D(basePt),
bul: 0
}
//储存多段线数据
let lineProps = [data]
let polyline = new Polyline(lineProps); let Callback = (p: Vector3) =>
this.UpdatePoint(pl, p);
app.m_Database.ModelSpace.Append(polyline); let firstOps: GetPointPrompt = { Msg: "请输入第一个点:", Callback };
// 切线 let keywords = [{ msg: "圆弧", key: "A" }, { msg: "直线", key: "L" }, { msg: "放弃", key: "U" }];
let tangentLine: Vector3; let keywords2 = keywords.concat([{ msg: "闭合", key: "C" }]);
// 弦 let nextOps: GetPointPrompt = { Msg: "请点击下一个点或", Callback };
let chord: Vector3;
// 圆心角
let cirAng: number;
// 圆弧方向
let dir: Vector3;
let KeyWordList = [{ msg: "圆弧", key: "A" }, { msg: "直线", key: "L" }, { msg: "放弃", key: "U" }];
//返回一步
let restore = () =>
{
lineProps.pop();
polyline.LineData = lineProps;
}
// 更新多段线凸度
let updateBul = (endPt: Vector3, startPt: Vector3) =>
{
// 弦长矢量
chord = endPt.clone().sub(startPt);
cirAng = getCirAngleByChordAndTangent(chord, tangentLine);
if (cirAng)
{
//凸度
let bul = Math.tan(cirAng / 4);
lineProps[lineProps.length - 2].bul = bul
}
}
while (true) while (true)
{ {
data = { let ops: GetPointPrompt;
pt: Vec3DTo2D(basePt), if (pl.NumberOfVertices === 0)
bul: 0 ops = firstOps;
} else
if (lineProps.length === 2)
{ {
KeyWordList.push({ msg: "闭合", key: "C" }) ops = nextOps;
ops.BasePoint = pl.EndPoint;
if (pl.NumberOfVertices > 3)
nextOps.KeyWordList = keywords2;
else
nextOps.KeyWordList = keywords;
} }
lineProps.push(data);
app.m_Editor.m_CommandStore.Prompt("请输入点2:"); pl.AddVertexAt(pl.NumberOfVertices, new Vector2());
ptRes = await app.m_Editor.GetPoint({ let p = await app.m_Editor.GetPoint(ops);
Msg: "请输入点2:",
BasePoint: basePt, if (p.Status === PromptStatus.OK)
AllowDrawRubberBand: true, this.UpdatePoint(pl, p.Value);
KeyWordList, else if (p.Status === PromptStatus.Keyword)
Callback: (v) =>
{ {
if (this.m_Model === 0) this.RemoveLastVertex(pl);
if (p.StringResult === "A")
{ {
if (!tangentLine) tangentLine = new Vector3(1, 0, 0); this.model = PolylineModel.Arc;
data.pt.set(v.x, v.y);
updateBul(v, basePt);
polyline.LineData = lineProps;
} }
else if (p.StringResult === "L")
{
this.model = PolylineModel.Line;
if (pl.NumberOfVertices > 0)
pl.SetBulgeAt(pl.NumberOfVertices - 1, 0);
} }
}); else if (p.StringResult === "U")
if (ptRes.Status == PromptStatus.OK)
{ {
data.pt.set(ptRes.Value.x, ptRes.Value.y) this.RemoveLastVertex(pl);
if (this.m_Model === 1) if (pl.NumberOfVertices > 0)
{ {
//切线 this.model = pl.GetBuilgeAt(pl.NumberOfVertices - 1) !== 0 ?
tangentLine = ptRes.Value.clone().sub(basePt).normalize(); PolylineModel.Arc : PolylineModel.Line;
} }
else
{
updateBul(ptRes.Value, basePt);
tangentLine = rotateLine(tangentLine, cirAng)
} }
polyline.LineData = lineProps; else if (p.StringResult === "C")
BasePts.push(basePt);
basePt = ptRes.Value;
continue;
}
else if (ptRes.Status == PromptStatus.Keyword)
{
//是否闭合曲线
if (ptRes.StringResult == "C")
{ {
data.pt = lineProps[0].pt; if (this.model === PolylineModel.Arc)
let endPt = Vec2DTo3D(data.pt);
if (this.m_Model === PolylineModel.Arc)
{ {
polyline.CloseMark = true; pl.AddVertexAt(pl.NumberOfVertices, new Vector2());
updateBul(endPt, basePt); this.UpdatePoint(pl, pl.StartPoint);
this.RemoveLastVertex(pl);
} }
polyline.LineData = lineProps; pl.CloseMark = true;
break; break;
} }
}
if (ptRes.StringResult == "U")
{
basePt = BasePts.pop();
lineProps.pop();
if (this.m_Model === 1)
tangentLine = basePt.clone().sub(BasePts[BasePts.length - 1]).normalize();
else else
{ {
data = lineProps[lineProps.length - 2]; this.RemoveLastVertex(pl);
cirAng = Math.atan(data.bul) * 4; break;
tangentLine = rotateLine(tangentLine, -cirAng)
} }
} }
else if (ptRes.StringResult == "A") if (pl.NumberOfVertices < 2)
{ pl.Erase();
this.m_Model = PolylineModel.Arc;
} }
else if (ptRes.StringResult == "L")
UpdatePoint(pl: Polyline, pt: Vector3)
{ {
lineProps[lineProps.length - 2].bul = 0; let ptCout = pl.NumberOfVertices;
this.m_Model = PolylineModel.Line;
} let p = pt.clone().applyMatrix4(pl.OCSInv);
restore(); pl.SetPointAt(ptCout - 1, Vec3DTo2D(p));
}
else if (this.model === PolylineModel.Arc && ptCout > 1)
{ {
restore(); let pLast = pl.GetPoint2dAt(ptCout - 2);
break; //弦长
let chord = p.clone().sub(Vec2DTo3D(pLast));
//切线
let tangent: Vector3;
if (ptCout > 2)
tangent = pl.GetCurveAtIndex(ptCout - 3).GetFistDeriv(1).applyMatrix4(pl.OCSInv);
else
tangent = new Vector3(1, 0, 0);
let cirAng = getCirAngleByChordAndTangent(chord, tangent);
if (cirAng)
pl.SetBulgeAt(ptCout - 2, Math.tan(cirAng * 0.25));
} }
app.m_Editor.UpdateScreen();
} }
RemoveLastVertex(pl: Polyline)
{
if (pl.NumberOfVertices > 0)
pl.RemoveVertexAt(pl.NumberOfVertices - 1);
} }
} }

@ -0,0 +1,53 @@
import * as THREE from 'three';
import { Box3, Vector3 } from 'three';
import { app } from '../ApplicationServices/Application';
import { Vec3DTo2D } from '../Common/CurveUtils';
import { Polyline } from '../DatabaseServices/Polyline';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
export class DrawRect implements Command
{
async exec()
{
let ptRes = await app.m_Editor.GetPoint();
if (ptRes.Status != PromptStatus.OK)
return;
let p1: THREE.Vector3;
let p2: THREE.Vector3;
p1 = ptRes.Value;
let rec = new Polyline();
rec.CloseMark = true;
rec.ApplyMatrix(app.m_Editor.UCSMatrix);
app.m_Database.ModelSpace.Append(rec);
app.m_Editor.AddNoSnapEntity(rec);
let box = new Box3();
let updateRect = (p1, p2) =>
{
box.setFromPoints([p2, p1].map((p: Vector3) => p.clone().applyMatrix4(rec.OCSInv)));
let px1 = Vec3DTo2D(box.min);
let px3 = Vec3DTo2D(box.max);
let px2 = new THREE.Vector2(px3.x, px1.y);
let px4 = new THREE.Vector2(px1.x, px3.y);
rec.LineData = [
{ pt: px1, bul: 0 },
{ pt: px2, bul: 0 },
{ pt: px3, bul: 0 },
{ pt: px4, bul: 0 }];
}
ptRes = await app.m_Editor.GetPoint({
Callback: (p) => updateRect(p, p1)
});
if (ptRes.Status == PromptStatus.OK)
updateRect(ptRes.Value, p1);
else
rec.Erase();
}
}

@ -1,6 +1,4 @@
import { Callback } from 'awesome-typescript-loader/dist/paths-plugin';
import * as THREE from 'three'; import * as THREE from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { CADFile } from '../DatabaseServices/CADFile'; import { CADFile } from '../DatabaseServices/CADFile';
import { Entity } from '../DatabaseServices/Entity'; import { Entity } from '../DatabaseServices/Entity';
@ -11,33 +9,33 @@ import { SelectPick } from '../Editor/SelectPick';
import { SelectSet, SelectType } from '../Editor/SelectSet'; import { SelectSet, SelectType } from '../Editor/SelectSet';
import { MoveMatrix } from '../Geometry/GeUtils'; import { MoveMatrix } from '../Geometry/GeUtils';
export class Stretch implements Command //拉伸的解析数据
interface StretchData
{ {
moveEntityList: Entity[];//被移动的图元(所有点都被选中)
stretchEntityMap: Map<Entity, Array<number>>; //被拉伸的图元,对照被拉伸的点索引.
}
m_CacheEntity: Map<Entity, CADFile> = new Map<Entity, CADFile>(); export class Stretch implements Command
async exec(ss: SelectSet)
{ {
if (ss.SelectObjectList.length == 0) m_CacheEntity: Map<Entity, CADFile> = new Map<Entity, CADFile>();
async exec()
{ {
let ssRes = await app.m_Editor.GetSelection(); let ssRes = await app.m_Editor.GetSelection({ UseSelect: true, Msg: "请选择拉伸对象:" });
if (ssRes.Status != PromptStatus.OK) if (ssRes.Status != PromptStatus.OK) return;
return; let ss = ssRes.SelectSet;
ss == ssRes.SelectSet; let p1 = await app.m_Editor.GetPoint({ Msg: "指定基点:" });//, KeyWordList: [{ msg: "位移", key: "D" }]
if (ss.SelectEntityList.length === 0)
return;
}
let p1 = await app.m_Editor.GetPoint({ Msg: "请选择第一个拉伸点:" });
if (p1.Status != PromptStatus.OK) return; if (p1.Status != PromptStatus.OK) return;
let data = this.parse(ss); let data = this.parse(ss);
for (let [obj] of data.str) for (let [e] of data.stretchEntityMap)
app.m_Editor.AddNoSnapEntity(obj.userData); app.m_Editor.AddNoSnapEntity(e);
let lastP = p1.Value.clone(); let lastP = p1.Value.clone();
let p2 = await app.m_Editor.GetPoint( let p2 = await app.m_Editor.GetPoint(
{ {
BasePoint: p1.Value, BasePoint: p1.Value,
Msg: "请选择第二个拉伸点:", Msg: "指定第二个点:",//或 <使用第一个点作为位移>
Callback: (p) => Callback: (p) =>
{ {
let v = p.clone().sub(lastP); let v = p.clone().sub(lastP);
@ -52,42 +50,37 @@ export class Stretch implements Command
this.m_CacheEntity.clear(); this.m_CacheEntity.clear();
} }
parse(ss: SelectSet): { str: Map<THREE.Object3D, Array<number>>, move: Array<THREE.Object3D> } parse(ss: SelectSet): StretchData
{ {
let stretchPtsIndexMap = new Map<THREE.Object3D, Array<number>>(); let data: StretchData =
let move = []; {
stretchEntityMap: new Map<Entity, Array<number>>(),
moveEntityList: []
};
for (let set of ss.SelectSetList) for (let set of ss.SelectSetList)
{ {
if (set instanceof SelectPick) if (set instanceof SelectPick)
{ {
for (let obj of set.m_SelectList) for (let obj of set.m_SelectList)
{ data.moveEntityList.push(obj.userData);
move.push(obj);
}
} }
else if (set instanceof SelectBox) else if (set instanceof SelectBox)
{ {
if (set.m_SelectType == SelectType.W) if (set.m_SelectType == SelectType.W)
{ {
for (let obj of set.m_SelectList) for (let obj of set.m_SelectList)
{ data.moveEntityList.push(obj.userData);
move.push(obj);
}
} }
else else
{ {
for (let obj of set.m_SelectList) for (let obj of set.m_SelectList)
{ {
let indexArr = []; let indexArr = [];
stretchPtsIndexMap.set(obj, indexArr);
let en = obj.userData; let en = obj.userData;
if (en && en instanceof Entity) if (en && en instanceof Entity)
{ {
let f = new CADFile(); this.CacheEntity(en);
en.WriteFile(f); data.stretchEntityMap.set(en, indexArr);
this.m_CacheEntity.set(en, f);
let pts = en.GetStretchPoints(); let pts = en.GetStretchPoints();
for (let i = pts.length; i--;) for (let i = pts.length; i--;)
{ {
@ -103,27 +96,37 @@ export class Stretch implements Command
} }
} }
} }
return {
str: stretchPtsIndexMap, for (let e of data.moveEntityList)
move: move this.CacheEntity(e);
}
return data;
} }
s(d: { str: Map<THREE.Object3D, Array<number>>, move: Array<THREE.Object3D> }, vec: THREE.Vector3) s(d: StretchData, vec: THREE.Vector3)
{ {
let moveMat = MoveMatrix(vec); let moveMat = MoveMatrix(vec);
for (let obj of d.move) for (let e of d.moveEntityList)
{ {
obj.applyMatrix(moveMat); this.RestoreEntity(e);
e.ApplyMatrix(moveMat);
} }
for (let [obj, arr] of d.str) for (let [e, arr] of d.stretchEntityMap)
{
if (obj.userData instanceof Entity)
{ {
let f = this.m_CacheEntity.get(obj.userData); this.RestoreEntity(e);
f.Reset(); e.MoveStretchPoints(arr, vec);
obj.userData.ReadFile(f);
obj.userData.MoveStretchPoints(arr, vec);
} }
} }
CacheEntity(e: Entity)
{
let f = new CADFile();
e.WriteFile(f);
this.m_CacheEntity.set(e, f);
}
RestoreEntity(e: Entity)
{
let f = this.m_CacheEntity.get(e);
f.Reset();
e.ReadFile(f);
} }
} }

@ -70,7 +70,7 @@ export class Command_Trim implements Command
if (s instanceof SelectBox) if (s instanceof SelectBox)
{ {
let set = s; let set = s;
splitCus = splitCus.filter(cu => { return set.IntersectObject(cu.Draw(RenderType.Wireframe)) }); splitCus = splitCus.filter(c => set.IntersectObject(c.Draw(RenderType.Wireframe)));
let needBreakCus: Curve[] = []; let needBreakCus: Curve[] = [];
while (splitCus.length > 0) while (splitCus.length > 0)

@ -0,0 +1,89 @@
import { app } from "../../ApplicationServices/Application";
import { Circle } from "../../DatabaseServices/Circle";
import { Curve } from "../../DatabaseServices/Curve";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { IntersectLAndLFor3D, IntersectOption, IntersectCircleAndCircle } from "../../GraphicsSystem/IntersectWith";
import { Line } from "three";
import { Arc } from "../../DatabaseServices/Arc";
export class TestIntersect implements Command
{
async exec()
{
// this.testLineAndLine();
// this.testLineAndCirOrArc();
this.testCirAndCir()
app.m_Editor.UpdateScreen();
}
async testLineAndLine()
{
let exRefSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true });
if (exRefSsRes.Status !== PromptStatus.OK) return;
let cus = exRefSsRes.SelectSet.SelectEntityList as Curve[];
let pt = IntersectLAndLFor3D(cus[0].StartPoint, cus[0].EndPoint, cus[1].StartPoint, cus[1].EndPoint);
console.log('pt: ', pt);
if (pt)
{
cus[0].ColorIndex = 7;
cus[1].ColorIndex = 7;
let cir = new Circle(pt, 0.1);
cir.ColorIndex = 2;
app.m_Database.ModelSpace.Append(cir);
} else
{
cus[0].ColorIndex = 1;
cus[1].ColorIndex = 1;
}
}
async testLineAndCirOrArc()
{
let exRefSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true });
if (exRefSsRes.Status !== PromptStatus.OK) return;
let cus = exRefSsRes.SelectSet.SelectEntityList as Curve[];
if (cus.length > 1)
{
let [cu1, cu2] = cus[0] instanceof Line ? cus : cus.reverse();
let pts = cu1.IntersectWith(cu2, IntersectOption.ExtendBoth);
if (pts.length)
{
pts.forEach(p =>
{
let cir = new Circle(p, 0.2);
cir.ColorIndex = 2;
app.m_Database.ModelSpace.Append(cir);
})
} else
{
cu1.ColorIndex = 1;
cu2.ColorIndex = 1;
}
}
}
async testCirAndCir()
{
let exRefSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true });
if (exRefSsRes.Status !== PromptStatus.OK) return;
let cus = exRefSsRes.SelectSet.SelectEntityList as Array<Circle | Arc>;
if (cus.length > 1)
{
let pt = IntersectCircleAndCircle(cus[0], cus[1]);
console.log('pt: ', pt);
if (pt.length)
{
cus[0].ColorIndex = 7;
cus[1].ColorIndex = 7;
pt.forEach(p =>
{
let cir = new Circle(p, 0.1);
cir.ColorIndex = 2;
app.m_Database.ModelSpace.Append(cir);
})
} else
{
cus[0].ColorIndex = 1;
cus[1].ColorIndex = 1;
}
}
}
}

@ -67,6 +67,14 @@ export function arrayLast<T>(arr: Array<T>): T
return arr[arr.length - 1]; return arr[arr.length - 1];
} }
/**
*
*
* @export
* @template T
* @param {Array<T>} arr
* @returns {Array<T>}
*/
export function arraySortByNumber<T>(arr: Array<T>): Array<T> export function arraySortByNumber<T>(arr: Array<T>): Array<T>
{ {
arr.sort(sortNumberCompart); arr.sort(sortNumberCompart);
@ -77,6 +85,7 @@ export function arraySortByNumber<T>(arr: Array<T>): Array<T>
* *
* *
* @param {(e1, e2) => boolean} [checkFuction] * @param {(e1, e2) => boolean} [checkFuction]
* @returns {Array<T>}
*/ */
export function arrayRemoveDuplicateBySort<T>(arr: Array<T>, checkFuction?: (e1, e2) => boolean): Array<T> export function arrayRemoveDuplicateBySort<T>(arr: Array<T>, checkFuction?: (e1, e2) => boolean): Array<T>

@ -1,21 +1,13 @@
import { Vector2, Vector3 } from 'three'; import { Matrix3, Vector2, Vector3 } from 'three';
import { Arc } from '../DatabaseServices/Arc'; import { Arc } from '../DatabaseServices/Arc';
import { Circle } from '../DatabaseServices/Circle'; import { Circle } from '../DatabaseServices/Circle';
import { Curve } from '../DatabaseServices/Curve'; import { Curve } from '../DatabaseServices/Curve';
import { Line } from '../DatabaseServices/Line'; import { Line } from '../DatabaseServices/Line';
import { Polyline } from '../DatabaseServices/Polyline'; import { Polyline } from '../DatabaseServices/Polyline';
import { equal, equaln } from '../Geometry/GeUtils'; import { Count } from '../Geometry/Count';
import { Matrix2 } from '../Geometry/Matrix2';
import { CurveMap } from '../Geometry/CurveMap'; import { CurveMap } from '../Geometry/CurveMap';
import { equal, equaln } from '../Geometry/GeUtils';
import { Stand } from '../Geometry/RegionParse'; import { Stand } from '../Geometry/RegionParse';
import { Count } from '../Geometry/Count';
//旋转矢量
export function rotateLine(l: Vector3, ang: number)
{
new Matrix2().setRotate(ang).applyVector(l);
return l;
}
//3点获取圆心 //3点获取圆心
export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3) export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3)
@ -65,10 +57,16 @@ export function getCirAngleByChordAndTangent(chord: Vector3, tangentLine: Vector
return cirAng *= dir.z; return cirAng *= dir.z;
} }
//行列式 //行列式
export function getDeterminant(v1: Vector2, v2: Vector2): number export function getDeterminantFor2V(v1: Vector2, v2: Vector2): number
{ {
return v1.x * v2.y - v1.y * v2.x; return v1.x * v2.y - v1.y * v2.x;
} }
export function getDeterminantFor3V(v1: Vector3, v2: Vector3, v3: Vector3)
{
let mat = new Matrix3();
mat.set(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z);
return mat.determinant();
}
// 2D 3D点转换 // 2D 3D点转换
export function Vec2DTo3D(pt: Vector2) export function Vec2DTo3D(pt: Vector2)
{ {

@ -1,4 +1,5 @@
import { Matrix4, Vector3 } from 'three'; import { Matrix4, Vector3 } from 'three';
import { equaln, isParallelTo } from '../Geometry/GeUtils';
/** /**
* *
@ -23,8 +24,9 @@ export function matrixSetVector(mat: Matrix4, col: number, v: Vector3)
* YZXAxisYAxisZAxis * YZXAxisYAxisZAxis
* *
* @export * @export
* @returns {Matrix4}
*/ */
export function matrixAlignCoordSys(matrixFrom: Matrix4, matrixTo: Matrix4) export function matrixAlignCoordSys(matrixFrom: Matrix4, matrixTo: Matrix4): Matrix4
{ {
let matrix = new Matrix4().getInverse(matrixFrom); let matrix = new Matrix4().getInverse(matrixFrom);
@ -32,3 +34,28 @@ export function matrixAlignCoordSys(matrixFrom: Matrix4, matrixTo: Matrix4)
return matrix; return matrix;
} }
/**
* 2
*
* @export
* @param {Matrix4} matrixFrom
* @param {Matrix4} matrixTo
* @returns {boolean} 2
*/
export function matrixIsCoplane(matrixFrom: Matrix4, matrixTo: Matrix4): boolean
{
let nor1 = new Vector3().setFromMatrixColumn(matrixFrom, 2);
let nor2 = new Vector3().setFromMatrixColumn(matrixFrom, 2);
//法线共面
if (!isParallelTo(nor1, nor2))
return false;
//高共面
let pt = new Vector3().setFromMatrixPosition(matrixTo);
//变换到自身对象坐标系.
pt.applyMatrix4(new Matrix4().getInverse(matrixFrom));
return equaln(pt.z, 0);
}

@ -3,7 +3,7 @@ import { Box3, Matrix4, Object3D, ShapeGeometry, Vector2, Vector3 } from 'three'
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { Vec2DTo3D, getCircleCenter } from '../Common/CurveUtils'; import { Vec2DTo3D, getCircleCenter } from '../Common/CurveUtils';
import { matrixSetVector } from '../Common/Matrix4Utils'; import { matrixSetVector } from '../Common/Matrix4Utils';
import { angle, angleTo2Pi, equal, equaln, midPoint, polar } from '../Geometry/GeUtils'; import { angle, angleTo2Pi, equal, equaln, midPoint, polar, MoveMatrix } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum'; import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectArcAndArc, IntersectCircleAndArc, IntersectLineAndArc, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith'; import { IntersectArcAndArc, IntersectCircleAndArc, IntersectLineAndArc, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith';
import { Factory } from './CADFactory'; import { Factory } from './CADFactory';
@ -548,22 +548,18 @@ export class Arc extends Curve
this.UpdateGeometry(geo); this.UpdateGeometry(geo);
} }
GetSnapPoints(): Array<THREE.Vector3> GetSnapPoints(): Array<THREE.Vector3>
{
return this.GetStretchPoints();
}
GetStretchPoints(): Array<Vector3>
{ {
return [ return [
this.StartPoint, this.StartPoint,
this.GetPointAtParam(0.5), this.GetPointAtParam(0.5),
this.EndPoint, this.EndPoint,
this.Center.clone(), this.Center.clone(),
] ];
} }
MoveSnapPoints(indexList: Array<number>, vec: Vector3)
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{ {
let ptsArr = this.GetStretchPoints(); this.WriteAllObjectRecord();
let ptsArr = this.GetSnapPoints();
if (indexList.length > 0) if (indexList.length > 0)
{ {
let index = indexList[0]; let index = indexList[0];
@ -583,6 +579,28 @@ export class Arc extends Curve
} }
} }
} }
GetStretchPoints(): Array<Vector3>
{
return [this.StartPoint, this.EndPoint];
}
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{
if (indexList.length === 0)
return;
this.WriteAllObjectRecord();
if (indexList.length === 2)
this.ApplyMatrix(MoveMatrix(vec));
else
for (let index of indexList)
{
if (index !== 0)
index = 2;
this.MoveSnapPoints([index], vec);
}
}
GetParamAtDist(d: number) GetParamAtDist(d: number)
{ {
@ -597,7 +615,9 @@ export class Arc extends Curve
an = angle(pt.clone().applyMatrix4(this.OCSInv)); an = angle(pt.clone().applyMatrix4(this.OCSInv));
an += Math.PI * 0.5 * (this.m_Clockwise ? -1 : 1); an += Math.PI * 0.5 * (this.m_Clockwise ? -1 : 1);
return polar(new Vector3(), an, this.m_Radius) as Vector3;
let ocs = new Matrix4().extractRotation(this.OCS);
return polar(new Vector3(), an, this.m_Radius).applyMatrix4(ocs);
} }
GetClosestPointTo(pt: Vector3, extend: boolean): Vector3 GetClosestPointTo(pt: Vector3, extend: boolean): Vector3
{ {

@ -1,10 +1,10 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Box3, EllipseCurve, Geometry, Matrix4, Object3D, Vector3 } from 'three'; import { Box3, EllipseCurve, Geometry, Matrix4, Object3D, Vector3 } from 'three';
import { arrayFirst } from '../Common/ArrayExt'; import { arrayFirst, arraySortByNumber, arrayRemoveDuplicateBySort, arrayLast } from '../Common/ArrayExt';
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { clamp } from '../Common/Utils'; import { clamp } from '../Common/Utils';
import { Arc } from '../DatabaseServices/Arc'; import { Arc } from '../DatabaseServices/Arc';
import { angle, equaln, polar } from '../Geometry/GeUtils'; import { angle, equaln, polar, MoveMatrix } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum'; import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith'; import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith';
import { Factory } from './CADFactory'; import { Factory } from './CADFactory';
@ -113,12 +113,19 @@ export class Circle extends Curve
GetSplitCurves(param: number[] | number) GetSplitCurves(param: number[] | number)
{ {
let params = this.SplitParamSort(param); let params: number[];
params.shift(); if (param instanceof Array)
params.pop(); {
params = param.filter(p => this.ParamOnCurve(p));
params.sort((a1, a2) => a2 - a1);//从大到小
arrayRemoveDuplicateBySort(params);
if (params.length < 2) return []; if (params.length < 2) return [];
params.push(arrayFirst(params)); }
params.reverse(); else //圆不能被单个参数切割
return [];
//补上最后一个到第一个的弧
params.unshift(arrayLast(params));
let anglelist = params.map(param => Math.PI * 2 * param); let anglelist = params.map(param => Math.PI * 2 * param);
@ -129,7 +136,8 @@ export class Circle extends Curve
let ea = anglelist[i + 1]; let ea = anglelist[i + 1];
if (!equaln(sa, ea)) if (!equaln(sa, ea))
{ {
let arc = new Arc(this.Center, this.m_Radius, sa, ea); let arc = new Arc(new Vector3(), this.m_Radius, sa, ea);
arc.ApplyMatrix(this.OCS);
curvelist.push(arc); curvelist.push(arc);
} }
} }
@ -142,7 +150,7 @@ export class Circle extends Curve
{ {
return NaN; return NaN;
} }
return angle(pt.clone().sub(this.Center)) / (Math.PI * 2); return angle(pt.clone().applyMatrix4(this.OCSInv)) / (Math.PI * 2);
} }
PtOnCurve(pt: Vector3) PtOnCurve(pt: Vector3)
@ -220,10 +228,6 @@ export class Circle extends Curve
} }
GetSnapPoints(): Array<THREE.Vector3> GetSnapPoints(): Array<THREE.Vector3>
{
return this.GetStretchPoints();
}
GetStretchPoints(): Array<Vector3>
{ {
let pts = [ let pts = [
new Vector3(), new Vector3(),
@ -237,14 +241,10 @@ export class Circle extends Curve
pts.forEach(p => p.applyMatrix4(ocs)); pts.forEach(p => p.applyMatrix4(ocs));
return pts; return pts;
} }
MoveStretchPoints(indexList: Array<number>, vec: Vector3) MoveSnapPoints(indexList: Array<number>, vec: Vector3)
{ {
let ocs = this.OCS;
ocs.setPosition(new Vector3());
let ocsInv = new Matrix4().getInverse(ocs);
vec = vec.clone().applyMatrix4(ocsInv);
let pts = this.GetStretchPoints(); let pts = this.GetSnapPoints();
if (indexList.length > 0) if (indexList.length > 0)
{ {
let index = indexList[0]; let index = indexList[0];
@ -263,12 +263,25 @@ export class Circle extends Curve
} }
} }
} }
GetStretchPoints(): Array<Vector3>
{
let pts = [new Vector3()];
let ocs = this.OCS;
pts.forEach(p => p.applyMatrix4(ocs));
return pts;
}
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{
if (indexList.length > 0)
{
let mat = MoveMatrix(vec);
this.ApplyMatrix(mat);
}
}
GetFistDeriv(pt: number | Vector3) GetFistDeriv(pt: number | Vector3)
{ {
if (typeof pt === "number") if (typeof pt === "number")
{
pt = this.GetPointAtParam(pt); pt = this.GetPointAtParam(pt);
}
else else
pt = pt.clone(); pt = pt.clone();

@ -87,7 +87,7 @@ export abstract class Curve extends Entity
{ {
//切割参数列表 //切割参数列表
let params: number[]; let params: number[];
if (param instanceof Array) if (Array.isArray(param))
{ {
params = param.filter(param => this.ParamOnCurve(param)); params = param.filter(param => this.ParamOnCurve(param));
params.push(0, this.EndParam); params.push(0, this.EndParam);

@ -2,10 +2,10 @@ import { Geometry, Mesh, Object3D, Quaternion, ShapeGeometry, Vector3 } from 'th
import * as THREE from 'three'; import * as THREE from 'three';
import { ColorMaterial } from '../../Common/ColorPalette'; import { ColorMaterial } from '../../Common/ColorPalette';
import { rotateLine } from '../../Common/CurveUtils';
import { Factory } from '../CADFactory'; import { Factory } from '../CADFactory';
import { Entity } from '../Entity'; import { Entity } from '../Entity';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { rotatePoint } from '../../Geometry/GeUtils';
/** /**
* *
@ -124,14 +124,14 @@ export class Dimension extends Entity
} }
reviseTextPosition(v: Vector3) reviseTextPosition(v: Vector3)
{ {
let reviseLine = rotateLine(new Vector3(1), this.TextRotation + Math.PI / 2).multiplyScalar(this.m_Text.Height / 2 + this.FONTTODIMDIST); let reviseLine = rotatePoint(new Vector3(1), this.TextRotation + Math.PI / 2).multiplyScalar(this.m_Text.Height / 2 + this.FONTTODIMDIST);
v.add(reviseLine); v.add(reviseLine);
} }
updateText(text: THREE.Mesh, pos: Vector3, ro: number) updateText(text: THREE.Mesh, pos: Vector3, ro: number)
{ {
this.reviseTextPosition(pos); this.reviseTextPosition(pos);
let moveVecX = rotateLine(new Vector3(1), this.TextRotation).negate().multiplyScalar(this.m_Text.Width / 2); let moveVecX = rotatePoint(new Vector3(1), this.TextRotation).negate().multiplyScalar(this.m_Text.Width / 2);
let moveVecY = rotateLine(new Vector3(0, -1), this.TextRotation).multiplyScalar(this.m_Text.Height / 2); let moveVecY = rotatePoint(new Vector3(0, -1), this.TextRotation).multiplyScalar(this.m_Text.Height / 2);
let p = pos.clone().add(moveVecX); let p = pos.clone().add(moveVecX);
p.add(moveVecY); p.add(moveVecY);

@ -1,19 +1,17 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Geometry, Group, Object3D, Shape, Vector3, Matrix4 } from 'three'; import { Geometry, Group, Object3D, Shape, Vector3 } from 'three';
import { ColorMaterial } from '../../Common/ColorPalette'; import { ColorMaterial } from '../../Common/ColorPalette';
import { rotateLine } from '../../Common/CurveUtils'; import { angleAndX, angleTo, getPtPostion, updateGeometry, rotatePoint } from '../../Geometry/GeUtils';
import { angleAndX, angleTo, getPtPostion, updateGeometry } from '../../Geometry/GeUtils';
import { RenderType } from '../../GraphicsSystem/Enum'; import { RenderType } from '../../GraphicsSystem/Enum';
import { IntersectLAndL } from '../../GraphicsSystem/IntersectWith'; import { IntersectLAndLFor3D } from '../../GraphicsSystem/IntersectWith';
import { Arc } from '../Arc'; import { Arc } from '../Arc';
import { Factory } from '../CADFactory'; import { Factory } from '../CADFactory';
import { CADFile } from '../CADFile';
import { Entity } from '../Entity';
import { Line } from '../Line'; import { Line } from '../Line';
import { Dimension } from './Dim';
import { Curve } from '../Curve';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { Entity } from '../Entity'; import { Dimension } from './Dim';
import { CADFile } from '../CADFile';
@Factory @Factory
export class LineAngularDimension extends Dimension export class LineAngularDimension extends Dimension
@ -118,7 +116,7 @@ export class LineAngularDimension extends Dimension
private getCaclSPtAndEPt() private getCaclSPtAndEPt()
{ {
// 2线交点即为圆心 // 2线交点即为圆心
let center = IntersectLAndL(this.m_StartPoint1, this.m_EndPoint1, this.m_StartPoint2, this.m_EndPoint2); let center = IntersectLAndLFor3D(this.m_StartPoint1, this.m_EndPoint1, this.m_StartPoint2, this.m_EndPoint2);
// 获取实际的首尾点,离圆心近的的为起始点 // 获取实际的首尾点,离圆心近的的为起始点
let [spt1, ept1] = this.StartPoint1.distanceTo(center) < this.EndPoint1.distanceTo(center) ? [this.StartPoint1, this.EndPoint1] : [this.EndPoint1, this.StartPoint1]; let [spt1, ept1] = this.StartPoint1.distanceTo(center) < this.EndPoint1.distanceTo(center) ? [this.StartPoint1, this.EndPoint1] : [this.EndPoint1, this.StartPoint1];
let [spt2, ept2] = this.StartPoint2.distanceTo(center) < this.EndPoint2.distanceTo(center) ? [this.StartPoint2, this.EndPoint2] : [this.EndPoint2, this.StartPoint2]; let [spt2, ept2] = this.StartPoint2.distanceTo(center) < this.EndPoint2.distanceTo(center) ? [this.StartPoint2, this.EndPoint2] : [this.EndPoint2, this.StartPoint2];
@ -128,7 +126,7 @@ export class LineAngularDimension extends Dimension
private getDimArcData() private getDimArcData()
{ {
// 2线交点即为圆心 // 2线交点即为圆心
let center = IntersectLAndL(this.m_StartPoint1, this.m_EndPoint1, this.m_StartPoint2, this.m_EndPoint2); let center = IntersectLAndLFor3D(this.m_StartPoint1, this.m_EndPoint1, this.m_StartPoint2, this.m_EndPoint2);
let rad = this.m_ArcPoint.distanceTo(center); let rad = this.m_ArcPoint.distanceTo(center);
let { ept1, ept2 } = this.getCaclSPtAndEPt(); let { ept1, ept2 } = this.getCaclSPtAndEPt();
//标注线段的起始端点 //标注线段的起始端点
@ -229,8 +227,8 @@ export class LineAngularDimension extends Dimension
let line1 = ept1.clone().sub(spt1); let line1 = ept1.clone().sub(spt1);
let line2 = ept2.clone().sub(spt2); let line2 = ept2.clone().sub(spt2);
rotateLine(line1, -Math.PI / 2); rotatePoint(line1, -Math.PI / 2);
rotateLine(line2, Math.PI / 2); rotatePoint(line2, Math.PI / 2);
let angle = angleTo(originLine, line1); let angle = angleTo(originLine, line1);
let angle1 = angleTo(originLine.negate(), line2); let angle1 = angleTo(originLine.negate(), line2);
if (Math.abs(angle) >= Math.PI / 2) if (Math.abs(angle) >= Math.PI / 2)

@ -6,7 +6,7 @@ import { RenderType } from '../GraphicsSystem/Enum';
import { Factory } from './CADFactory'; import { Factory } from './CADFactory';
import { CADFile } from './CADFile'; import { CADFile } from './CADFile';
import { Curve } from './Curve'; import { Curve } from './Curve';
import { rotateLine } from '../Common/CurveUtils'; import { rotatePoint } from '../Geometry/GeUtils';
@Factory @Factory
export class Ellipse extends Curve export class Ellipse extends Curve
@ -65,7 +65,7 @@ export class Ellipse extends Curve
} }
PtInCurve(pt: Vector3) PtInCurve(pt: Vector3)
{ {
let p = rotateLine(pt.clone().sub(this.Center), -this.Angle); let p = rotatePoint(pt.clone().sub(this.Center), -this.Angle);
let a = this.RadX; let a = this.RadX;
let b = this.RadY; let b = this.RadY;
return Math.pow(p.x, 2) / Math.pow(a, 2) + Math.pow(p.y, 2) / Math.pow(b, 2) < 1 return Math.pow(p.x, 2) / Math.pow(a, 2) + Math.pow(p.y, 2) / Math.pow(b, 2) < 1

@ -1,5 +1,6 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Box3, Geometry, Matrix4, Object3D, Vector3 } from 'three'; import { Box3, Geometry, Matrix4, Object3D, Vector3 } from 'three';
import { matrixIsCoplane } from '../Common/Matrix4Utils';
import { RenderType } from '../GraphicsSystem/Enum'; import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { Factory } from './CADFactory'; import { Factory } from './CADFactory';
@ -7,7 +8,6 @@ import { CADFile } from './CADFile';
import { CADObject } from './CADObject'; import { CADObject } from './CADObject';
import { ObjectId } from './ObjectId'; import { ObjectId } from './ObjectId';
/** /**
* Entity ,. * Entity ,.
* *
@ -41,7 +41,6 @@ export class Entity extends CADObject
{ {
return this.m_Color; return this.m_Color;
} }
/** /**
* *
* *
@ -80,6 +79,18 @@ export class Entity extends CADObject
return new Matrix4().getInverse(this.m_Matrix); return new Matrix4().getInverse(this.m_Matrix);
} }
/**
* .
*
* @param {Entity} e
* @returns {boolean}
* @memberof Entity
*/
IsCoplaneTo(e: Entity): boolean
{
return matrixIsCoplane(this.m_Matrix, e.OCS);
}
/** /**
* . * .
* *
@ -150,7 +161,6 @@ export class Entity extends CADObject
*/ */
Update() Update()
{ {
let ocs = this.OCS; let ocs = this.OCS;
for (let [type, en] of this.m_DrawEntity) for (let [type, en] of this.m_DrawEntity)
{ {

@ -1,4 +1,3 @@
//直线对象
import * as THREE from 'three'; import * as THREE from 'three';
import { Box3, Geometry, Object3D, Vector3 } from 'three'; import { Box3, Geometry, Object3D, Vector3 } from 'three';
import { arraySortByNumber } from '../Common/ArrayExt'; import { arraySortByNumber } from '../Common/ArrayExt';

@ -1,11 +1,11 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Box3, Geometry, Matrix4, Object3D, Vector2, Vector3 } from 'three'; import { Box3, Geometry, Matrix4, Object3D, Vector2, Vector3 } from 'three';
import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard'; import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard';
import { arrayLast } from '../Common/ArrayExt'; import { arrayLast, arrayRemove } from '../Common/ArrayExt';
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { Vec2DTo3D, Vec3DTo2D, getDeterminant, rotateLine } from '../Common/CurveUtils'; import { Vec2DTo3D, Vec3DTo2D, getDeterminantFor2V } from '../Common/CurveUtils';
import { FixIndex } from '../Common/Utils'; import { FixIndex } from '../Common/Utils';
import { equal, equaln, updateGeometry } from '../Geometry/GeUtils'; import { equal, equaln, updateGeometry, rotatePoint } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum'; import { RenderType } from '../GraphicsSystem/Enum';
import { IntersectOption, IntersectPolylineAndCurve } from '../GraphicsSystem/IntersectWith'; import { IntersectOption, IntersectPolylineAndCurve } from '../GraphicsSystem/IntersectWith';
import { angleTo } from './../Geometry/GeUtils'; import { angleTo } from './../Geometry/GeUtils';
@ -75,6 +75,78 @@ export class Polyline extends Curve
{ {
return this.m_LineData; return this.m_LineData;
} }
get NumberOfVertices(): number
{
return this.m_LineData.length;
}
/**
* .
* :
* pl.AddVertexAt(pl.NumberOfVerticesk,p);//在末尾插入一个点
*
* @param {number} index
* @param {Vector2} pt
* @returns {this}
* @memberof Polyline
*/
AddVertexAt(index: number, pt: Vector2): this
{
this.WriteAllObjectRecord();
this.m_LineData.splice(index, 0, { pt: pt.clone(), bul: 0 });
this.Update();
return this;
}
RemoveVertexAt(index: number): this
{
if (index < this.m_LineData.length)
{
this.m_LineData.splice(index, 1);
this.Update();
}
return this;
}
GetPoint2dAt(index: number): Vector2 | undefined
{
if (index >= 0 && this.m_LineData.length > index)
return this.m_LineData[index].pt.clone();
}
/**
*
*
* @param {number} index
* @param {Vector2} pt
* @memberof Polyline
*/
SetPointAt(index: number, pt: Vector2): this
{
let d = this.m_LineData[index];
if (d)
{
this.WriteAllObjectRecord();
d.pt.copy(pt);
this.Update();
}
return this;
}
SetBulgeAt(index: number, bul: number): this
{
let d = this.m_LineData[index];
if (d)
{
this.WriteAllObjectRecord();
d.bul = bul;
this.Update();
}
return this;
}
GetBuilgeAt(index: number): number
{
return this.m_LineData[index].bul;
}
//多段线起点 //多段线起点
get StartPoint() get StartPoint()
{ {
@ -120,7 +192,7 @@ export class Polyline extends Curve
let startV = this.m_LineData[i]; let startV = this.m_LineData[i];
let endV = this.m_LineData[i + 1]; let endV = this.m_LineData[i + 1];
area += getDeterminant(startV.pt, endV.pt) / 2; area += getDeterminantFor2V(startV.pt, endV.pt) / 2;
if (startV.bul != 0) if (startV.bul != 0)
{ {
@ -132,7 +204,7 @@ export class Polyline extends Curve
{ {
let startV = arrayLast(this.m_LineData); let startV = arrayLast(this.m_LineData);
let endV = this.m_LineData[0]; let endV = this.m_LineData[0];
area += getDeterminant(startV.pt, endV.pt) / 2 area += getDeterminantFor2V(startV.pt, endV.pt) / 2
} }
return area; return area;
} }
@ -670,7 +742,7 @@ export class Polyline extends Curve
if (equaln(startV.pt.distanceTo(endV.pt), 0)) return; if (equaln(startV.pt.distanceTo(endV.pt), 0)) return;
let tarLine = this.GetFistDeriv(param).normalize(); let tarLine = this.GetFistDeriv(param).normalize();
//偏移向量 //偏移向量
let moveVec = rotateLine(tarLine, Math.PI / 2).multiplyScalar(-dist); let moveVec = rotatePoint(tarLine, Math.PI / 2).multiplyScalar(-dist);
//偏移矩阵 //偏移矩阵
let mat = new Matrix4().makeTranslation(moveVec.x, moveVec.y, moveVec.z); let mat = new Matrix4().makeTranslation(moveVec.x, moveVec.y, moveVec.z);
let originLine = Vec2DTo3D(endV.pt.clone().sub(startV.pt)); let originLine = Vec2DTo3D(endV.pt.clone().sub(startV.pt));
@ -678,7 +750,7 @@ export class Polyline extends Curve
startV.pt = Vec3DTo2D(Vec2DTo3D(startV.pt).applyMatrix4(mat)); startV.pt = Vec3DTo2D(Vec2DTo3D(startV.pt).applyMatrix4(mat));
if (startV.bul !== 0) if (startV.bul !== 0)
{ {
moveVec = rotateLine(moveVec, Math.atan(startV.bul) * 4); moveVec = rotatePoint(moveVec, Math.atan(startV.bul) * 4);
} }
mat.makeTranslation(moveVec.x, moveVec.y, moveVec.z); mat.makeTranslation(moveVec.x, moveVec.y, moveVec.z);
endV.pt = Vec3DTo2D(Vec2DTo3D(endV.pt).applyMatrix4(mat)); endV.pt = Vec3DTo2D(Vec2DTo3D(endV.pt).applyMatrix4(mat));
@ -1352,7 +1424,7 @@ export class Polyline extends Curve
return { pts, buls }; return { pts, buls };
} }
CreateCurve() private CreateCurve()
{ {
let { pts, buls } = this.PtsBuls; let { pts, buls } = this.PtsBuls;
let curve = CreateBoardUtil.createPath(pts, buls); let curve = CreateBoardUtil.createPath(pts, buls);
@ -1391,7 +1463,7 @@ export class Polyline extends Curve
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
let vLoc = Vec3DTo2D(moveVec.clone().applyMatrix4(this.OCSInv)); let moveVLoc = Vec3DTo2D(moveVec.clone().applyMatrix4(new Matrix4().extractRotation(this.OCSInv)));
for (let index of indexList) for (let index of indexList)
{ {
@ -1404,18 +1476,14 @@ export class Polyline extends Curve
let d = this.m_LineData[ptIndex]; let d = this.m_LineData[ptIndex];
if (d.bul == 0) if (d.bul == 0)
{ {
this.m_LineData[ptIndex].pt.add(vLoc); this.m_LineData[ptIndex].pt.add(moveVLoc);
this.m_LineData[nextIndex].pt.add(vLoc); this.m_LineData[nextIndex].pt.add(moveVLoc);
} }
else else
{ {
// 以下代码保证了中心点不变 let arc = this.GetCurveAtIndex(ptIndex) as Arc;
let arcStartPoint = this.GetPointAtParam(ptIndex); arc.MoveSnapPoints([1], moveVec);
let arcMidP = this.GetPointAtParam(ptIndex + 0.5).add(moveVec); this.m_LineData[ptIndex].bul = Math.tan(arc.AllAngle * 0.25) * (arc.IsClockWise ? -1 : 1);
let arcEndPoint = this.GetPointAtParam(nextIndex);
let arc = new Arc().FromThreePoint(arcStartPoint, arcMidP, arcEndPoint);
this.m_LineData[ptIndex].bul = Math.tan(arc.AllAngle * 0.25) * (equal(arc.StartPoint, arcStartPoint) && arc.IsClockWise ? -1 : 1);
} }
} }
} }
@ -1444,7 +1512,9 @@ export class Polyline extends Curve
MoveStretchPoints(indexList: Array<number>, vec: Vector3) MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
let moveVc = new Vector2(vec.x, vec.y);
//本地坐标系移动向量
let moveVLoc = vec.clone().applyMatrix4(new Matrix4().extractRotation(this.OCSInv));
let ptCout = this.m_LineData.length; let ptCout = this.m_LineData.length;
@ -1495,7 +1565,7 @@ export class Polyline extends Curve
ChangeBul(nextIndex, index); ChangeBul(nextIndex, index);
//修改顶点 //修改顶点
this.m_LineData[index].pt.add(Vec3DTo2D(vec)); this.m_LineData[index].pt.add(Vec3DTo2D(moveVLoc));
} }
this.Update(); this.Update();
} }

@ -59,29 +59,13 @@ export class Region extends Entity
} }
BooleanOper(otherRegion: Region, boolType: BoolOpeartionType) BooleanOper(otherRegion: Region, boolType: BoolOpeartionType)
{ {
this.WriteAllObjectRecord(); if (this.IsCoplaneTo(otherRegion))
//法线共面
if (!isParallelTo(this.Normal, otherRegion.Normal))
{
console.log("对象不共面1");
return;
}
//高共面
let pt = otherRegion.Position;
//变换到自身对象坐标系.
pt.applyMatrix4(this.OCSInv);
if (!equaln(pt.z, 0))
{ {
console.log("对象不共面2"); this.WriteAllObjectRecord();
return;
}
this.m_ShapeManager.BoolOper(otherRegion.m_ShapeManager, boolType); this.m_ShapeManager.BoolOper(otherRegion.m_ShapeManager, boolType);
this.Update(); this.Update();
} }
}
InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D
{ {
let regionGroup = new Group(); let regionGroup = new Group();

@ -32,7 +32,6 @@ export class Text extends Entity
protected FONTSIZE = 0.2; protected FONTSIZE = 0.2;
//字体粗细 //字体粗细
protected PROVISITION = -0.1; protected PROVISITION = -0.1;
Normal: Vector3 = new Vector3(0, 0, 1);
m_fontWidth: number; m_fontWidth: number;
textArea: HTMLTextAreaElement; textArea: HTMLTextAreaElement;
constructor(pos?: Vector3, str?: string, h?: number, ro?: number) constructor(pos?: Vector3, str?: string, h?: number, ro?: number)

@ -12,7 +12,7 @@ import { DrawLinearDimension } from '../Add-on/DrawDim/DrawLinearDimension';
import { DrawEllipse } from '../Add-on/DrawEllipse'; import { DrawEllipse } from '../Add-on/DrawEllipse';
import { DrawFloor } from '../Add-on/DrawFloor'; import { DrawFloor } from '../Add-on/DrawFloor';
import { DrawGripStretch } from '../Add-on/DrawGripStretch'; import { DrawGripStretch } from '../Add-on/DrawGripStretch';
import { DrawCircle, DrawLine, DrawRect, DrawSphere, DrawTest, ZoomE } from '../Add-on/DrawLine'; import { DrawCircle, DrawLine, DrawSphere, DrawTest, ZoomE } from '../Add-on/DrawLine';
import { DrawPolyline } from '../Add-on/DrawPolyline'; import { DrawPolyline } from '../Add-on/DrawPolyline';
import { DrawRegion } from '../Add-on/DrawRegion'; import { DrawRegion } from '../Add-on/DrawRegion';
import { DrawSky } from '../Add-on/DrawSky'; import { DrawSky } from '../Add-on/DrawSky';
@ -52,12 +52,14 @@ import { Fbx } from '../Add-on/loadfbx';
import { Command_PLTest } from '../Add-on/polytest'; import { Command_PLTest } from '../Add-on/polytest';
import { Command_PtInCu } from '../Add-on/ptincu'; import { Command_PtInCu } from '../Add-on/ptincu';
import { Command_Ssget } from '../Add-on/ssget'; import { Command_Ssget } from '../Add-on/ssget';
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
import { TestIntersect } from '../Add-on/test/testIntersect';
import { TestBoolOperationUtil } from '../Add-on/testEntity/TestBoolOperation';
import { Command_DimTest } from '../DatabaseServices/Dimension/dimTest'; import { Command_DimTest } from '../DatabaseServices/Dimension/dimTest';
import { commandMachine } from './CommandMachine'; import { commandMachine } from './CommandMachine';
import { TestBoolOperationUtil } from '../Add-on/testEntity/TestBoolOperation'; import { DrawRect } from '../Add-on/DrawRec';
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
export function registerCommand() export function registerCommand()
{ {
commandMachine.RegisterCommand("l", new DrawLine()) commandMachine.RegisterCommand("l", new DrawLine())
@ -170,6 +172,8 @@ export function registerCommand()
commandMachine.RegisterCommand("testbool", new TestBoolOperationUtil()); commandMachine.RegisterCommand("testbool", new TestBoolOperationUtil());
commandMachine.RegisterCommand("join", new Command_Join()); commandMachine.RegisterCommand("join", new Command_Join());
commandMachine.RegisterCommand("testInt", new TestIntersect());
// commandMachine.RegisterCommand("st", new SaveTarget()) // commandMachine.RegisterCommand("st", new SaveTarget())
// commandMachine.RegisterCommand("rt", new RevTarget()) // commandMachine.RegisterCommand("rt", new RevTarget())

@ -40,7 +40,6 @@ export class Editor
m_KeywordsServices: GetKeyWordsServices; m_KeywordsServices: GetKeyWordsServices;
//用户坐标系 //用户坐标系
private m_UCSMatrix = new THREE.Matrix4();
constructor(app: ApplicationService) constructor(app: ApplicationService)
{ {
this.m_App = app; this.m_App = app;

@ -11,7 +11,6 @@ import { Editor, EditorService } from './Editor';
import { MouseControls } from './MouseControls'; import { MouseControls } from './MouseControls';
import { commandMachine } from './CommandMachine'; import { commandMachine } from './CommandMachine';
export class SnapDragServices implements EditorService export class SnapDragServices implements EditorService
{ {

@ -1,14 +1,14 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { GetPointPrompt } from '../Common/InputState'; import { GetPointPrompt } from '../Common/InputState';
import { Entity } from '../DatabaseServices/Entity'; import { Entity } from '../DatabaseServices/Entity';
import { equaln, fixAngle, polar } from '../Geometry/GeUtils'; import { equaln, fixAngle, polar } from '../Geometry/GeUtils';
import { IntersectLAndL } from '../GraphicsSystem/IntersectWith'; import { IntersectLAndLFor3D } from '../GraphicsSystem/IntersectWith';
import { PreViewer } from '../GraphicsSystem/PreViewer'; import { PreViewer } from '../GraphicsSystem/PreViewer';
//捕捉轴 //捕捉轴
interface SnapAxis interface SnapAxis
{ {
@ -104,7 +104,7 @@ export class SnapServices
for (let j = i + 1; j < snapAxisList.length; j++) for (let j = i + 1; j < snapAxisList.length; j++)
{ {
let axis2 = snapAxisList[j]; let axis2 = snapAxisList[j];
let insP = IntersectLAndL(axis1.BasePoint, axis1.SnapPoint, axis2.BasePoint, axis2.SnapPoint); let insP = IntersectLAndLFor3D(axis1.BasePoint, axis1.SnapPoint, axis2.BasePoint, axis2.SnapPoint);
if (insP) if (insP)
axisIntersectList.push({ axisIntersectList.push({
IntersectPoint: insP, IntersectPoint: insP,

@ -1,6 +1,6 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Geometry, Vector, Vector2, Vector3 } from 'three'; import { Geometry, Vector, Vector2, Vector3 } from 'three';
import { rotateLine } from '../Common/CurveUtils'; import { Matrix2 } from './Matrix2';
export const cZeroVec = new THREE.Vector3(); export const cZeroVec = new THREE.Vector3();
@ -8,6 +8,20 @@ export const cXAxis = new THREE.Vector3(1, 0, 0);
export const cYAxis = new THREE.Vector3(0, 1, 0); export const cYAxis = new THREE.Vector3(0, 1, 0);
export const cZAxis = new THREE.Vector3(0, 0, 1); export const cZAxis = new THREE.Vector3(0, 0, 1);
/**
* ,
*
* @export
* @param {Vector3} pt
* @param {number} ang .
* @returns {Vector3} pt.
*/
export function rotatePoint(pt: Vector3, ang: number): Vector3
{
new Matrix2().setRotate(ang).applyVector(pt);
return pt;
}
export function equaln(v1: number, v2: number, fuzz = 1e-3) export function equaln(v1: number, v2: number, fuzz = 1e-3)
{ {
return Math.abs(v1 - v2) < fuzz; return Math.abs(v1 - v2) < fuzz;
@ -150,7 +164,7 @@ export function midPtCir(v1: THREE.Vector3, v2: THREE.Vector3)
let baseline = new Vector3(1, 0, 0); let baseline = new Vector3(1, 0, 0);
let outLine = v2.clone().sub(v1); let outLine = v2.clone().sub(v1);
let ang = angleTo(baseline, outLine) / 2; let ang = angleTo(baseline, outLine) / 2;
let midLine = rotateLine(outLine, -ang); let midLine = rotatePoint(outLine, -ang);
return v1.clone().add(midLine); return v1.clone().add(midLine);
} }

@ -1,6 +1,5 @@
import { Vector3 } from 'three'; import { Vector3 } from 'three';
import { getDeterminantFor3V } from '../Common/CurveUtils';
import { Vec2DTo3D, Vec3DTo2D } from '../Common/CurveUtils';
import { Arc } from '../DatabaseServices/Arc'; import { Arc } from '../DatabaseServices/Arc';
import { Circle } from '../DatabaseServices/Circle'; import { Circle } from '../DatabaseServices/Circle';
import { Curve } from '../DatabaseServices/Curve'; import { Curve } from '../DatabaseServices/Curve';
@ -8,6 +7,7 @@ import { Line } from '../DatabaseServices/Line';
import { Polyline } from '../DatabaseServices/Polyline'; import { Polyline } from '../DatabaseServices/Polyline';
import { equal, equaln, midPoint } from '../Geometry/GeUtils'; import { equal, equaln, midPoint } from '../Geometry/GeUtils';
/** /**
* . * .
* *
@ -60,28 +60,23 @@ function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: Int
}) })
} }
/** export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc)
* ,,.
*
* @export
* @param {(Circle | Arc)} c1
* @param {(Circle | Arc)} c2
* @returns
*/
export function IntersectCircleAndCircle(c1: Circle | Arc, c2: Circle | Arc)
{ {
let center1 = c1.Center; if (!cu1.IsCoplaneTo(cu2)) return [];
let center2 = c2.Center;
let radius1 = c1.Radius; let c1OcsInv = cu1.OCSInv;
let radius2 = c2.Radius; let c1Ocs = cu1.OCS;
let center1 = cu1.Center.applyMatrix4(c1OcsInv);
let center2 = cu2.Center.applyMatrix4(c1OcsInv);
let radius1 = cu1.Radius;
let radius2 = cu2.Radius;
let pts: Vector3[] = []; let pts: Vector3[] = [];
let dist = center2.distanceTo(center1); let dist = center2.distanceTo(center1);
if (dist > (radius1 + radius2 + 1e-3)) if (dist > (radius1 + radius2 + 1e-3))
{
return pts; return pts;
}
let dstsqr = dist * dist; let dstsqr = dist * dist;
let r1sqr = radius1 * radius1; let r1sqr = radius1 * radius1;
@ -99,21 +94,20 @@ export function IntersectCircleAndCircle(c1: Circle | Arc, c2: Circle | Arc)
let phix = center1.x + (ratio_a * dx); let phix = center1.x + (ratio_a * dx);
let phiy = center1.y + (ratio_a * dy); let phiy = center1.y + (ratio_a * dy);
dx = dx * ratio_h; dx *= ratio_h;
dy = dy * ratio_h; dy *= ratio_h;
let pt = new Vector3(phix + dy, phiy - dx); let p1 = new Vector3(phix + dy, phiy - dx);
let p2 = new Vector3(phix - dy, phiy + dx); let p2 = new Vector3(phix - dy, phiy + dx);
p1.applyMatrix4(c1Ocs);
p2.applyMatrix4(c1Ocs);
pts.push(pt); pts.push(p1);
if (!equal(pt, p2))//防止点重复 if (!equal(p1, p2))//防止点重复
{
pts.push(p2); pts.push(p2);
}
return pts; return pts;
} }
/** /**
* . * .
* *
@ -154,9 +148,9 @@ export function IntersectArcAndArc(arc1: Arc, arc2: Arc, extType: IntersectOptio
*/ */
function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc) function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
{ {
let startPoint = Vec3DTo2D(line.StartPoint); let startPoint = line.StartPoint;
let endPoint = Vec3DTo2D(line.EndPoint); let endPoint = line.EndPoint;
let center = Vec3DTo2D(circle.Center); let center = circle.Center;
let radius = circle.Radius; let radius = circle.Radius;
let a = endPoint.distanceToSquared(startPoint); let a = endPoint.distanceToSquared(startPoint);
@ -171,16 +165,16 @@ function IntersectLineAndCircleOrArc(line: Line, circle: Circle | Arc)
if (equaln(det, 0, 1e-5)) if (equaln(det, 0, 1e-5))
{ {
let delta = -b / (2 * a); let delta = -b / (2 * a);
return [Vec2DTo3D(startPoint.add(lineV.multiplyScalar(delta)))]; return [startPoint.add(lineV.multiplyScalar(delta))];
} }
else if (det > 0) else if (det > 0)
{ {
let sqrt_det = Math.sqrt(det); let sqrt_det = Math.sqrt(det);
let delta = (-b + sqrt_det) / (2 * a); let delta = (-b + sqrt_det) / (2 * a);
let p2 = Vec2DTo3D(startPoint.clone().add(lineV.clone().multiplyScalar(delta))); let p2 = startPoint.clone().add(lineV.clone().multiplyScalar(delta));
delta = (-b - sqrt_det) / (2 * a); delta = (-b - sqrt_det) / (2 * a);
let p3 = Vec2DTo3D(startPoint.clone().add(lineV.multiplyScalar(delta))); let p3 = startPoint.clone().add(lineV.multiplyScalar(delta));
return [p2, p3]; return [p2, p3];
} }
@ -200,7 +194,7 @@ export function IntersectLineAndArc(line: Line, arc: Arc, extType: IntersectOpti
return CheckPointOnCurve(ptArr, line, arc, extType); return CheckPointOnCurve(ptArr, line, arc, extType);
} }
//直线和直线 //直线和直线
export function IntersectLAndL(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3): Vector3 export function IntersectLAndLFor2D(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3): Vector3
{ {
let dx1 = p1.x - p2.x; let dx1 = p1.x - p2.x;
let dx2 = p3.x - p4.x; let dx2 = p3.x - p4.x;
@ -227,11 +221,55 @@ export function IntersectLAndL(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector
return pt; return pt;
} }
export function IntersectLAndLFor3D(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3)
{
let x12 = p1.x - p2.x;
let x43 = p4.x - p3.x;
let x42 = p4.x - p2.x;
let y12 = p1.y - p2.y;
let y43 = p4.y - p3.y;
let y42 = p4.y - p2.y;
let z12 = p1.z - p2.z;
let z43 = p4.z - p3.z;
let z42 = p4.z - p2.z;
let pt: Vector3;
let v1 = p2.clone().sub(p1).normalize();
let v2 = p4.clone().sub(p3).normalize();
let w = p3.clone().sub(p1);
if (Math.abs(v1.dot(v2)) === 1)
{
let tmpLine = new Line(p1, p2);
let par = tmpLine.GetParamAtPoint(p3);
if (par)
{
pt = midPoint(midPoint(p1, p2), midPoint(p3, p4));
}
}
else if (equaln(getDeterminantFor3V(v1, v2, w), 0, 0.01))
{
let t: number;
if (x12 * y43 - y12 * x43)
{
t = (x42 * y43 - x43 * y42) / (x12 * y43 - y12 * x43);
}
else if (x12 * z43 - x43 * z12)
{
t = (x42 * z43 - x43 * z42) / (x12 * z43 - x43 * z12);
}
else
{
t = (y42 * z43 - y43 * z42) / (y12 * z43 - y43 * z12);
}
pt = new Vector3(x12 * t + p2.x, y12 * t + p2.y, z12 * t + p2.z);
}
return pt;
}
//直线和直线 //直线和直线
export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption) export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption)
{ {
let pt = IntersectLAndL(l1.StartPoint, l1.EndPoint, l2.StartPoint, l2.EndPoint); let pt = IntersectLAndLFor3D(l1.StartPoint, l1.EndPoint, l2.StartPoint, l2.EndPoint);
return pt ? CheckPointOnCurve([pt], l1, l2, extType) : []; return pt ? CheckPointOnCurve([pt], l1, l2, extType) : [];
} }

Loading…
Cancel
Save