// 法線の代表値を求める //public static CadVertex RepresentativeNormal(VertexList points) //{ // if (points.Count < 3) // { // return CadVertex.Zero; // } // int idx = FindMaxDistantPointIndex(points[0], points); // int idxA = idx - 1; // int idxB = idx + 1; // if (idxA < 0) // { // idxA = points.Count - 1; // } // if (idxB >= points.Count) // { // idxB = idxB - points.Count; // } // CadVertex normal = CadMath.Normal(points[idx], points[idxA], points[idxB]); // return normal; //} public static Vector3d TypicalNormal(VertexList points) { if (points.Count < 3) { return(Vector3d.Zero); } int idx = FindMaxDistantPointIndex(points[0], points); int idxA = idx - 1; int idxB = idx + 1; if (idxA < 0) { idxA = points.Count - 1; } if (idxB >= points.Count) { idxB = idxB - points.Count; } Vector3d normal = CadMath.Normal(points[idx].vector, points[idxA].vector, points[idxB].vector); return(normal); }
private void drawCircle(DrawContext dc, DrawPen pen) { if (PointList.Count == 0) { return; } if (PointList.Count == 1) { dc.Drawing.DrawCross(pen, PointList[0].vector, 2); if (PointList[0].Selected) { dc.Drawing.DrawSelectedPoint(PointList[0].vector, dc.GetPen(DrawTools.PEN_SELECT_POINT)); } return; } Vector3d normal = CadMath.Normal(PointList[0].vector, PointList[2].vector, PointList[1].vector); CircleExpander.Draw(PointList[0], PointList[1], PointList[2], 32, dc, pen); double size = dc.DevSizeToWoldSize(4); dc.Drawing.DrawCross(pen, PointList[0].vector, size); }
public void RotateEyePoint(Vector2 prev, Vector2 current) { Vector2 d = current - prev; double ry = (d.X / 10.0) * (Math.PI / 20); double rx = (d.Y / 10.0) * (Math.PI / 20); CadQuaternion q; CadQuaternion r; CadQuaternion qp; q = CadQuaternion.RotateQuaternion(Vector3d.UnitY, ry); r = q.Conjugate(); qp = CadQuaternion.FromVector(mEye); qp = r * qp; qp = qp * q; mEye = qp.ToVector3d(); qp = CadQuaternion.FromVector(mUpVector); qp = r * qp; qp = qp * q; mUpVector = qp.ToVector3d(); Vector3d ev = mLookAt - mEye; Vector3d a = new Vector3d(ev); Vector3d b = new Vector3d(mUpVector); Vector3d axis = CadMath.Normal(a, b); if (!axis.IsZero()) { q = CadQuaternion.RotateQuaternion(axis, rx); r = q.Conjugate(); qp = CadQuaternion.FromVector(mEye); qp = r * qp; qp = qp * q; mEye = qp.ToVector3d(); qp = CadQuaternion.FromVector(mUpVector); qp = r * qp; qp = qp * q; mUpVector = qp.ToVector3d(); } CalcViewMatrix(); CalcViewDir(); CalcProjectionZW(); }
public void PanCamera(DrawContext dc, Vector2 prev, Vector2 current) { Vector2 d = current - prev; double rx = d.X * (Math.PI / 1000); double ry = d.Y * (Math.PI / 1000); CadQuaternion q; CadQuaternion r; CadQuaternion qp; Vector3d lookv = dc.LookAt - dc.Eye; Vector3d upv = dc.UpVector; q = CadQuaternion.RotateQuaternion(upv, rx); r = q.Conjugate(); qp = CadQuaternion.FromVector(lookv); qp = r * qp; qp = qp * q; lookv = qp.ToVector3d(); Vector3d ev = dc.LookAt - dc.Eye; Vector3d a = new Vector3d(ev); Vector3d b = new Vector3d(upv); Vector3d axis = CadMath.Normal(a, b); if (!axis.IsZero()) { q = CadQuaternion.RotateQuaternion(axis, ry); r = q.Conjugate(); qp = CadQuaternion.FromVector(lookv); qp = r * qp; qp = qp * q; lookv = qp.ToVector3d(); qp = CadQuaternion.FromVector(upv); qp = r * qp; qp = qp * q; upv = qp.ToVector3d(); } dc.SetCamera(dc.Eye, lookv + dc.Eye, upv); }
public static void ForEachSegs( CadVertex cp, CadVertex pa, CadVertex pb, int splitCnt, Action <CadVertex, CadVertex> action) { CadVertex va = pa - cp; CadVertex vb = pb - cp; if (va.Norm() < 0.01) { return; } double dt = (2.0 * Math.PI) / (double)splitCnt; int div = splitCnt; Vector3d normal = CadMath.Normal(va.vector, vb.vector); CadQuaternion q = CadQuaternion.RotateQuaternion(normal, dt); CadQuaternion r = q.Conjugate(); CadVertex p = va; CadVertex tp1 = pa; CadVertex tp2 = pa; int i = 0; for (; i < div - 1; i++) { CadQuaternion qp = CadQuaternion.FromPoint(p.vector); qp = r * qp; qp = qp * q; p.vector = qp.ToPoint(); tp2 = p + cp; action(tp1, tp2); tp1 = tp2; } action(tp1, pa); }
public static void Draw( CadVertex cp, CadVertex pa, CadVertex pb, int splitCnt, DrawContext dc, DrawPen pen) { CadVertex va = pa - cp; CadVertex vb = pb - cp; if (va.Norm() < 0.01) { return; } double dt = (2.0 * Math.PI) / (double)splitCnt; int div = splitCnt; Vector3d normal = CadMath.Normal(va.vector, vb.vector); CadQuaternion q = CadQuaternion.RotateQuaternion(normal, dt); CadQuaternion r = q.Conjugate(); CadVertex p = va; CadVertex tp1 = pa; CadVertex tp2 = pa; int i = 0; for (; i < div - 1; i++) { CadQuaternion qp = CadQuaternion.FromPoint(p.vector); qp = r * qp; qp = qp * q; p.vector = qp.ToPoint(); tp2 = p + cp; dc.Drawing.DrawLine(pen, tp1.vector, tp2.vector); tp1 = tp2; } dc.Drawing.DrawLine(pen, tp1.vector, pa.vector); }
public override void MoveSelectedPointsFromStored(DrawContext dc, Vector3d delta) { //base.MoveSelectedPoints(dc, delta); if (Locked) { return; } Vector3d d; if (!IsSelectedAll() && mPointList.Count > 2 && RestrictionByNormal) { Vector3d vdir = dc.ViewDir; Vector3d a = delta; Vector3d b = delta + vdir; d = CadMath.CrossPlane(a, b, StoreList[0].vector, Normal); if (!d.IsValid()) { Vector3d nvNormal = CadMath.Normal(Normal, vdir); double ip = CadMath.InnerProduct(nvNormal, delta); d = nvNormal * ip; } } else { d = delta; } FigUtil.MoveSelectedPointsFromStored(this, dc, d); mChildList.ForEach(c => { c.MoveSelectedPointsFromStored(dc, delta); }); }
public static void DrawArrow( Action <DrawPen, Vector3d, Vector3d> DrawLine, DrawPen pen, Vector3d pt0, Vector3d pt1, ArrowTypes type, ArrowPos pos, double len, double width) { DrawLine(pen, pt0, pt1); Vector3d d = pt1 - pt0; double dl = d.Length; if (dl < 0.00001) { return; } Vector3d tmp = new Vector3d(dl, 0, 0); double angle = Vector3d.CalculateAngle(tmp, d); Vector3d normal = CadMath.CrossProduct(tmp, d); // 回転軸 if (normal.Length < 0.0001) { normal = new Vector3d(0, 0, 1); } else { normal = normal.UnitVector(); normal = CadMath.Normal(tmp, d); } CadQuaternion q = CadQuaternion.RotateQuaternion(normal, -angle); CadQuaternion r = q.Conjugate(); ArrowHead a; if (pos == ArrowPos.END || pos == ArrowPos.START_END) { a = ArrowHead.Create(type, ArrowPos.END, len, width); a.Rotate(q, r); a += pt1; DrawLine(pen, a.p0.vector, a.p1.vector); DrawLine(pen, a.p0.vector, a.p2.vector); DrawLine(pen, a.p0.vector, a.p3.vector); DrawLine(pen, a.p0.vector, a.p4.vector); } if (pos == ArrowPos.START || pos == ArrowPos.START_END) { a = ArrowHead.Create(type, ArrowPos.START, len, width); a.Rotate(q, r); a += pt0; DrawLine(pen, a.p0.vector, a.p1.vector); DrawLine(pen, a.p0.vector, a.p2.vector); DrawLine(pen, a.p0.vector, a.p3.vector); DrawLine(pen, a.p0.vector, a.p4.vector); } }
private void DrawDim(DrawContext dc, DrawPen linePen, DrawBrush textBrush) { dc.Drawing.DrawLine(linePen, PointList[0].vector, PointList[3].vector); dc.Drawing.DrawLine(linePen, PointList[1].vector, PointList[2].vector); Vector3d cp = CadMath.CenterPoint(PointList[3].vector, PointList[2].vector); double arrowW = ARROW_W; double arrowL = ARROW_LEN; double ww = (PointList[1] - PointList[0]).Norm() / 4.0; if (ww > arrowL) { dc.Drawing.DrawArrow(linePen, cp, PointList[3].vector, ArrowTypes.CROSS, ArrowPos.END, arrowL, arrowW); dc.Drawing.DrawArrow(linePen, cp, PointList[2].vector, ArrowTypes.CROSS, ArrowPos.END, arrowL, arrowW); } else { Vector3d v0 = cp - PointList[3].vector; Vector3d v1 = cp - PointList[2].vector; v0 = -(v0.Normalized() * (arrowL * 1.5)) / dc.WorldScale + PointList[3].vector; v1 = -(v1.Normalized() * (arrowL * 1.5)) / dc.WorldScale + PointList[2].vector; dc.Drawing.DrawArrow(linePen, v0, PointList[3].vector, ArrowTypes.CROSS, ArrowPos.END, arrowL, arrowW); dc.Drawing.DrawArrow(linePen, v1, PointList[2].vector, ArrowTypes.CROSS, ArrowPos.END, arrowL, arrowW); dc.Drawing.DrawLine(linePen, PointList[2].vector, PointList[3].vector); } CadVertex lineV = PointList[2] - PointList[3]; double len = lineV.Norm(); string lenStr = CadUtil.ValToString(len); CadVertex p = PointList[3] + (lineV / 2); p += (PointList[3] - PointList[0]).UnitVector() * (arrowW); CadVertex up = PointList[3] - PointList[0]; // 裏返しになる場合は、反転する // If it turns over, reverse it Vector3d normal = CadMath.Normal(lineV.vector, up.vector); double scala = CadMath.InnerProduct(normal, dc.ViewDir); if (scala > 0) { lineV = -lineV; } // --- lineV ---> // 3<------------ p ----------->2 // ^ | | // | | | // up 0 1 // dc.Drawing.DrawText(FontID, textBrush, p.vector, lineV.vector, up.vector, new DrawTextOption(DrawTextOption.H_CENTER), lenStr); }
public override void MoveSelectedPointsFromStored(DrawContext dc, Vector3d delta) { if (PointList[0].Selected && PointList[1].Selected && PointList[2].Selected && PointList[3].Selected) { PointList[0] = StoreList[0] + delta; PointList[1] = StoreList[1] + delta; PointList[2] = StoreList[2] + delta; PointList[3] = StoreList[3] + delta; return; } if (PointList[2].Selected || PointList[3].Selected) { Vector3d v0 = StoreList[3].vector - StoreList[0].vector; if (v0.IsZero()) { // 移動方向が不定の場合 MoveSelectedPointWithHeight(dc, delta); return; } Vector3d v0u = v0.UnitVector(); double d = CadMath.InnerProduct(v0u, delta); Vector3d vd = v0u * d; CadVertex nv3 = StoreList[3] + vd; CadVertex nv2 = StoreList[2] + vd; if (nv3.EqualsThreshold(StoreList[0], 0.001) || nv2.EqualsThreshold(StoreList[1], 0.001)) { return; } PointList[3] = nv3; PointList[2] = nv2; return; } if (PointList[0].Selected || PointList[1].Selected) { Vector3d v0 = StoreList[0].vector; Vector3d v1 = StoreList[1].vector; Vector3d v2 = StoreList[2].vector; Vector3d v3 = StoreList[3].vector; Vector3d lv = v3 - v0; double h = lv.Norm(); Vector3d planeNormal = CadMath.Normal(v0, v1, v2); Vector3d cp0 = v0; Vector3d cp1 = v1; if (PointList[0].Selected) { cp0 = CadMath.CrossPlane(v0 + delta, v0, planeNormal); } if (PointList[1].Selected) { cp1 = CadMath.CrossPlane(v1 + delta, v1, planeNormal); } if (cp0.EqualsThreshold(cp1, 0.001)) { return; } if (PointList[0].Selected) { PointList[0] = PointList[0].SetVector(cp0); } if (PointList[1].Selected) { PointList[1] = PointList[1].SetVector(cp1); } Vector3d normal = CadMath.Normal(cp0, cp0 + planeNormal, cp1); Vector3d d = normal * h; PointList[3] = PointList[3].SetVector(PointList[0] + d); PointList[2] = PointList[2].SetVector(PointList[1] + d); } }
private void DrawCompassOrtho() { PushMatrixes(); double size = 40; double vw = DC.ViewWidth; double vh = DC.ViewHeight; double cx = size / 2 + 24; double cy = size / 2 + 40; double left = -cx; double right = vw - cx; double top = cy; double bottom = -(vh - cy); double arrowLen = 10; double arrowW2 = 5; Matrix4d prjm = Matrix4d.CreateOrthographicOffCenter(left, right, bottom, top, 100, 10000); GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref prjm); GL.MatrixMode(MatrixMode.Modelview); Vector3d lookAt = Vector3d.Zero; Vector3d eye = -DC.ViewDir * 300; Matrix4d mdlm = Matrix4d.LookAt(eye, lookAt, DC.UpVector); GL.LoadMatrix(ref mdlm); Vector3d p0; Vector3d p1; GL.LineWidth(2); p0 = Vector3d.UnitX * -size; p1 = Vector3d.UnitX * size; DrawArrow(DC.GetPen(DrawTools.PEN_AXIS_X), p0, p1, ArrowTypes.CROSS, ArrowPos.END, arrowLen, arrowW2); p0 = Vector3d.UnitY * -size; p1 = Vector3d.UnitY * size; DrawArrow(DC.GetPen(DrawTools.PEN_AXIS_Y), p0, p1, ArrowTypes.CROSS, ArrowPos.END, arrowLen, arrowW2); p0 = Vector3d.UnitZ * -size; p1 = Vector3d.UnitZ * size; DrawArrow(DC.GetPen(DrawTools.PEN_AXIS_Z), p0, p1, ArrowTypes.CROSS, ArrowPos.END, arrowLen, arrowW2); GL.LineWidth(1); FontTex tex; Vector3d xv = CadMath.Normal(DC.ViewDir, DC.UpVector); Vector3d yv = CadMath.Normal(DC.ViewDir, DC.UpVector); double fs = 0.6; tex = mFontFaceW.CreateTexture("X"); p1 = Vector3d.UnitX * size; GL.Color4(DC.GetBrush(DrawTools.BRUSH_COMPASS_LABEL_X).Color4()); mFontRenderer.Render(tex, p1, xv * tex.ImgW * fs, DC.UpVector * tex.ImgH * fs); tex = mFontFaceW.CreateTexture("Y"); p1 = Vector3d.UnitY * size; GL.Color4(DC.GetBrush(DrawTools.BRUSH_COMPASS_LABEL_Y).Color4()); mFontRenderer.Render(tex, p1, xv * tex.ImgW * fs, DC.UpVector * tex.ImgH * fs); tex = mFontFaceW.CreateTexture("Z"); p1 = Vector3d.UnitZ * size; GL.Color4(DC.GetBrush(DrawTools.BRUSH_COMPASS_LABEL_Z).Color4()); mFontRenderer.Render(tex, p1, xv * tex.ImgW * fs, DC.UpVector * tex.ImgH * fs); PopMatrixes(); }
// 図形は凸である public static bool IsConvex(VertexList points) { int cnt = points.Count; if (cnt < 3) { return(false); } int i = 0; Vector3d n = default; Vector3d cn = default; double scala = 0; for (; i < cnt - 2;) { n = CadMath.Normal(points[i].vector, points[i + 1].vector, points[i + 2].vector); i++; if (!n.IsZero()) { break; } } if (n.IsZero()) { return(false); } for (; i < cnt - 2;) { cn = CadMath.Normal(points[i].vector, points[i + 1].vector, points[i + 2].vector); i++; scala = CadMath.InnerProduct(cn, n); if (Math.Abs(scala) < CadMath.Epsilon) { continue; } if (scala < CadMath.RP1Min) { return(false); } } cn = CadMath.Normal(points[i].vector, points[i + 1].vector, points[0].vector); scala = CadMath.InnerProduct(cn, n); if (Math.Abs(scala) < 0.000001) { return(true); } if (scala < 0.999999) { return(false); } return(true); }
private void CheckCircle(DrawContext dc, CadLayer layer, CadFigure fig) { if (fig.PointCount < 3) { return; } VertexList vl = fig.PointList; if (fig.StoreList != null) { vl = fig.StoreList; } Vector3d c = vl[0].vector; Vector3d a = vl[1].vector; Vector3d b = vl[2].vector; Vector3d normal = CadMath.Normal(a - c, b - c); Vector3d tw = Target.Pos; tw.Z = 0; tw = dc.DevPointToWorldPoint(tw); Vector3d crossP = CadMath.CrossPlane(tw, tw + dc.ViewDir, c, normal); if (crossP.IsInvalid()) { // 真横から見ている場合 // viewed edge-on //DOut.tpl("crossP is invalid"); return; } double r = (a - c).Norm(); double tr = (crossP - c).Norm(); Vector3d cirP = c + (crossP - c) * (r / tr); Vector3d dcirP = dc.WorldPointToDevPoint(cirP); Vector3d dcrossP = dc.WorldPointToDevPoint(crossP); dcirP.Z = 0; dcrossP.Z = 0; double dist = (dcirP - Target.Pos).Norm(); if (dist > Range) { //DOut.tpl($"dist:{dist} Range:{Range}"); return; } if (dist < MinDist) { FigureSegment fseg = new FigureSegment(fig, 0, 0, 0); MarkSeg.Layer = layer; MarkSeg.FigSeg = fseg; MarkSeg.CrossPoint = cirP; MarkSeg.CrossPointScrn = dc.WorldPointToDevPoint(cirP); MarkSeg.Distance = dist; MinDist = dist; } }
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); }