合并arc分支

pull/15/head
ChenX 7 years ago
parent 9ec2ff2032
commit fcd97ae825

@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`三点圆心 1`] = `3.141592653589793`;
exports[`三点圆心 2`] = `0`;

@ -0,0 +1,61 @@
import { Arc } from '../../src/DatabaseServices/Arc';
import { Vector3, Vector2 } from 'three';
import { app } from '../../src/ApplicationServices/Application';
import { Command } from '../../src/Editor/CommandMachine';
import { PromptStatus } from '../../src/Editor/PromptResult';
import { RenderType } from '../../src/GraphicsSystem/Enum';
test("三点共线", () =>
{
let pt1 = new Vector3(0, 0, 0);
let pt2 = new Vector3(0, 1, 0);
let pt3 = new Vector3(0, 2, 0);
let arc = new Arc();
arc.FromThreePoint(pt1, pt2, pt3);
console.log(arc.Center);
console.log(arc.StartAngle);
console.log(arc.EndAngle);
console.log(arc.Radius);
expect(arc.Center.toArray()).toMatchObject([0, 0, 0]);
})
test("三点圆心", () =>
{
let arc = new Arc();
arc.FromThreePoint(
new Vector3(0, 0, 0),
new Vector3(5, 5, 0),
new Vector3(10, 0, 0)
)
console.log(arc.StartAngle);
console.log(arc.EndAngle);
expect(arc.Center.toArray()).toMatchObject([5, 0, 0]);
expect(arc.StartAngle).toMatchSnapshot();
expect(arc.EndAngle).toMatchSnapshot();
})
test("三点同一位置", () =>
{
let arc = new Arc();
arc.FromThreePoint(
new Vector3(5, 5, 0),
new Vector3(5, 5, 0),
new Vector3(5, 5, 0)
)
console.log(arc.StartAngle);
console.log(arc.EndAngle);
expect(arc.Center.toArray()).toMatchObject([0, 0, 0]);
expect(arc.StartAngle).toMatchSnapshot();
expect(arc.EndAngle).toMatchSnapshot();
})

@ -40,7 +40,10 @@ export class DrawArc implements Command
{
arc.FromThreePoint(pt1, pt2, p);
arc.Update();
app.m_Database.ModelSpace.Append(arc);
if (!arc.Id)
{
app.m_Database.ModelSpace.Append(arc);
}
}
}
});

@ -1,12 +1,12 @@
import { EllipseCurve, Geometry, Vector3, ShapeGeometry, Matrix4, Vector2 } from 'three';
import { Matrix4, ShapeGeometry, Vector3 } from 'three';
import * as THREE from 'three';
import { polar } from '../Geometry/GeUtils';
import { ColorMaterial } from '../Common/ColorPalette';
import { getArcAngle, isAtArc, Vec3DTo2D } from '../Common/CurveUtils';
import { equal, polar } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum';
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
import { Entity } from './Entity';
import { Curve } from './Curve';
@ -83,56 +83,287 @@ export class Arc extends Curve
this.m_EndAngle = v <= 0 ? 1e-19 : v;
this.Update();
}
//******************** Curve function start*****************//
get StartPoint()
{
let startPoint = new Vector3();
polar(startPoint, this.m_StartAngle, this.m_Radius);
return this.m_Center.clone().add(startPoint);
let startPt = new Vector3();
polar(startPt, this.m_StartAngle, this.m_Radius);
startPt = this.m_Center.clone().add(startPt);
return startPt;
}
get EndPoint()
{
let endtPt = new Vector3();
polar(endtPt, this.m_EndAngle, this.m_Radius);
endtPt = this.m_Center.clone().add(endtPt);
return endtPt;
}
get StartParam()
{
let startPm: number = 0.0;
return startPm;
}
get EndParam()
{
let endPm: number = 1.0;
return endPm;
}
GetPointAtParam(param: number)
{
if (0 <= param && param <= 1)
{
param = 1 - param;
let ptAtpm = new Vector3();
let angle = this.GetParamAngle(param);
polar(ptAtpm, this.GetParamAngle(param), this.m_Radius);
ptAtpm = this.m_Center.clone().add(ptAtpm);
console.log(ptAtpm);
return ptAtpm;
}
}
GetPointAtDistance(distance: number)
{
if (distance <= (Math.abs(this.getArcBul()) * this.m_Radius))//长度不能超过总弧长
{
let ptAtDist = new Vector3();
let propor = distance / this.getArcBul();
polar(ptAtDist, Math.abs(this.getArcBul(propor)), this.m_Radius);
ptAtDist = this.m_Center.clone().add(ptAtDist);
return ptAtDist;
}
}
GetDistAtParam(param: number)
{
if (0 <= param && param <= 1)
{
let distAtPm: number = 0;
distAtPm = Math.abs(this.getArcBul(param)) * this.m_Radius;
return distAtPm;
}
}
GetDistAtPoint(pt?: Vector3)
{
if (!pt)
{
return;
}
let dist: number = 0;
//求出点1和点2的中点
let midpt = new Vector3(0, 0, 0);
let startPt = new Vector3(0, 0, 0);
polar(startPt, this.m_StartAngle, this.m_Radius);
startPt = this.m_Center.clone().add(startPt);
midpt.x = (pt.x + startPt.x) / 2;
midpt.y = (pt.y + startPt.y) / 2;
let length = this.m_Center.distanceTo(midpt);
if (length)
{
dist = Math.acos(length / this.m_Radius) * 2 * this.m_Radius;
if (Math.abs(this.getArcBul()) > Math.PI)
dist = 2 * Math.PI * this.m_Radius - dist;
}
else
{
dist = Math.PI * this.m_Radius;
}
return dist;
}
// GetFistDeriv(param: number | Vector3)
// {
// if (typeof (param) === "number")
// {
// param = this.GetPointAtParam(param);
// }
// let fistDeriv = -((param.x - this.m_Center.x) / (param.y - this.m_Center.y)) || 0;
// if (equaln(param.x, this.m_Center.x))
// {
// fistDeriv = 1;
// }
// return fistDeriv;
// }
GetSplitCurves(param: number[] | number)
{
let anglelist = new Array<number>();
let curvelist = new Array<Arc>();
anglelist.push(this.m_StartAngle);
if (param instanceof Array)
{
for (let pm of param)
{
anglelist.push(this.GetParamAngle(pm));
}
}
else
{
anglelist.push(this.GetParamAngle(param));
}
anglelist.push(this.m_EndAngle);
for (let i = 0; i < anglelist.length - 1; i++)
{
let arc = new Arc();
arc.m_Center = this.m_Center;
arc.m_Radius = this.m_Radius;
arc.m_Normal = this.m_Normal;
arc.m_StartAngle = anglelist[i];
arc.m_EndAngle = anglelist[i + 1];
curvelist.push(arc);
}
return curvelist;
}
PtOnCurve(pt: Vector3)
{
let isOnArc = false;
let startPoint = new Vector3();
let endPoint = new Vector3();
polar(startPoint, this.m_StartAngle, this.m_Radius);
polar(endPoint, this.m_EndAngle, this.m_Radius);
return this.m_Center.clone().add(endPoint);
startPoint = this.m_Center.clone().add(startPoint);
endPoint = this.m_Center.clone().add(endPoint);
if (equal(startPoint, pt) || equal(endPoint, pt))//如果是是起始点和终止点
{
isOnArc = true;
return isOnArc;
}
isOnArc = isAtArc(Vec3DTo2D(startPoint), Vec3DTo2D(endPoint), Math.tan(this.getArcBul() / 4), pt);
return isOnArc;
}
GetOffsetCurves(offsetDist: number)
{
let arcArr = new Array<Curve>();
if ((offsetDist + this.m_Radius) > 0)
{
let arc = new Arc();
arc.m_Center = this.m_Center;
arc.m_Radius = this.m_Radius + offsetDist;
arc.m_Normal = this.m_Normal;
arc.m_StartAngle = this.m_StartAngle;
arc.m_EndAngle = this.m_EndAngle;
arcArr.push(arc);
}
return arcArr;
}
Extend(newParam: number)
{
if (0 > newParam || newParam > 1)
{
if (newParam > 1)
{
newParam -= 1;
}
let allAngle = Math.abs(this.getArcBul(newParam));
if (allAngle + Math.abs(this.getArcBul()) < (2 * Math.PI))//原弧长+延伸<圆
{
this.SetExtendPointAngle(newParam, allAngle);
}
}
}
//******************** Curve function end*****************//
SetExtendPointAngle(newParam: number, allAngle: number)
{
let pmXAngle: number = 0;
if (0 > newParam)
{
if (this.m_StartAngle + allAngle > 2 * Math.PI)
this.m_StartAngle = this.m_StartAngle + allAngle - 2 * Math.PI;
else
this.m_StartAngle = this.m_StartAngle + allAngle;
}
else
{
if (this.m_EndAngle - allAngle >= 0)
this.m_EndAngle = this.m_EndAngle - allAngle;
else
this.m_EndAngle = this.m_EndAngle - allAngle + 2 * Math.PI;
}
}
getArcBul(param: number = 1)//圆心角
{
let ptArr = this.GetStretchPoints();
return getArcAngle(ptArr[0], ptArr[1], ptArr[2]) * param;
}
GetParamAngle(param: number)//返回相对于x轴正方向所形成的角度
{
let pmAngle = 0;
if (this.m_EndAngle < this.m_StartAngle)
{
pmAngle = (this.m_StartAngle - this.m_EndAngle) * param + this.m_EndAngle;
}
else
{
pmAngle = (this.m_EndAngle - this.m_StartAngle) * param + this.m_StartAngle + Math.PI;
}
return pmAngle;
}
FromThreePoint(pt1?: Vector3, pt2?: Vector3, pt3?: Vector3)
{
if (!(pt1 && pt2 && pt3))
return;
//定义两个点,分别表示两个中点
let midpt1 = new Vector3(0, 0, 0);
let midpt2 = new Vector3(0, 0, 0);
//求出点1和点2的中点
midpt1.x = (pt2.x + pt1.x) / 2;
midpt1.y = (pt2.y + pt1.y) / 2;
//求出点3和点1的中点 a
midpt2.x = (pt3.x + pt1.x) / 2;
midpt2.y = (pt3.y + pt1.y) / 2;
//求出分别与直线pt1pt2pt1pt3垂直的直线的斜率
let k1 = -(pt2.x - pt1.x) / (pt2.y - pt1.y);
let k2 = -(pt3.x - pt1.x) / (pt3.y - pt1.y);
if (k1 !== k2)//不共线
// 通过三个点到圆心距离相等建立方程:
// (2 * pt2.x - 2 * pt1.x) * center.x + (2 * pt1.y - 2 * pt2.y) * center.y=pt1.y2+pt2.x2-pt1.x2-pt2.y2
// (2 * pt3.x - 2 * pt2.x) * center.x + (2 * pt2.y - 2 * pt3.y) * center.y=pt2.y2+pt3.x2-pt2.x2-pt3.y2
// 令:
// a1 = 2 * pt2.x - 2 * pt1.x b1 = 2 * pt1.y - 2 * pt2.y c1 = pt1.y2+pt2.x2-pt1.x2-pt2.y2
// a2 = 2 * pt3.x - 2 * pt2.x b2 = 2 * pt2.y - 2 * pt3.y c2 = pt2.y2+pt3.x2-pt2.x2-pt3.y2
// 则上述方程组变成一下形式:
// a1 * center.x + b1 * center.y=c1
// a2 * center.x + b2 * center.y=c2
// 联立以上方程组可以求出:
// center.x = (c1 * b2 - c2 * b1) / a1 * b2 - a2 * b1;
// center.y = (a1 * c2 - a2 * c1) / a1 * b2 - a2 * b1;
let a1 = pt1.x - pt2.x;
let b1 = pt1.y - pt2.y;
let c1 = (Math.pow(pt1.x, 2) - Math.pow(pt2.x, 2) + Math.pow(pt1.y, 2) - Math.pow(pt2.y, 2)) / 2;
let a2 = pt3.x - pt2.x;
let b2 = pt3.y - pt2.y;
let c2 = (Math.pow(pt3.x, 2) - Math.pow(pt2.x, 2) + Math.pow(pt3.y, 2) - Math.pow(pt2.y, 2)) / 2;
//令temp = A1*B2 - A2*B1
let temp = a1 * b2 - a2 * b1;
//判断三点是否共线
if (temp === 0)
{
//然后求出过中点midpt1斜率为k1的直线方程既pt1pt2的中垂线y - midPt1.y = k1( x - midPt1.x)
//以及过中点midpt2斜率为k2的直线方程既pt1pt3的中垂线y - midPt2.y = k2( x - midPt2.x)
//连立两条中垂线方程求解交点得到:
this.m_Center.x = (midpt2.y - midpt1.y - k2 * midpt2.x + k1 * midpt1.x) / (k1 - k2);
this.m_Center.y = midpt1.y + k1 * (midpt2.y - midpt1.y - k2 * midpt2.x + k2 * midpt1.x) / (k1 - k2);
//用圆心和其中一个点求距离得到半径:
this.m_Radius = this.m_Center.distanceTo(pt1);
//起始角度 端点角度
this.m_StartAngle = this.getangle(pt1, this.m_Center);
this.m_EndAngle = this.getangle(pt3, this.m_Center);
//求出向量p1->p2,p1->p3
let p1 = new Vector3(0, 0, 0);
p1.x = pt2.x - pt1.x;
p1.y = pt2.y - pt1.y;
let p2 = new Vector3(0, 0, 0);
p2.x = pt3.x - pt1.x;
p2.y = pt3.y - pt1.y;
//叉积
this.m_Normal = p1.clone().cross(p2).normalize();
return;
}
else
{
//不共线则求出圆心:
this.m_Center.x = (c1 * b2 - c2 * b1) / temp;
this.m_Center.y = (a1 * c2 - a2 * c1) / temp;
}
//用圆心和其中一个点求距离得到半径:
this.m_Radius = this.m_Center.distanceTo(pt1);
//起始角度 端点角度
this.m_StartAngle = this.getangle(pt1, this.m_Center);
this.m_EndAngle = this.getangle(pt3, this.m_Center);
//求出向量p1->p2,p1->p3
let p1 = new Vector3(0, 0, 0);
p1.x = pt2.x - pt1.x;
p1.y = pt2.y - pt1.y;
let p2 = new Vector3(0, 0, 0);
p2.x = pt3.x - pt1.x;
p2.y = pt3.y - pt1.y;
//叉积
//this.m_Normal = p1.clone().cross(p2).normalize();
let normal = Math.tan(getArcAngle(pt1, pt2, pt3) * 0.25);
if (normal > 0)
{
let startAngle = this.m_StartAngle;
this.m_StartAngle = this.m_EndAngle;
this.m_EndAngle = startAngle;
}
}
@ -150,7 +381,7 @@ export class Arc extends Curve
//创建
let shape = new THREE.Shape();
//圆心x,圆心y,半径,起点角度,端点角度,时针方向
shape.absarc(this.m_Center.x, this.m_Center.y, this.m_Radius, this.m_StartAngle, this.m_EndAngle, this.m_Normal.z < 0);
shape.absarc(this.m_Center.x, this.m_Center.y, this.m_Radius, this.m_StartAngle, this.m_EndAngle, true);
let geo = new THREE.Geometry().setFromPoints(shape.getPoints(60));
let arc = new THREE.Line(geo, ColorMaterial.GetLineMaterial(this.m_Color));
this.m_DrawEntity.set(renderType, arc);
@ -163,13 +394,12 @@ export class Arc extends Curve
super.Update();
for (let [, obj] of this.m_DrawEntity)
{
let geo = obj["geometry"] as Geometry;
let geo = obj["geometry"] as ShapeGeometry;
let shape = new THREE.Shape();
//圆心x,圆心y,半径,起点角度,端点角度,时针方向
shape.absarc(this.m_Center.x, this.m_Center.y, this.m_Radius, this.m_StartAngle, this.m_EndAngle, this.m_Normal.z < 0);
shape.absarc(this.m_Center.x, this.m_Center.y, this.m_Radius, this.m_StartAngle, this.m_EndAngle, true);
// //调用setFromPoints()方法, 重新设置边界.
geo.setFromPoints(shape.getPoints(60));
geo.computeBoundingSphere();
geo.verticesNeedUpdate = true;
}
@ -181,32 +411,19 @@ export class Arc extends Curve
this.m_Center.applyMatrix4(m);
this.Update();
}
GetSnapPoints(): Array<THREE.Vector3>
{
return this.GetStretchPoints();
}
GetStretchPoints(): Array<Vector3>
{
//求出圆弧的中点角度
let midptAngle = this.m_StartAngle;
if (this.m_Normal.z < 0)//顺时针
{
if (this.m_EndAngle < this.m_StartAngle)
midptAngle = (this.m_StartAngle - this.m_EndAngle) / 2 + this.m_EndAngle;
else
midptAngle = (this.m_EndAngle - this.m_StartAngle) / 2 + this.m_StartAngle + Math.PI;
}
else//逆时针
{
if (this.m_StartAngle < this.m_EndAngle)
midptAngle = (this.m_EndAngle - this.m_StartAngle) / 2 + this.m_StartAngle;
else
midptAngle = (this.m_StartAngle - this.m_EndAngle) / 2 + this.m_EndAngle + Math.PI;
}
//用角度求出三个点位置
//用角度求出三个点位置
let startPoint = new Vector3();
let endPoint = new Vector3();
let midPoint = new Vector3();
polar(startPoint, this.m_StartAngle, this.m_Radius);
polar(endPoint, this.m_EndAngle, this.m_Radius);
polar(midPoint, midptAngle, this.m_Radius);
polar(midPoint, this.GetParamAngle(0.5), this.m_Radius);
return [
this.m_Center.clone().add(startPoint),
@ -226,8 +443,14 @@ export class Arc extends Curve
if (p)
{
p.add(vec);
index > 2 ? this.m_Center = this.m_Center.add(vec) :
if (index > 2)
{
this.m_Center = this.m_Center.add(vec);
}
else
{
this.FromThreePoint(ptsArr[0], ptsArr[1], ptsArr[2]);
}
this.Update();
}
}

@ -5,7 +5,8 @@ import * as THREE from 'three';
import { ColorMaterial } from '../Common/ColorPalette';
import { equal, polar } from '../Geometry/GeUtils';
import { RenderType } from '../GraphicsSystem/Enum';
import { Intersect, IntersectLineAndLine } from '../GraphicsSystem/IntersectWith';
import { Intersect, IntersectLineAndArc, IntersectLineAndLine } from '../GraphicsSystem/IntersectWith';
import { Arc } from './Arc';
import { Factory } from './CADFactory';
import { CADFile } from './CADFile';
import { Curve } from './Curve';
@ -92,6 +93,10 @@ export class Line extends Curve
{
return IntersectLineAndLine(this, curve, intType);
}
if (curve instanceof Arc)
{
return IntersectLineAndArc(this, curve, intType);
}
//其他的尚未实现.
return [];
}

@ -1,6 +1,8 @@
import { Matrix4, Vector3 } from 'three';
import * as THREE from 'three';
import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard';
export const cZeroVec = new THREE.Vector3();
export const cXAxis = new THREE.Vector3(1, 0, 0);
export const cYAxis = new THREE.Vector3(0, 1, 0);
@ -207,3 +209,53 @@ export function Intersect(p1: THREE.Vector3, p2: THREE.Vector3, p3: THREE.Vector
return pt;
}
//2点加凸度获取圆弧中点
export function getCircleMidPt(startV: THREE.Vector2, endV: THREE.Vector2, bul: number)
{
let arc2d = new CreateBoardUtil.Arc2d(startV, endV, bul);
let circlePt = arc2d.m_Center;
//起始矢量
let startVec = startV.clone().sub(circlePt);
//终止矢量
let endVec = endV.clone().sub(circlePt);
// 将起始线终止线转3维
let startLine = new Vector3(startVec.x, startVec.y, 0);
let endLine = new Vector3(endVec.x, endVec.y, 0);
//圆心角
let circleAng = startLine.angleTo(endLine);
if (Math.abs(bul) > 1)
{
circleAng = Math.PI * 2 - circleAng;
}
circleAng *= (bul > 0 ? 1 : -1)
let mat = new THREE.Matrix4();
mat.makeRotationZ(circleAng / 2);
startLine.applyMatrix4(mat);
let cen = new Vector3(circlePt.x, circlePt.y, 0);
// 圆弧中点
return cen.add(startLine);
}//3点获取圆心
export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3)
{
//定义两个点,分别表示两个中点
let midpt1 = new Vector3(0, 0, 0);
let midpt2 = new Vector3(0, 0, 0);
//求出点1和点2的中点
midpt1.x = (pt2.x + pt1.x) / 2;
midpt1.y = (pt2.y + pt1.y) / 2;
//求出点3和点1的中点
midpt2.x = (pt3.x + pt1.x) / 2;
midpt2.y = (pt3.y + pt1.y) / 2;
//求出分别与直线pt1pt2pt1pt3垂直的直线的斜率
let k1 = -(pt2.x - pt1.x) / (pt2.y - pt1.y);
let k2 = -(pt3.x - pt1.x) / (pt3.y - pt1.y);
let center = new Vector3();
center.x = (midpt2.y - midpt1.y - k2 * midpt2.x + k1 * midpt1.x) / (k1 - k2);
center.y = midpt1.y + k1 * (midpt2.y - midpt1.y - k2 * midpt2.x + k2 * midpt1.x) / (k1 - k2);
return center;
}

@ -1,7 +1,9 @@
import { Line } from "../DatabaseServices/Line";
import { Vector2, Vector3 } from "three";
import { equaln } from "../Geometry/GeUtils";
import { Curve } from "../DatabaseServices/Curve";
import { Vector3 } from 'three';
import { Arc } from '../DatabaseServices/Arc';
import { Curve } from '../DatabaseServices/Curve';
import { Line } from '../DatabaseServices/Line';
import { equal, equaln } from '../Geometry/GeUtils';
export enum Intersect
@ -11,7 +13,32 @@ export enum Intersect
ExtendArg = 2,
ExtendBoth = 3,
}
export function IntersectLineAndArc(line: Line, arc: Arc, intType: Intersect)
{
let pts: Vector3[] = [];
let k = (line.EndPoint.y - line.StartPoint.y) / (line.EndPoint.x - line.StartPoint.x);
let b = line.EndPoint.y - k * line.EndPoint.x;
//列方程
let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
let c = Math.pow(arc.Center.x, 2) + Math.pow(b - arc.Center.y, 2) - Math.pow(arc.Radius, 2);
let a = (1 + Math.pow(k, 2));
let b1 = (2 * arc.Center.x - 2 * k * (b - arc.Center.y));
let tmp = Math.sqrt(b1 * b1 - 4 * a * c);
if (!isNaN(tmp))
{
x1 = (b1 + tmp) / (2 * a);
y1 = k * x1 + b;
x2 = (b1 - tmp) / (2 * a);
y2 = k * x2 + b;
let pt1 = new Vector3(x1, y1, 0);
let pt2 = new Vector3(x2, y2, 0);
if (line.PtOnCurve(pt1) && arc.PtOnCurve(pt1))//点在线上&&点在圆弧上
pts.push(pt1);
if (line.PtOnCurve(pt2) && arc.PtOnCurve(pt2) && !equal(pt1, pt2))//点在线上&&点在圆弧上&&不重复原来的点
pts.push(pt2);
}
return pts;
}
export function IntersectLineAndLine(l1: Line, l2: Line, intType: Intersect)
{
let p1 = l1.StartPoint;

Loading…
Cancel
Save