public static void BresenhamLine(BitmapData bitmapData, CadVertex p0, CadVertex p1, uint color) { int x0 = (int)p0.X; int y0 = (int)p0.Y; int x1 = (int)p1.X; int y1 = (int)p1.Y; int stepx; int stepy; int dx; int dy; int a; int a1; int e; if (x0 < x1) { dx = x1 - x0; stepx = 1; } else { dx = x0 - x1; stepx = -1; } if (y0 < y1) { dy = y1 - y0; stepy = 1; } else { dy = y0 - y1; stepy = -1; } int x = x0; int y = y0; int wc = bitmapData.Width; unsafe { uint *p = (uint *)bitmapData.Scan0; if (dx > dy) { a = 2 * dy; a1 = a - (2 * dx); e = a - dx; while (true) { *(p + (y * wc) + x) = color; if (x == x1) { break; } if (e >= 0) { y += stepy; e += a1; } else { e += a; } x += stepx; } } else { a = 2 * dx; a1 = a - (2 * dy); e = a - dy; while (true) { *(p + (y * wc) + x) = color; if (y == y1) { break; } if (e >= 0) { x += stepx; e += a1; } else { e += a; } y += stepy; } } } }
void CheckFig(CadLayer layer, CadFigure fig) { int n = fig.PointCount; for (int i = 0; i < n; i++) { CadVertex cp = fig.PointList[i]; CadVertex p = DC.WorldPointToDevPoint(cp); CadVertex d = p - TargetPoint; double dist = d.Norm2D(); if (dist > Range) { continue; } Result res = new ResultPoint(cp, dist, fig, i); ResultList.Add(res); } // // Create segment list that in range. // And check center point of segment // // 範囲内の線分リスト作成 // ついでに中点のチェックも行う // n = fig.SegmentCount; for (int i = 0; i < n; i++) { CadSegment seg = fig.GetSegmentAt(i); CadVertex pw = (seg.P1 - seg.P0) / 2 + seg.P0; CadVertex ps = DC.WorldPointToDevPoint(pw); double dist = (ps - TargetPoint).Norm2D(); if (dist <= Range) { Result res = new ResultSegCenter(pw, dist, fig, i); ResultList.Add(res); } CadVertex p0 = DC.WorldPointToDevPoint(seg.P0); CadVertex p1 = DC.WorldPointToDevPoint(seg.P1); double d = CadMath.DistancePointToSeg(p0.vector, p1.vector, TargetPoint.vector); if (d > Range) { continue; } SegmentItem segItem = new SegmentItem(); segItem.Layer = layer; segItem.Fig = fig; segItem.SegIndex = i; segItem.ScrSegment = new CadSegment(p0, p1); SegList.Add(segItem); } }
// 単純に頂点を追加 public int AddVertex(CadVertex v) { return(VertexStore.Add(v)); }
public ResultPoint(CadVertex wp, double dist, CadFigure fig, int index) : base(wp, dist) { Fig = fig; PointIndex = index; }
public ResultSegCenter(CadVertex wp, double dist, CadFigure fig, int segIndex) : base(wp, dist) { Fig = fig; SegIndex = segIndex; }
public static List <CadFigure> Split(CadFigure fig, int curveSplitNum = 32) { CadVertex p0 = default(CadVertex); var triangles = new List <CadFigure>(); int i1 = -1; int state = 0; CadFigure triangle; VertexList pointList = fig.GetPoints(curveSplitNum); i1 = CadUtil.FindMaxDistantPointIndex(p0, pointList); if (i1 == -1) { return(triangles); } triangle = GetTriangleWithCenterPoint(pointList, i1); Vector3d tp0 = triangle.PointList[0].vector; Vector3d tp1 = triangle.PointList[1].vector; Vector3d tp2 = triangle.PointList[2].vector; Vector3d dir = CadMath.Normal(tp1, tp0, tp2); Vector3d currentDir = Vector3d.Zero; while (pointList.Count > 3) { if (state == 0) { i1 = CadUtil.FindMaxDistantPointIndex(p0, pointList); if (i1 == -1) { return(triangles); } } triangle = GetTriangleWithCenterPoint(pointList, i1); tp0 = triangle.PointList[0].vector; tp1 = triangle.PointList[1].vector; tp2 = triangle.PointList[2].vector; currentDir = CadMath.Normal(tp1, tp0, tp2); bool hasIn = ListContainsPointInTriangle(pointList, triangle); double scala = CadMath.InnerProduct(dir, currentDir); if (!hasIn && (scala > 0)) { triangles.Add(triangle); pointList.RemoveAt(i1); state = 0; continue; } if (state == 0) { state = 1; i1 = 0; } else if (state == 1) { i1++; if (i1 >= pointList.Count) { break; } } } if (pointList.Count == 3) { triangle = CadFigure.Create(CadFigure.Types.POLY_LINES); triangle.AddPoints(pointList, 0, 3); triangle.IsLoop = true; triangles.Add(triangle); } return(triangles); }
public Result(CadVertex wp, double dist) { WoldPoint = wp; Dist = dist; }
public override void SetPointAt(int index, CadVertex pt) { mPointList[index] = pt; }
// 回転体の作成 // 削除予定 public static CadMesh CreateRotatingBody(int circleDiv, VertexList vl, FaceType facetype = FaceType.TRIANGLE) { if (vl.Count < 2) { return(null); } CadMesh mesh = new CadMesh(vl.Count * circleDiv, vl.Count * circleDiv); // 上下端が中心軸にあるなら共有 int s = 0; int e = vl.Count; int vc = vl.Count; bool topCap = false; bool bottomCap = false; int ps = 0; if (vl[0].X == 0) { mesh.VertexStore.Add(vl[0]); s += 1; topCap = true; vc--; ps++; } if (vl[vl.Count - 1].X == 0) { mesh.VertexStore.Add(vl[vl.Count - 1]); e -= 1; bottomCap = true; vc--; ps++; } double d = Math.PI * 2.0 / circleDiv; for (int i = 0; i < circleDiv; i++) { double a = i * d; for (int vi = s; vi < e; vi++) { CadVertex v = vl[vi]; CadVertex vv = default(CadVertex); vv.X = v.X * Math.Cos(a); vv.Y = v.Y; vv.Z = v.X * Math.Sin(a); mesh.VertexStore.Add(vv); } } CadFace f; if (topCap) { for (int i = 0; i < circleDiv; i++) { f = new CadFace(0, ((i + 1) % circleDiv) * vc + ps, i * vc + ps); mesh.FaceStore.Add(f); } } if (bottomCap) { for (int i = 0; i < circleDiv; i++) { int bi = (vc - 1); f = new CadFace(1, (i * vc) + bi + ps, ((i + 1) % circleDiv) * vc + bi + ps); mesh.FaceStore.Add(f); } } // 四角形で作成 if (facetype == FaceType.QUADRANGLE) { for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } else { // 三角形で作成 for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); f = new CadFace( nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } return(mesh); }
public override void AddPointInCreating(DrawContext dc, CadVertex p) { mPointList.Add(p); }
public override void AddPoint(CadVertex p) { mPointList.Add(p); }
public override void MoveSelectedPointsFromStored(DrawContext dc, Vector3d delta) { CadVertex cp = StoreList[0]; if (cp.Selected) { mPointList[0] = cp + delta; mPointList[1] = StoreList[1] + delta; mPointList[2] = StoreList[2] + delta; mPointList[3] = StoreList[3] + delta; mPointList[4] = StoreList[4] + delta; return; } StackArray <CadVertex> vt = default; vt[0] = StoreList[1] - cp; vt[1] = StoreList[2] - cp; vt[2] = StoreList[3] - cp; vt[3] = StoreList[4] - cp; vt.Length = 4; if (vt[0].Norm() < 0.01) { return; } int ai = -1; for (int i = 0; i < 4; i++) { if (StoreList[i + 1].Selected) { ai = i; break; } } if (ai < 0) { return; } int bi = (ai + 1) % 4; int ci = (ai + 2) % 4; int di = (ai + 3) % 4; Vector3d normal = CadMath.CrossProduct(vt[ai].vector, vt[bi].vector); normal = normal.UnitVector(); vt[ai] += delta; CadVertex uva = vt[ai].UnitVector(); CadVertex uvb = vt[bi].UnitVector(); if (!uva.EqualsThreshold(uvb)) { normal = CadMath.CrossProduct(vt[ai].vector, vt[bi].vector); if (normal.IsZero()) { return; } normal = normal.UnitVector(); } CadQuaternion q = CadQuaternion.RotateQuaternion(normal, Math.PI / 2.0); CadQuaternion r = q.Conjugate(); CadQuaternion qp = CadQuaternion.FromPoint(vt[ai].vector); qp = r * qp; qp = qp * q; vt[bi] = (CadVertex)qp.ToPoint(); vt[ci] = -vt[ai]; vt[di] = -vt[bi]; CadVertex tmp; for (int i = 0; i < vt.Length; i++) { tmp = vt[i]; tmp.Selected = false; vt[i] = tmp; } tmp = vt[ai]; tmp.Selected = true; vt[ai] = tmp; mPointList[1] = vt[0] + cp; mPointList[2] = vt[1] + cp; mPointList[3] = vt[2] + cp; mPointList[4] = vt[3] + cp; }
public CadVertex CreateVertex(double x, double y, double z) { return(CadVertex.Create(x, y, z)); }
// option: // e.g. // a100q30 max area = 100, min degree = 30 // a100q max area = 100, min degree = default (20) // min degree < 34 // Other options see // https://www.cs.cmu.edu/~quake/triangle.switch.html // public void Triangulate(uint figID, string option) { CadFigure tfig = Controller.DB.GetFigure(figID); if (tfig == null || tfig.Type != Types.POLY_LINES) { return; } if (tfig.PointCount < 3) { return; } CadFigure cfig = FigUtil.Clone(tfig); Vector3d org = cfig.PointList[0].vector; Vector3d dir = Vector3d.UnitZ; Vector3d faceNormal = CadUtil.TypicalNormal(cfig.PointList); Vector3d rotateV = default; double t = 0; if (!faceNormal.EqualsThreshold(dir) && !(-faceNormal).EqualsThreshold(dir)) { rotateV = CadMath.Normal(faceNormal, dir); t = -CadMath.AngleOfVector(faceNormal, dir); CadUtil.RotateFigure(cfig, org, rotateV, t); } //Controller.CurrentLayer.AddFigure(cfig); VertexList vl = cfig.GetPoints(12); CadMesh m = IglW.Triangulate(vl, option); HeModel hem = HeModelConverter.ToHeModel(m); CadFigureMesh fig = (CadFigureMesh)Controller.DB.NewFigure(CadFigure.Types.MESH); fig.SetMesh(hem); for (int i = 0; i < fig.PointCount; i++) { CadVertex v = fig.PointList[i]; v.Z = org.Z; fig.PointList[i] = v; } if (t != 0) { CadUtil.RotateFigure(fig, org, rotateV, -t); } CadOpeList root = new CadOpeList(); CadOpe ope; ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig); ope = new CadOpeRemoveFigure(Controller.CurrentLayer, figID); Session.AddOpe(ope); Controller.CurrentLayer.RemoveFigureByID(figID); Controller.CurrentFigure = null; Session.PostRemakeObjectTree(); }
public override void DrawTemp(DrawContext dc, CadVertex tp, DrawPen pen) { }
// 回転体の作成 public static CadMesh CreateRotatingBody(int circleDiv, Vector3d org, Vector3d axis, VertexList vl, bool topCap, bool btmCap, FaceType facetype = FaceType.TRIANGLE) { if (vl.Count < 2) { return(null); } #region 面の向きが外から中心に向かってみた場合に左回りになるように回転軸の向きを調整 // vlの全体的な向きを求めるためvl[0]から一番遠い点を求める int fi = CadUtil.FindMaxDistantPointIndex(vl[0], vl); Vector3d vldir = (Vector3d)(vl[fi] - vl[0]); // vlの全体的な向きと回転軸の向きが同じ場合、回転軸の向きを反転 double dot = CadMath.InnerProduct(axis, vldir); if (dot > 0) { axis *= -1; } #endregion CadMesh mesh = new CadMesh(vl.Count * circleDiv, vl.Count * circleDiv); CrossInfo crossS = CadMath.PerpCrossLine(org, org + axis, (Vector3d)vl[0]); CrossInfo crossE = CadMath.PerpCrossLine(org, org + axis, (Vector3d)vl.End()); crossS.Distance = (crossS.CrossPoint - (Vector3d)vl[0]).Length; crossE.Distance = (crossE.CrossPoint - (Vector3d)vl.End()).Length; int s = 0; int e = vl.Count; int vc = vl.Count; int ps = 0; // VertexStoreの並びは以下の様になる。vlの個数をnとする。 // topCap中心点, btmCap中心点, 側面点0, 側面点1 ..... 側面点n-1 // 変数ps: 側面の点0の位置 // 変数s: vlから取り出す先頭位置 // 最初の点をtopCapの中心とする場合、側面点0ではなくなるので、+1する // 変数e: vlから取り出す終端 // 最後の点をbtmCapの中心とする場合、側面点n-1ではなくなるので、-1する // 変数vc: 側面1列の点の数 if (crossS.Distance < CadMath.Epsilon) { mesh.VertexStore.Add(vl[0]); s += 1; topCap = true; vc--; ps++; } else if (topCap) { mesh.VertexStore.Add((CadVertex)crossS.CrossPoint); ps++; } if (crossE.Distance < CadMath.Epsilon) { mesh.VertexStore.Add(vl.End()); e -= 1; btmCap = true; vc--; ps++; } else if (btmCap) { mesh.VertexStore.Add((CadVertex)crossE.CrossPoint); ps++; } double d = Math.PI * 2.0 / circleDiv; CadQuaternion qp; for (int i = 0; i < circleDiv; i++) { double a = i * d; CadQuaternion q = CadQuaternion.RotateQuaternion(axis, a); CadQuaternion con = q.Conjugate(); for (int vi = s; vi < e; vi++) { CadVertex p = vl[vi]; p.vector -= org; qp = CadQuaternion.FromPoint(p.vector); qp = con * qp; qp = qp * q; p.vector = qp.ToPoint(); p += org; mesh.VertexStore.Add(p); } } CadFace f; if (topCap) { for (int i = 0; i < circleDiv; i++) { f = new CadFace(0, ((i + 1) % circleDiv) * vc + ps, i * vc + ps); mesh.FaceStore.Add(f); } } if (btmCap) { for (int i = 0; i < circleDiv; i++) { int bi = (vc - 1); f = new CadFace(1, (i * vc) + bi + ps, ((i + 1) % circleDiv) * vc + bi + ps); mesh.FaceStore.Add(f); } } // 四角形で作成 if (facetype == FaceType.QUADRANGLE) { for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } else { // 三角形で作成 for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); f = new CadFace( nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } return(mesh); }
public override void AddPointInCreating(DrawContext dc, CadVertex p) { }
private void DrawSelectedLines(DrawContext dc) { int i; int num = PointList.Count; for (i = 0; i < num; i++) { CadVertex p = PointList[i]; if (!p.Selected) { continue; } dc.Drawing.DrawSelectedPoint(p.vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); if (p.IsHandle) { int idx = i + 1; if (idx >= num) { idx = 0; } CadVertex next = GetPointAt(idx); if (!next.IsHandle) { // Draw handle dc.Drawing.DrawLine(dc.GetPen(DrawTools.PEN_HANDLE_LINE), p.vector, next.vector); dc.Drawing.DrawSelectedPoint(next.vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); } idx = i - 1; if (idx >= 0) { CadVertex prev = GetPointAt(idx); if (!prev.IsHandle) { // Draw handle dc.Drawing.DrawLine(dc.GetPen(DrawTools.PEN_HANDLE_LINE), p.vector, prev.vector); dc.Drawing.DrawSelectedPoint(prev.vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); } } } else { int idx = i + 1; if (idx < PointCount) { CadVertex np = GetPointAt(idx); if (np.IsHandle) { dc.Drawing.DrawLine(dc.GetPen(DrawTools.PEN_MATCH_SEG), p.vector, np.vector); dc.Drawing.DrawSelectedPoint(np.vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); } } idx = i - 1; if (idx >= 0) { CadVertex np = GetPointAt(idx); if (np.IsHandle) { dc.Drawing.DrawLine(dc.GetPen(DrawTools.PEN_MATCH_SEG), p.vector, np.vector); dc.Drawing.DrawSelectedPoint(np.vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); } } } } }