// 点pから直線abに向かう垂線との交点を求める public static CrossInfo PerpCrossLine(Vector3d a, Vector3d b, Vector3d p) { CrossInfo ret = default; if (a.Equals(b)) { return(ret); } Vector3d ab = b - a; Vector3d ap = p - a; // A-B 単位ベクトル Vector3d unit_ab = ab.UnitVector(); // Aから交点までの距離 double dist_ax = InnerProduct(unit_ab, ap); ret.CrossPoint.X = a.X + (unit_ab.X * dist_ax); ret.CrossPoint.Y = a.Y + (unit_ab.Y * dist_ax); ret.CrossPoint.Z = a.Z + (unit_ab.Z * dist_ax); ret.IsCross = true; return(ret); }
private void CheckFigPoint(DrawContext dc, Vector3d pt, CadLayer layer, CadFigure fig, int ptIdx) { Vector3d ppt = dc.WorldPointToDevPoint(pt); double dx = Math.Abs(ppt.X - Target.Pos.X); double dy = Math.Abs(ppt.Y - Target.Pos.Y); CrossInfo cix = CadMath.PerpCrossLine(Target.Pos, Target.Pos + Target.DirX, ppt); CrossInfo ciy = CadMath.PerpCrossLine(Target.Pos, Target.Pos + Target.DirY, ppt); double nx = (ppt - ciy.CrossPoint).Norm(); // Cursor Y軸からの距離 double ny = (ppt - cix.CrossPoint).Norm(); // Cursor X軸からの距離 if (nx <= Range) { if (nx < XMatch.DistanceX || (nx == XMatch.DistanceX && ny < XMatch.DistanceY)) { XMatch = GetMarkPoint(pt, ppt, nx, ny, layer, fig, ptIdx); } } if (ny <= Range) { if (ny < YMatch.DistanceY || (ny == YMatch.DistanceY && nx < YMatch.DistanceX)) { YMatch = GetMarkPoint(pt, ppt, nx, ny, layer, fig, ptIdx); } } if (dx <= Range && dy <= Range) { double minDist = (XYMatch.DistanceX * XYMatch.DistanceX) + (XYMatch.DistanceY * XYMatch.DistanceY); double curDist = (dx * dx) + (dy * dy); if (curDist <= minDist) { MarkPoint t = GetMarkPoint(pt, ppt, dx, dy, layer, fig, ptIdx); //t.dump(); XYMatch = t; if (!XYMatchSet.Contains(t)) { XYMatchList.Add(XYMatch); XYMatchSet.Add(XYMatch); //DOut.pl($"PointSearcher XYMatchList cnt:{XYMatchList.Count}"); } } } }
// // 点pを通り、a - b に平行で、a-bに垂直な線分を求める // // +----------p------------+ // | | // | | // a b // public static CadSegment PerpSeg(CadVertex a, CadVertex b, CadVertex p) { CadSegment seg = default(CadSegment); seg.P0 = a; seg.P1 = b; CrossInfo ci = CadMath.PerpCrossLine(a.vector, b.vector, p.vector); if (ci.IsCross) { CadVertex nv = p - ci.CrossPoint; seg.P0 += nv; seg.P1 += nv; } return(seg); }
public static EditResult CutSegment(CadObjectDB db, MarkSegment seg, Vector3d p) { EditResult result = new EditResult(); if (seg.Figure.Type != CadFigure.Types.POLY_LINES) { return(result); } CrossInfo ci = CadMath.PerpendicularCrossSeg(seg.pA.vector, seg.pB.vector, p); if (!ci.IsCross) { return(result); } CadFigure org = db.GetFigure(seg.FigureID); int a = Math.Min(seg.PtIndexA, seg.PtIndexB); int b = Math.Max(seg.PtIndexA, seg.PtIndexB); CadFigure fa = db.NewFigure(CadFigure.Types.POLY_LINES); CadFigure fb = db.NewFigure(CadFigure.Types.POLY_LINES); fa.AddPoints(org.PointList, 0, a + 1); fa.AddPoint(new CadVertex(ci.CrossPoint)); fb.AddPoint(new CadVertex(ci.CrossPoint)); fb.AddPoints(org.PointList, b); if (org.IsLoop) { fb.AddPoint(fa.GetPointAt(0)); } result.AddList.Add(new EditResult.Item(seg.LayerID, fa)); result.AddList.Add(new EditResult.Item(seg.LayerID, fb)); result.RemoveList.Add(new EditResult.Item(org.LayerID, org)); return(result); }
// 点pから直線abに向かう垂線との交点を求める2D public static CrossInfo PerpendicularCrossLine2D(Vector3d a, Vector3d b, Vector3d p) { CrossInfo ret = default; double t1; Vector3d ab = b - a; Vector3d ap = p - a; t1 = InnrProduct2D(ab, ap); double norm = ab.Norm2D(); double norm2 = norm * norm; ret.IsCross = true; ret.CrossPoint.X = ab.X * t1 / norm2 + a.X; ret.CrossPoint.Y = ab.Y * t1 / norm2 + a.Y; return(ret); }
// 点pから線分abに向かう垂線との交点を求める2D public static CrossInfo PerpendicularCrossSeg2D(Vector3d a, Vector3d b, Vector3d p) { CrossInfo ret = default; double t1; Vector3d ab = b - a; Vector3d ap = p - a; t1 = InnrProduct2D(ab, ap); if (t1 < 0) { return(ret); } double t2; Vector3d ba = a - b; Vector3d bp = p - b; t2 = InnrProduct2D(ba, bp); if (t2 < 0) { return(ret); } double abl = ab.Norm2D(); double abl2 = abl * abl; ret.IsCross = true; ret.CrossPoint.X = ab.X * t1 / abl2 + a.X; ret.CrossPoint.Y = ab.Y * t1 / abl2 + a.Y; return(ret); }
// 点pから線分abに向かう垂線との交点を求める public static CrossInfo PerpendicularCrossSeg(Vector3d a, Vector3d b, Vector3d p) { CrossInfo ret = default; Vector3d ab = b - a; Vector3d ap = p - a; Vector3d ba = a - b; Vector3d bp = p - b; // A-B 単位ベクトル Vector3d unit_ab = ab.UnitVector(); // B-A 単位ベクトル (A-B単位ベクトルを反転) B側の中外判定に使用 Vector3d unit_ba = unit_ab * -1.0; // Aから交点までの距離 // A->交点->B or A->B->交点なら + // 交点<-A->B なら - double dist_ax = InnerProduct(unit_ab, ap); // Bから交点までの距離 B側の中外判定に使用 double dist_bx = InnerProduct(unit_ba, bp); //Console.WriteLine("getNormCross dist_ax={0} dist_bx={1}" , dist_ax.ToString(), dist_bx.ToString()); if (dist_ax > 0 && dist_bx > 0) { ret.IsCross = true; } ret.CrossPoint.X = a.X + (unit_ab.X * dist_ax); ret.CrossPoint.Y = a.Y + (unit_ab.Y * dist_ax); ret.CrossPoint.Z = a.Z + (unit_ab.Z * dist_ax); return(ret); }