public void RotateWithAxis(CadFigure fig, Vector3d org, Vector3d axisDir, double angle) { fig.ForEachFig(f => { CadUtil.RotateFigure(f, org, axisDir, angle); }); }
public static void PasteFiguresAsBin(PlotterController controller) { if (!Clipboard.ContainsData(CadClipBoard.TypeNameBin)) { return; } byte[] bin = (byte[])Clipboard.GetData(CadClipBoard.TypeNameBin); List <CadFigure> figList = BinToFigList(bin); // Pase figures in fig list Vector3d pp = controller.LastDownPoint; MinMax3D mm3d = CadUtil.GetFigureMinMaxIncludeChild(figList); Vector3d d = pp - mm3d.GetMinAsVector(); CadOpeList opeRoot = new CadOpeList(); foreach (CadFigure fig in figList) { PasteFigure(controller, fig, d); controller.CurrentLayer.AddFigure(fig); // 子ObjectはLayerに追加しない CadOpe ope = new CadOpeAddFigure(controller.CurrentLayer.ID, fig.ID); opeRoot.OpeList.Add(ope); } controller.HistoryMan.foward(opeRoot); }
private void FaceToDirection(CadFigure fig, Vector3d org, Vector3d dir) { if (fig.Type != CadFigure.Types.POLY_LINES) { return; } Vector3d faceNormal = CadUtil.TypicalNormal(fig.PointList); if (faceNormal.EqualsThreshold(dir) || (-faceNormal).EqualsThreshold(dir)) { // Face is already target direction return; } // | 回転軸 rv // | // | // | --------->向けたい方向 dir // / // / // 面の法線 faceNormal Vector3d rv = CadMath.Normal(faceNormal, dir); double t = CadMath.AngleOfVector(faceNormal, dir); CadUtil.RotateFigure(fig, org, rv, t); }
public void RotateWithAxis(List <CadFigure> rootFigList, Vector3d org, Vector3d axisDir, double angle) { foreach (CadFigure fig in rootFigList) { fig.ForEachFig(f => { CadUtil.RotateFigure(fig, org, axisDir, angle); }); } }
public void PrintVector(Vector3d v) { var sb = new StringBuilder(); sb.Append(CadUtil.ValToString(v.X)); sb.Append(", "); sb.Append(CadUtil.ValToString(v.Y)); sb.Append(", "); sb.Append(CadUtil.ValToString(v.Z)); ItConsole.println(sb.ToString()); }
public static void AddCircleCommand() { var dwg = CadApp.DocumentManager.MdiActiveDocument; var ed = dwg.Editor; try { CadUtil.AddCircle(dwg); } catch (System.Exception ex) { ed.WriteMessage($"\nError:\n{ex.Message}\n"); } }
public void Scale(uint id, Vector3d org, double scale) { CadFigure fig = Controller.DB.GetFigure(id); if (fig == null) { return; } fig.Select(); Controller.StartEdit(); fig.ForEachFig((f) => { CadUtil.ScaleFigure(f, org, scale); }); Controller.EndEdit(); Session.PostRedraw(); }
public bool ToBezier(MarkSegment seg) { if (seg.FigureID == 0) { return(false); } CadFigure fig = mDB.GetFigure(seg.FigureID); int num = CadUtil.InsertBezierHandle(fig, seg.PtIndexA, seg.PtIndexB); bool ret = num > 0; if (ret) { CadOpe ope = new CadOpeInsertPoints( fig.LayerID, fig.ID, seg.PtIndexA + 1, num); HistoryMan.foward(ope); } return(ret); }
public static CadMesh CreateExtruded(VertexList src, Vector3d dv, int div = 0) { if (src.Count < 3) { return(null); } div += 1; VertexList vl; Vector3d n = CadUtil.TypicalNormal(src); if (CadMath.InnerProduct(n, dv) <= 0) { vl = new VertexList(src); vl.Reverse(); } else { vl = src; } int vlCnt = vl.Count; CadMesh mesh = new CadMesh(vl.Count * 2, vl.Count); CadFace f; Vector3d dt = dv / div; Vector3d sv = Vector3d.Zero; // 頂点リスト作成 for (int i = 0; i < div + 1; i++) { for (int j = 0; j < vlCnt; j++) { mesh.VertexStore.Add(vl[j] + sv); } sv += dt; } // 表面 f = new CadFace(); for (int i = 0; i < vlCnt; i++) { f.VList.Add(i); } mesh.FaceStore.Add(f); // 裏面 f = new CadFace(); int si = (div + 1) * vlCnt - 1; int ei = si - (vlCnt - 1); for (int i = si; i >= ei; i--) { f.VList.Add(i); } mesh.FaceStore.Add(f); // 側面 for (int k = 0; k < div; k++) { int ti = vlCnt * k; for (int i = 0; i < vlCnt; i++) { int j = (i + 1) % vlCnt; f = new CadFace(); f.VList.Add(i + ti); f.VList.Add(i + ti + vlCnt); f.VList.Add(j + ti + vlCnt); f.VList.Add(j + ti); mesh.FaceStore.Add(f); } } MeshUtil.SplitAllFace(mesh); return(mesh); }
// 回転体の作成 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 void CreateBitmap(int w, int h, uint argb, int lineW, string fname) { DrawContext dc = Controller.DC; CadObjectDB db = Controller.DB; List <uint> idlist = Controller.DB.GetSelectedFigIDList(); var figList = new List <CadFigure>(); idlist.ForEach(id => { figList.Add(db.GetFigure(id)); }); CadRect r = CadUtil.GetContainsRectScrn(dc, figList); CadRect wr = default(CadRect); wr.p0 = dc.DevPointToWorldPoint(r.p0); wr.p1 = dc.DevPointToWorldPoint(r.p1); DrawContextGDIBmp tdc = new DrawContextGDIBmp(); tdc.WorldScale = dc.WorldScale; tdc.SetCamera(dc.Eye, dc.LookAt, dc.UpVector); tdc.CalcProjectionMatrix(); tdc.SetViewSize(w, h); tdc.SetViewOrg(new Vector3d(w / 2, h / 2, 0)); tdc.SetupTools(DrawTools.DrawMode.DARK); Pen pen = new Pen(Color.FromArgb((int)argb), lineW); DrawPen drawPen = new DrawPen(pen); double sw = r.p1.X - r.p0.X; double sh = r.p1.Y - r.p0.Y; double a = Math.Min(w, h) / (Math.Max(sw, sh) + lineW); tdc.DeviceScaleX *= a; tdc.DeviceScaleY *= a; CadRect tr = CadUtil.GetContainsRectScrn(tdc, figList); Vector3d trcp = (Vector3d)((tr.p1 - tr.p0) / 2 + tr.p0); Vector3d d = trcp - tdc.ViewOrg; tdc.SetViewOrg(tdc.ViewOrg - d); DrawParams dp = default; dp.LinePen = drawPen; dp.EdgePen = drawPen; Env.RunOnMainThread((Action)(() => { tdc.Drawing.Clear(dc.GetBrush(DrawTools.BRUSH_TRANSPARENT)); tdc.GdiGraphics.SmoothingMode = SmoothingMode.AntiAlias; foreach (CadFigure fig in figList) { fig.Draw(tdc, dp); } if (fname.Length > 0) { tdc.Image.Save(fname); } else { BitmapUtil.BitmapToClipboardAsPNG(tdc.Image); } tdc.Dispose(); drawPen.Dispose(); })); }
// 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(); }