/// <summary> /// Угол между векторами /// </summary> public static double Angle(Vector a, Vector b, double epsilon) { double q = Math.Asin(CrossProduct(a, b) / (a.Length * b.Length)); if (a.Length < epsilon || b.Length < epsilon) throw new ZeroVectorsAngleException("Trying to find angle between zero-length vectors (epsilon = " + epsilon + ")"); else return q; }
/// <summary> /// Векторное произведение /// </summary> public static double CrossProduct(Vector a, Vector b) { return a.m_x * b.m_y - a.m_y * b.m_x; }
public static Point GetCrossing(Segment s1, Segment s2) { // Algorithmic equality if (s1 == s2) throw new SelfCrossingException("Trying to find selfcrossing"); // TODO: Add rough estimation here (i.e. rectangle estimation) if (s1._Crossings.ContainsKey(s2)) return s1._Crossings[s2]; // TODO: Check integrity // Parallelism and zero-length Vector AB1 = new Vector(s1._B.X - s1._A.X, s1._B.Y - s1._A.Y); Vector AB2 = new Vector(s2._B.X - s2._A.X, s2._B.Y - s2._A.Y); double D = Vector.CrossProduct(AB2, AB1); if (Math.Abs(D) == 0) return null; if (s1._A == s2._A || s1._A == s2._B) return s1._A; if (s1._B == s2._A || s1._B == s2._B) return s1._B; // Calculating crossing between lines double m = Vector.CrossProduct((Vector)s1._A, AB1); double n = Vector.CrossProduct((Vector)s2._A, AB2); double x = (m * AB2.X - n * AB1.X) / D; double y = (m * AB2.Y - n * AB1.Y) / D; // Checking if an endpoint of one segment is contained by other if (s1._A.X == x && s1._A.Y == y) return s1._A; if (s1._B.X == x && s1._B.Y == y) return s1._B; if (s2._A.X == x && s2._A.Y == y) return s2._A; if (s2._B.X == x && s2._B.Y == y) return s2._B; // Checking if the crossing point is in both segments Vector AC1 = new Vector(x - s1._A.X, y - s1._A.Y); Vector BC1 = new Vector(x - s1._B.X, y - s1._B.Y); if ((AB1 * AC1) * (-AB1 * BC1) < 0) return null; Vector AC2 = new Vector(x - s2._A.X, y - s2._A.Y); Vector BC2 = new Vector(x - s2._B.X, y - s2._B.Y); if ((AB2 * AC2) * (-AB2 * BC2) < 0) return null; // Adding the point to crossing dictionaries Point crs = new Point(x, y); s1._Crossings.Add(s2, crs); s2._Crossings.Add(s1, crs); return crs; }
public static Point Move(Point p, Vector v) { return new Point(p._X + v.X, p._Y + v.Y); }
public double GetArea() { double res = 0; for (int i = 1; i < mVertex.Length - 1; i++) { Vector a = new Vector(mVertex[i].X - mVertex[0].X, mVertex[i].Y - mVertex[0].Y); Vector b = new Vector(mVertex[i + 1].X - mVertex[0].X, mVertex[i + 1].Y - mVertex[0].Y); res += Vector.CrossProduct(a, b); } res /= 2; return res; }
public bool Contains(Point p) { Vector a0 = new Vector( mVertex[0].X - mVertex[mVertex.Length - 1].X, mVertex[0].Y - mVertex[mVertex.Length - 1].Y); Vector b0 = new Vector( p.X - mVertex[mVertex.Length - 1].X, p.Y - mVertex[mVertex.Length - 1].Y); if (Vector.CrossProduct(a0, b0) <= 0) return false; for (int i = 1; i < mVertex.Length; i++) { Vector a = new Vector( mVertex[i].X - mVertex[i - 1].X, mVertex[i].Y - mVertex[i - 1].Y); Vector b = new Vector( p.X - mVertex[i - 1].X, p.Y - mVertex[i - 1].Y); if (Vector.CrossProduct(a, b) <= 0) return false; } return true; }
public override bool ReportMousePosition(int x, int y, int width, int height) { if (width == 0 || height == 0) return false; CrotateStageOperationParameters pm = ((CrotateStageOperationParameters)Parameters); bool res = false; if (mDragState == DragState.Center) { int new_scr_x = mCenterDotStartX - mDragStartX + x; int new_scr_y = mCenterDotStartY - mDragStartY + y; pm.Center = new Point((double)new_scr_x / width, (double)new_scr_y / height); res = true; } else if (mDragState == DragState.Round) { Point scr_C = new Point(width * pm.Center.X, height * pm.Center.Y); Point cur = new Point(x, y); Vector cur_dir = new Vector(scr_C, cur); pm.Angle = 180.0 / Math.PI * Math.Atan2(cur_dir.Y, cur_dir.X); res = true; } else if (mDragState == DragState.Corner) { Point scr_C = new Point(width * pm.Center.X, height * pm.Center.Y); Point scr_cur = new Point(x, y); Point scr_rnd = new Point( (scr_C.X + (rt_corner_rot.X + rb_corner_rot.X) / 2), (scr_C.Y + (rt_corner_rot.Y + rb_corner_rot.Y) / 2)); Point scr_start = new Point(mDragStartX, mDragStartY); // Rotated orts Vector v_w = new Vector(scr_C, scr_rnd); v_w /= v_w.Length; Vector v_h = new Vector(v_w.Y, -v_w.X); // Current diameter Vector D = new Vector(scr_C, scr_cur); double Dw = D * v_w; double Dh = D * v_h; // Starting diameter Vector D0 = new Vector(scr_C, scr_start); double D0w = D0 * v_w; double D0h = D0 * v_h; switch (pm.Mode) { case CatEye.Core.CrotateStageOperation.Mode.Disproportional: pm.CropWidth = mCropWidthStart * Dw / D0w; pm.CropHeight = mCropHeightStart * Dh / D0h; break; case CatEye.Core.CrotateStageOperation.Mode.ProportionalWidthFixed: pm.CropWidth = mCropWidthStart * Dw / D0w; break; case CatEye.Core.CrotateStageOperation.Mode.ProportionalHeightFixed: pm.CropHeight = mCropHeightStart * Dh / D0h; break; } res = true; } return res; }