/// <summary> /// constructs an affine manifold from a set of points /// </summary> /// <param name="pts"> /// points on the manifold; /// 1st index: point index. /// 2nd index: spatial dimension. /// </param> static public AffineManifold FromPoints(params double[][] pts) { int D = pts.Length; for (int i = 0; i < D; i++) if (pts[i].Length != D) throw new ArgumentException(); var ret = new AffineManifold(D); switch (D) { case 2: ret.Normal[0] = -(pts[1][1] - pts[0][1]); ret.Normal[1] = +(pts[1][0] - pts[0][0]); break; case 3: double a_1 = pts[1][0] - pts[0][0]; double a_2 = pts[1][1] - pts[0][1]; double a_3 = pts[1][2] - pts[0][2]; double b_1 = pts[2][0] - pts[0][0]; double b_2 = pts[2][1] - pts[0][1]; double b_3 = pts[2][2] - pts[0][2]; ret.Normal[0] = a_2 * b_3 - a_3 * b_2; ret.Normal[1] = a_3 * b_1 - a_1 * b_3; ret.Normal[2] = a_1 * b_2 - a_2 * b_1; break; default: throw new NotSupportedException(); } ret.a = GenericBlas.InnerProd(ret.Normal, pts[0]); return ret; }
/// <summary> /// Intersection of two 1D affine manifolds in 2D space /// </summary> static public Vector Intersect2D(AffineManifold A, AffineManifold B) { if (A.Normal.Dim != 2) { throw new ArgumentException(); } if (B.Normal.Dim != 2) { throw new ArgumentException(); } if (A.Normal.AbsSquare() <= 0.0) { throw new ArithmeticException(); } if (B.Normal.AbsSquare() <= 0.0) { throw new ArithmeticException(); } double n1x = A.Normal[0]; double n1y = A.Normal[1]; double a1 = A.a; double n2x = B.Normal[0]; double n2y = B.Normal[1]; double a2 = B.a; return(new Vector( (-n1y * a2 + a1 * n2y) / (n1x * n2y - n2x * n1y), -(-n1x * a2 + n2x * a1) / (n1x * n2y - n2x * n1y) )); }
/// <summary> /// constructs an affine manifold from a set of points /// </summary> /// <param name="pts"> /// points on the manifold; /// 1st index: point index. /// 2nd index: spatial dimension. /// </param> static public AffineManifold FromPoints(MultidimensionalArray pts) { int D = pts.GetLength(1); var ret = new AffineManifold(D); switch (D) { case 2: ret.Normal[0] = -(pts[1, 1] - pts[0, 1]); ret.Normal[1] = +(pts[1, 0] - pts[0, 0]); break; case 3: double a_1 = pts[1, 0] - pts[0, 0]; double a_2 = pts[1, 1] - pts[0, 1]; double a_3 = pts[1, 2] - pts[0, 2]; double b_1 = pts[2, 0] - pts[0, 0]; double b_2 = pts[2, 1] - pts[0, 1]; double b_3 = pts[2, 2] - pts[0, 2]; ret.Normal[0] = a_2 * b_3 - a_3 * b_2; ret.Normal[1] = a_3 * b_1 - a_1 * b_3; ret.Normal[2] = a_1 * b_2 - a_2 * b_1; break; default: throw new NotSupportedException(); } double[] Offset = pts.ExtractSubArrayShallow(0, -1).To1DArray(); ret.a = GenericBlas.InnerProd(ret.Normal, Offset); return ret; }
/// <summary> /// non-shallow cloning /// </summary> /// <returns></returns> public object Clone() { var ret = new AffineManifold(this.Normal.Dim); ret.Normal = this.Normal; ret.a = this.a; return(ret); }
/// <summary> /// constructs an affine manifold from a set of points /// </summary> /// <param name="pts"> /// points on the manifold; /// 1st index: point index. /// </param> static public AffineManifold FromPoints(params Vector[] pts) { int D = pts.Length; if (D <= 1) { throw new ArgumentException("1D or lower is not supported"); } for (int i = 0; i < D; i++) { if (pts[i].Dim != D) { throw new ArgumentException(); } } var ret = new AffineManifold(D); switch (D) { case 2: ret.Normal[0] = -(pts[1][1] - pts[0][1]); ret.Normal[1] = +(pts[1][0] - pts[0][0]); break; case 3: double a_1 = pts[1][0] - pts[0][0]; double a_2 = pts[1][1] - pts[0][1]; double a_3 = pts[1][2] - pts[0][2]; double b_1 = pts[2][0] - pts[0][0]; double b_2 = pts[2][1] - pts[0][1]; double b_3 = pts[2][2] - pts[0][2]; ret.Normal[0] = a_2 * b_3 - a_3 * b_2; ret.Normal[1] = a_3 * b_1 - a_1 * b_3; ret.Normal[2] = a_1 * b_2 - a_2 * b_1; break; default: throw new NotSupportedException(); } ret.a = ret.Normal * pts[0]; if (ret.Normal.AbsSquare() <= 0.0) { throw new ArithmeticException(); } return(ret); }
/// <summary> /// Intersection of two 1D affine manifolds in 2D space /// </summary> static public double[] Intersect2D(AffineManifold A, AffineManifold B) { if (A.Normal.Length != 2) throw new ArgumentException(); if (B.Normal.Length != 2) throw new ArgumentException(); double[] ret = new double[2]; double n1x = A.Normal[0]; double n1y = A.Normal[1]; double a1 = A.a; double n2x = B.Normal[0]; double n2y = B.Normal[1]; double a2 = B.a; ret[0] = (-n1y*a2+a1*n2y)/(n1x*n2y-n2x*n1y); ret[1] = -(-n1x*a2+n2x*a1)/(n1x*n2y-n2x*n1y); return ret; }
/// <summary> /// constructs an affine manifold from a set of points /// </summary> /// <param name="pts"> /// points on the manifold; /// 1st index: point index. /// 2nd index: spatial dimension. /// </param> static public AffineManifold FromPoints(MultidimensionalArray pts) { int D = pts.GetLength(1); var ret = new AffineManifold(D); switch (D) { case 2: ret.Normal[0] = -(pts[1, 1] - pts[0, 1]); ret.Normal[1] = +(pts[1, 0] - pts[0, 0]); break; case 3: double a_1 = pts[1, 0] - pts[0, 0]; double a_2 = pts[1, 1] - pts[0, 1]; double a_3 = pts[1, 2] - pts[0, 2]; double b_1 = pts[2, 0] - pts[0, 0]; double b_2 = pts[2, 1] - pts[0, 1]; double b_3 = pts[2, 2] - pts[0, 2]; ret.Normal[0] = a_2 * b_3 - a_3 * b_2; ret.Normal[1] = a_3 * b_1 - a_1 * b_3; ret.Normal[2] = a_1 * b_2 - a_2 * b_1; break; default: throw new NotSupportedException(); } double[] Offset = pts.ExtractSubArrayShallow(0, -1).To1DArray(); ret.a = ret.Normal * (new Vector(Offset)); if (ret.Normal.AbsSquare() <= 0.0) { throw new ArithmeticException(); } return(ret); }
/// <summary> /// non-shallow cloning /// </summary> /// <returns></returns> public object Clone() { var ret = new AffineManifold(this.Normal.Length); Array.Copy(this.Normal, ret.Normal, this.Normal.Length); ret.a = this.a; return ret; }