Beispiel #1
0
        /**
         * Test relation between this Pnt and circumcircle of a simplex.
         * @param simplex the simplex (as an array of Pnts)
         * @return -1, 0, or +1 for inside, on, or outside of circumcircle
         */
        public int vsCircumcircle(Pnt[] simplex)
        {
            Pnt[] matrix = new Pnt[simplex.Length + 1];
            for (int i = 0; i < simplex.Length; i++)
            {
                matrix[i] = simplex[i].extend(new double[] { 1, simplex[i].dot(simplex[i]) });
            }
            matrix[simplex.Length] = this.extend(new double[] { 1, this.dot(this) });
            double d      = determinant(matrix);
            int    result = -1;

            if (d > 0)
            {
                result = 1;
            }
            else if (d == 0)
            {
                result = 0;
            }


            if (content(simplex) < 0)
            {
                result = -result;
            }
            return(result);
        }
		/**
		 * Locate the triangle with point (a Pnt) inside (or on) it.
		 * @param point the Pnt to locate
		 * @return triangle (Simplex<Pnt>) that holds the point; null if no such triangle
		 */
		public Simplex locate(Pnt point) {
        Simplex triangle = mostRecent;
        if (!this.contains(triangle)) triangle = null;
        
        // Try a directed walk (this works fine in 2D, but can fail in 3D)
        Set visited = new HashSet();
        while (triangle != null) {
            if (visited.contains(triangle)) { // This should never happen
                Console.WriteLine("Warning: Caught in a locate loop");
                break;
            }
            visited.add(triangle);
            // Corner opposite point
            Pnt corner = point.isOutside((Pnt[]) triangle.toArray(new Pnt[0]));
            if (corner == null) return triangle;
            triangle = this.neighborOpposite(corner, triangle);
        }
        // No luck; try brute force
        Console.WriteLine("Warning: Checking all triangles for " + point);
        for (Iterator it = this.iterator(); it.hasNext();) {
            Simplex tri = (Simplex) it.next();
            if (point.isOutside((Pnt[]) tri.toArray(new Pnt[0])) == null) return tri;
        }
        // No such triangle
		Console.WriteLine("Warning: No triangle holds " + point);
        return null;
    }
Beispiel #3
0
        /**
         * Main program (used for testing).
         */
        public static void main(String[] args)
        {
            Pnt p = new Pnt(1, 2, 3);

            Console.WriteLine("Pnt created: " + p);
            Pnt[] matrix1 = { new Pnt(1, 2), new Pnt(3, 4) };
            Pnt[] matrix2 = { new Pnt(7, 0, 5), new Pnt(2, 4, 6), new Pnt(3, 8, 1) };
            Console.WriteLine("Results should be -2 and -288: ");
            Console.WriteLine(determinant(matrix1) + " " + determinant(matrix2));
            Pnt p1 = new Pnt(1, 1); Pnt p2 = new Pnt(-1, 1);

            Console.WriteLine("Angle between " + p1 + " and " + p2 + ": " + p1.angle(p2));
            Console.WriteLine(p1 + " subtract " + p2 + ": " + p1.subtract(p2));
            Pnt v0 = new Pnt(0, 0), v1 = new Pnt(1, 1), v2 = new Pnt(2, 2);

            Pnt[] vs = { v0, new Pnt(0, 1), new Pnt(1, 0) };
            Pnt   vp = new Pnt(.1, .1);

            Console.WriteLine(vp + " isInside " + toString(vs) + ": " + vp.isInside(vs));
            Console.WriteLine(v1 + " isInside " + toString(vs) + ": " + v1.isInside(vs));
            Console.WriteLine(vp + " vsCircumcircle " + toString(vs) + ": " +
                              vp.vsCircumcircle(vs));
            Console.WriteLine(v1 + " vsCircumcircle " + toString(vs) + ": " +
                              v1.vsCircumcircle(vs));
            Console.WriteLine(v2 + " vsCircumcircle " + toString(vs) + ": " +
                              v2.vsCircumcircle(vs));
            Console.WriteLine("Circumcenter of " + toString(vs) + " is " + circumcenter(vs));
        }
        /* Basic Drawing Methods */

        /**
         * Draw a point.
         * @param point the Pnt to draw
         */
        public void draw(Pnt point)
        {
            int r = pointRadius;
            int x = (int)point.coord(0);
            int y = (int)point.coord(1);

            g.fillOval(x - r, y - r, r + r, r + r);
        }
Beispiel #5
0
        /**
         * Perpendicular bisector of two Pnts.
         * Works in any dimension.  The coefficients are returned as a Pnt of one
         * higher dimension (e.g., (A,B,C,D) for an equation of the form
         * Ax + By + Cz + D = 0).
         * @param point the other point
         * @return the coefficients of the perpendicular bisector
         */
        public Pnt bisector(Pnt point)
        {
            int    dim  = dimCheck(point);
            Pnt    diff = this.subtract(point);
            Pnt    sum  = this.add(point);
            double dot  = diff.dot(sum);

            return(diff.extend(new double[] { -dot / 2 }));
        }
Beispiel #6
0
        /**
         * Check that dimensions match.
         * @param p the Pnt to check (against this Pnt)
         * @return the dimension of the Pnts
         * @throws IllegalArgumentException if dimension fail to match
         */
        public int dimCheck(Pnt p)
        {
            int len = this.coordinates.Length;

            if (len != p.coordinates.Length)
            {
                throw new InvalidOperationException("Dimension mismatch");
            }
            return(len);
        }
Beispiel #7
0
        /**
         * Add.
         * @param p the other Pnt
         * @return a new Pnt = this + p
         */
        public Pnt add(Pnt p)
        {
            int len = dimCheck(p);

            double[] coords = new double[len];
            for (int i = 0; i < len; i++)
            {
                coords[i] = this.coordinates[i] + p.coordinates[i];
            }
            return(new Pnt(coords));
        }
Beispiel #8
0
        /**
         * Dot product.
         * @param p the other Pnt
         * @return dot product of this Pnt and p
         */
        public double dot(Pnt p)
        {
            int    len = dimCheck(p);
            double sum = 0;

            for (int i = 0; i < len; i++)
            {
                sum += this.coordinates[i] * p.coordinates[i];
            }
            return(sum);
        }
 /**
  * Draw all the Voronoi edges.
  */
 public void drawAllVoronoi()
 {
     // Loop through all the edges of the DT (each is done twice)
     for (Iterator it = dt.iterator(); it.hasNext();)
     {
         Simplex triangle = (Simplex)it.next();
         for (Iterator otherIt = dt.neighbors(triangle).iterator(); otherIt.hasNext();)
         {
             Simplex other = (Simplex)otherIt.next();
             Pnt     p     = Pnt.circumcenter((Pnt[])triangle.toArray(new Pnt[0]));
             Pnt     q     = Pnt.circumcenter((Pnt[])other.toArray(new Pnt[0]));
             draw(p, q);
         }
     }
 }
        /**
         * Draw a circle.
         * @param center the center of the circle
         * @param radius the circle's radius
         * @param fillColor; null implies no fill
         */
        public void draw(Pnt center, double radius, Color fillColor)
        {
            int x = (int)center.coord(0);
            int y = (int)center.coord(1);
            int r = (int)radius;

            if (fillColor != null)
            {
                Color temp = g.getColor();
                g.setColor(fillColor);
                g.fillOval(x - r, y - r, r + r, r + r);
                g.setColor(temp);
            }
            g.drawOval(x - r, y - r, r + r, r + r);
        }
Beispiel #11
0
        /* Pnts as simplices */

        /**
         * Determine the signed content (i.e., area or volume, etc.) of a simplex.
         * @param simplex the simplex (as an array of Pnts)
         * @return the signed content of the simplex
         */
        public static double content(Pnt[] simplex)
        {
            Pnt[] matrix = new Pnt[simplex.Length];
            for (int i = 0; i < matrix.Length; i++)
            {
                matrix[i] = simplex[i].extend(new double[] { 1 });
            }
            int fact = 1;

            for (int i = 1; i < matrix.Length; i++)
            {
                fact = fact * i;
            }
            return(determinant(matrix) / fact);
        }
        /**
         * Mouse press.
         * @param e the MouseEvent
         */
        public void mousePressed(MouseEvent e)
        {
            if (e.getComponent() != this)
            {
                return;
            }
            Pnt point = new Pnt(e.getX(), e.getY());

            if (debug)
            {
                Console.WriteLine("Click " + point);
            }
            dt.delaunayPlace(point);
            repaint();
        }
Beispiel #13
0
        /**
         * Test if this Pnt is on a simplex.
         * @param simplex the simplex (an array of Pnts)
         * @return the simplex Pnt that "witnesses" on-ness (or null if not on)
         */
        public Pnt isOn(Pnt[] simplex)
        {
            int[] result  = this.relation(simplex);
            Pnt   witness = null;

            for (int i = 0; i < result.Length; i++)
            {
                if (result[i] == 0)
                {
                    witness = simplex[i];
                }
                else if (result[i] > 0)
                {
                    return(null);
                }
            }
            return(witness);
        }
		/**
		 * Place a new point site into the DT.
		 * @param site the new Pnt
		 * @return set of all new triangles created
		 */
		public Set delaunayPlace(Pnt site) {
        Set newTriangles = new HashSet();
        Set oldTriangles = new HashSet();
        Set doneSet = new HashSet();
        LinkedList waitingQ = new LinkedList();
        
        // Locate containing triangle
        if (debug) Console.WriteLine("Locate");
        Simplex triangle = locate(site);
        
        // Give up if no containing triangle or if site is already in DT
		var triangle_null = triangle == null;
        if (triangle_null || triangle.contains(site)) return newTriangles;
        
        // Find Delaunay cavity (those triangles with site in their circumcircles)
        if (debug) Console.WriteLine("Cavity");
        waitingQ.add(triangle);
        while (!waitingQ.isEmpty()) {
            triangle = (Simplex) waitingQ.removeFirst();      
            if (site.vsCircumcircle((Pnt[]) triangle.toArray(new Pnt[0])) == 1) continue;
            oldTriangles.add(triangle);
            Iterator it = this.neighbors(triangle).iterator();
            for (; it.hasNext();) {
                Simplex tri = (Simplex) it.next();
                if (doneSet.contains(tri)) continue;
                doneSet.add(tri);
                waitingQ.add(tri);
            }
        }
        // Create the new triangles
        if (debug) Console.WriteLine("Create");
        for (Iterator it = Simplex.boundary(oldTriangles).iterator(); it.hasNext();) {
            Set facet = (Set) it.next();
            facet.add(site);
            newTriangles.add(new Simplex(facet));
        }
        // Replace old triangles with new triangles
		if (debug) Console.WriteLine("Update");
        this.update(oldTriangles, newTriangles);
        
        // Update mostRecent triangle
        if (!newTriangles.isEmpty()) mostRecent = (Simplex) newTriangles.iterator().next();
        return newTriangles;
    }
Beispiel #15
0
        /**
         * Locate the triangle with point (a Pnt) inside (or on) it.
         * @param point the Pnt to locate
         * @return triangle (Simplex<Pnt>) that holds the point; null if no such triangle
         */
        public Simplex locate(Pnt point)
        {
            Simplex triangle = mostRecent;

            if (!this.contains(triangle))
            {
                triangle = null;
            }

            // Try a directed walk (this works fine in 2D, but can fail in 3D)
            Set visited = new HashSet();

            while (triangle != null)
            {
                if (visited.contains(triangle)) // This should never happen
                {
                    Console.WriteLine("Warning: Caught in a locate loop");
                    break;
                }
                visited.add(triangle);
                // Corner opposite point
                Pnt corner = point.isOutside((Pnt[])triangle.toArray(new Pnt[0]));
                if (corner == null)
                {
                    return(triangle);
                }
                triangle = this.neighborOpposite(corner, triangle);
            }
            // No luck; try brute force
            Console.WriteLine("Warning: Checking all triangles for " + point);
            for (Iterator it = this.iterator(); it.hasNext();)
            {
                Simplex tri = (Simplex)it.next();
                if (point.isOutside((Pnt[])tri.toArray(new Pnt[0])) == null)
                {
                    return(tri);
                }
            }
            // No such triangle
            Console.WriteLine("Warning: No triangle holds " + point);
            return(null);
        }
 /**
  * Draw all the empty circles (one for each triangle) of the DT.
  */
 public void drawAllCircles()
 {
     // Loop through all triangles of the DT
     for (Iterator it = dt.iterator(); it.hasNext();)
     {
         Simplex triangle = (Simplex)it.next();
         for (Iterator otherIt = initialTriangle.iterator(); otherIt.hasNext();)
         {
             Pnt p = (Pnt)otherIt.next();
             if (triangle.contains(p))
             {
                 triangle = null;
                 break;
             }
         }
         if (triangle != null)
         {
             Pnt    c      = Pnt.circumcenter((Pnt[])triangle.toArray(new Pnt[0]));
             double radius = c.subtract((Pnt)triangle.iterator().next()).magnitude();
             draw(c, radius, null);
         }
     }
 }
Beispiel #17
0
        /**
         * Circumcenter of a simplex.
         * @param simplex the simplex (as an array of Pnts)
         * @return the circumcenter (a Pnt) of simplex
         */
        public static Pnt circumcenter(Pnt[] simplex)
        {
            int dim = simplex[0].dimension();

            if (simplex.Length - 1 != dim)
            {
                throw new InvalidOperationException("Dimension mismatch");
            }
            Pnt[] matrix = new Pnt[dim];
            for (int i = 0; i < dim; i++)
            {
                matrix[i] = simplex[i].bisector(simplex[i + 1]);
            }
            Pnt    hCenter = cross(matrix);               // Center in homogeneous coordinates
            double last    = hCenter.coordinates[dim];

            double[] result = new double[dim];
            for (int i = 0; i < dim; i++)
            {
                result[i] = hCenter.coordinates[i] / last;
            }
            return(new Pnt(result));
        }
Beispiel #18
0
        /**
         * Equality.
         * @param other the other Object to compare to
         * @return true iff the Pnts have the same coordinates
         */
        public bool equals(object other)
        {
            // ficme: jsc should insert parenthesis
            var other_is_Pnt = (other is Pnt);

            if (!other_is_Pnt)
            {
                return(false);
            }
            Pnt p = (Pnt)other;

            if (this.coordinates.Length != p.coordinates.Length)
            {
                return(false);
            }
            for (int i = 0; i < this.coordinates.Length; i++)
            {
                if (this.coordinates[i] != p.coordinates[i])
                {
                    return(false);
                }
            }
            return(true);
        }
Beispiel #19
0
 /**
  * Angle (in radians) between two Pnts (treated as vectors).
  * @param p the other Pnt
  * @return the angle (in radians) between the two Pnts
  */
 public double angle(Pnt p)
 {
     return(Math.Acos(this.dot(p) / (this.magnitude() * p.magnitude())));
 }
 /**
  * Draw a line segment.
  * @param endA one endpoint
  * @param endB the other endpoint
  */
 public void draw(Pnt endA, Pnt endB)
 {
     g.drawLine((int)endA.coord(0), (int)endA.coord(1),
                (int)endB.coord(0), (int)endB.coord(1));
 }
		/**
		 * Draw a line segment.
		 * @param endA one endpoint
		 * @param endB the other endpoint
		 */
		public void draw(Pnt endA, Pnt endB)
		{
			g.drawLine((int)endA.coord(0), (int)endA.coord(1),
					   (int)endB.coord(0), (int)endB.coord(1));
		}
		/**
		 * Mouse press.
		 * @param e the MouseEvent
		 */
		public void mousePressed(MouseEvent e)
		{
			if (e.getComponent() != this) return;
			Pnt point = new Pnt(e.getX(), e.getY());
			if (debug) Console.WriteLine("Click " + point);
			dt.delaunayPlace(point);
			repaint();
		}
Beispiel #23
0
		/**
		 * Circumcenter of a simplex.
		 * @param simplex the simplex (as an array of Pnts)
		 * @return the circumcenter (a Pnt) of simplex
		 */
		public static Pnt circumcenter(Pnt[] simplex)
		{
			int dim = simplex[0].dimension();
			if (simplex.Length - 1 != dim)
				throw new InvalidOperationException("Dimension mismatch");
			Pnt[] matrix = new Pnt[dim];
			for (int i = 0; i < dim; i++)
				matrix[i] = simplex[i].bisector(simplex[i + 1]);
			Pnt hCenter = cross(matrix);      // Center in homogeneous coordinates
			double last = hCenter.coordinates[dim];
			double[] result = new double[dim];
			for (int i = 0; i < dim; i++) result[i] = hCenter.coordinates[i] / last;
			return new Pnt(result);
		}
Beispiel #24
0
		/**
		 * Test if this Pnt is inside a simplex.
		 * @param simplex the simplex (an arary of Pnts)
		 * @return true iff this Pnt is inside simplex.
		 */
		public bool isInside(Pnt[] simplex)
		{
			int[] result = this.relation(simplex);
			for (int i = 0; i < result.Length; i++) if (result[i] >= 0) return false;
			return true;
		}
Beispiel #25
0
		/**
		 * Test if this Pnt is outside of simplex.
		 * @param simplex the simplex (an array of Pnts)
		 * @return the simplex Pnt that "witnesses" outsideness (or null if not outside)
		 */
		public Pnt isOutside(Pnt[] simplex)
		{
			int[] result = this.relation(simplex);
			for (int i = 0; i < result.Length; i++)
			{
				if (result[i] > 0) return simplex[i];
			}
			return null;
		}
Beispiel #26
0
		/**
		 * Check that dimensions match.
		 * @param p the Pnt to check (against this Pnt)
		 * @return the dimension of the Pnts
		 * @throws IllegalArgumentException if dimension fail to match
		 */
		public int dimCheck(Pnt p)
		{
			int len = this.coordinates.Length;
			if (len != p.coordinates.Length)
				throw new InvalidOperationException("Dimension mismatch");
			return len;
		}
Beispiel #27
0
        /**
         * Place a new point site into the DT.
         * @param site the new Pnt
         * @return set of all new triangles created
         */
        public Set delaunayPlace(Pnt site)
        {
            Set        newTriangles = new HashSet();
            Set        oldTriangles = new HashSet();
            Set        doneSet      = new HashSet();
            LinkedList waitingQ     = new LinkedList();

            // Locate containing triangle
            if (debug)
            {
                Console.WriteLine("Locate");
            }
            Simplex triangle = locate(site);

            // Give up if no containing triangle or if site is already in DT
            var triangle_null = triangle == null;

            if (triangle_null || triangle.contains(site))
            {
                return(newTriangles);
            }

            // Find Delaunay cavity (those triangles with site in their circumcircles)
            if (debug)
            {
                Console.WriteLine("Cavity");
            }
            waitingQ.add(triangle);
            while (!waitingQ.isEmpty())
            {
                triangle = (Simplex)waitingQ.removeFirst();
                if (site.vsCircumcircle((Pnt[])triangle.toArray(new Pnt[0])) == 1)
                {
                    continue;
                }
                oldTriangles.add(triangle);
                Iterator it = this.neighbors(triangle).iterator();
                for (; it.hasNext();)
                {
                    Simplex tri = (Simplex)it.next();
                    if (doneSet.contains(tri))
                    {
                        continue;
                    }
                    doneSet.add(tri);
                    waitingQ.add(tri);
                }
            }
            // Create the new triangles
            if (debug)
            {
                Console.WriteLine("Create");
            }
            for (Iterator it = Simplex.boundary(oldTriangles).iterator(); it.hasNext();)
            {
                Set facet = (Set)it.next();
                facet.add(site);
                newTriangles.add(new Simplex(facet));
            }
            // Replace old triangles with new triangles
            if (debug)
            {
                Console.WriteLine("Update");
            }
            this.update(oldTriangles, newTriangles);

            // Update mostRecent triangle
            if (!newTriangles.isEmpty())
            {
                mostRecent = (Simplex)newTriangles.iterator().next();
            }
            return(newTriangles);
        }
Beispiel #28
0
		/* Pnts as simplices */

		/**
		 * Determine the signed content (i.e., area or volume, etc.) of a simplex.
		 * @param simplex the simplex (as an array of Pnts)
		 * @return the signed content of the simplex
		 */
		public static double content(Pnt[] simplex)
		{
			Pnt[] matrix = new Pnt[simplex.Length];
			for (int i = 0; i < matrix.Length; i++)
				matrix[i] = simplex[i].extend(new double[] { 1 });
			int fact = 1;
			for (int i = 1; i < matrix.Length; i++) fact = fact * i;
			return determinant(matrix) / fact;
		}
Beispiel #29
0
		/**
		 * Add.
		 * @param p the other Pnt
		 * @return a new Pnt = this + p
		 */
		public Pnt add(Pnt p)
		{
			int len = dimCheck(p);
			double[] coords = new double[len];
			for (int i = 0; i < len; i++)
				coords[i] = this.coordinates[i] + p.coordinates[i];
			return new Pnt(coords);
		}
Beispiel #30
0
		/**
		 * Relation between this Pnt and a simplex (represented as an array of Pnts).
		 * Result is an array of signs, one for each vertex of the simplex, indicating
		 * the relation between the vertex, the vertex's opposite facet, and this
		 * Pnt. <pre>
		 *   -1 means Pnt is on same side of facet
		 *    0 means Pnt is on the facet
		 *   +1 means Pnt is on opposite side of facet</pre>
		 * @param simplex an array of Pnts representing a simplex
		 * @return an array of signs showing relation between this Pnt and the simplex
		 * @throws IllegalArgumentExcpetion if the simplex is degenerate
		 */
		public int[] relation(Pnt[] simplex)
		{
			/* In 2D, we compute the cross of this matrix:
			 *    1   1   1   1
			 *    p0  a0  b0  c0
			 *    p1  a1  b1  c1
			 * where (a, b, c) is the simplex and p is this Pnt.  The result
			 * is a vector in which the first coordinate is the signed area
			 * (all signed areas are off by the same constant factor) of
			 * the simplex and the remaining coordinates are the *negated*
			 * signed areas for the simplices in which p is substituted for
			 * each of the vertices. Analogous results occur in higher dimensions.
			 */
			int dim = simplex.Length - 1;
			if (this.dimension() != dim)
				throw new InvalidOperationException("Dimension mismatch");

			/* Create and load the matrix */
			Pnt[] matrix = new Pnt[dim + 1];
			/* First row */
			double[] coords = new double[dim + 2];
			for (int j = 0; j < coords.Length; j++) coords[j] = 1;
			matrix[0] = new Pnt(coords);
			/* Other rows */
			for (int i = 0; i < dim; i++)
			{
				coords[0] = this.coordinates[i];
				for (int j = 0; j < simplex.Length; j++)
					coords[j + 1] = simplex[j].coordinates[i];
				matrix[i + 1] = new Pnt(coords);
			}

			/* Compute and analyze the vector of areas/volumes/contents */
			Pnt vector = cross(matrix);
			double content = vector.coordinates[0];
			int[] result = new int[dim + 1];
			for (int i = 0; i < result.Length; i++)
			{
				double value = vector.coordinates[i + 1];
				if (Math.Abs(value) <= 1.0e-6 * Math.Abs(content)) result[i] = 0;
				else if (value < 0) result[i] = -1;
				else result[i] = 1;
			}
			if (content < 0)
			{
				for (int i = 0; i < result.Length; i++) result[i] = -result[i];
			}
			if (content == 0)
			{
				for (int i = 0; i < result.Length; i++) result[i] = Math.Abs(result[i]);
			}
			return result;
		}
Beispiel #31
0
		/**
		 * Angle (in radians) between two Pnts (treated as vectors).
		 * @param p the other Pnt
		 * @return the angle (in radians) between the two Pnts
		 */
		public double angle(Pnt p)
		{
			return Math.Acos(this.dot(p) / (this.magnitude() * p.magnitude()));
		}
Beispiel #32
0
		/**
		 * Test if this Pnt is on a simplex.
		 * @param simplex the simplex (an array of Pnts)
		 * @return the simplex Pnt that "witnesses" on-ness (or null if not on)
		 */
		public Pnt isOn(Pnt[] simplex)
		{
			int[] result = this.relation(simplex);
			Pnt witness = null;
			for (int i = 0; i < result.Length; i++)
			{
				if (result[i] == 0) witness = simplex[i];
				else if (result[i] > 0) return null;
			}
			return witness;
		}
Beispiel #33
0
		/**
		 * Perpendicular bisector of two Pnts.
		 * Works in any dimension.  The coefficients are returned as a Pnt of one
		 * higher dimension (e.g., (A,B,C,D) for an equation of the form
		 * Ax + By + Cz + D = 0).
		 * @param point the other point
		 * @return the coefficients of the perpendicular bisector
		 */
		public Pnt bisector(Pnt point)
		{
			int dim = dimCheck(point);
			Pnt diff = this.subtract(point);
			Pnt sum = this.add(point);
			double dot = diff.dot(sum);
			return diff.extend(new double[] { -dot / 2 });
		}
Beispiel #34
0
		/**
		 * Test relation between this Pnt and circumcircle of a simplex.
		 * @param simplex the simplex (as an array of Pnts)
		 * @return -1, 0, or +1 for inside, on, or outside of circumcircle
		 */
		public int vsCircumcircle(Pnt[] simplex)
		{
			Pnt[] matrix = new Pnt[simplex.Length + 1];
			for (int i = 0; i < simplex.Length; i++)
				matrix[i] = simplex[i].extend(new double[] { 1, simplex[i].dot(simplex[i]) });
			matrix[simplex.Length] = this.extend(new double[] { 1, this.dot(this) });
			double d = determinant(matrix);
			int result = -1;

			if (d > 0)
				result = 1;
			else if (d == 0)
				result = 0;


			if (content(simplex) < 0) result = -result;
			return result;
		}
Beispiel #35
0
		/* Pnts as matrices */

		/**
		 * Create a String for a matrix.
		 * @param matrix the matrix (an array of Pnts)
		 * @return a String represenation of the matrix
		 */
		public static string toString(Pnt[] matrix)
		{
			var buf = new StringBuilder("{");
			for (int i = 0; i < matrix.Length; i++) buf.Append(" " + matrix[i]);
			buf.Append(" }");
			return buf.ToString();
		}
Beispiel #36
0
		/**
		 * Main program (used for testing).
		 */
		public static void main(String[] args)
		{
			Pnt p = new Pnt(1, 2, 3);
			Console.WriteLine("Pnt created: " + p);
			Pnt[] matrix1 = { new Pnt(1, 2), new Pnt(3, 4) };
			Pnt[] matrix2 = { new Pnt(7, 0, 5), new Pnt(2, 4, 6), new Pnt(3, 8, 1) };
			Console.WriteLine("Results should be -2 and -288: ");
			Console.WriteLine(determinant(matrix1) + " " + determinant(matrix2));
			Pnt p1 = new Pnt(1, 1); Pnt p2 = new Pnt(-1, 1);
			Console.WriteLine("Angle between " + p1 + " and " + p2 + ": " + p1.angle(p2));
			Console.WriteLine(p1 + " subtract " + p2 + ": " + p1.subtract(p2));
			Pnt v0 = new Pnt(0, 0), v1 = new Pnt(1, 1), v2 = new Pnt(2, 2);
			Pnt[] vs = { v0, new Pnt(0, 1), new Pnt(1, 0) };
			Pnt vp = new Pnt(.1, .1);
			Console.WriteLine(vp + " isInside " + toString(vs) + ": " + vp.isInside(vs));
			Console.WriteLine(v1 + " isInside " + toString(vs) + ": " + v1.isInside(vs));
			Console.WriteLine(vp + " vsCircumcircle " + toString(vs) + ": " +
							   vp.vsCircumcircle(vs));
			Console.WriteLine(v1 + " vsCircumcircle " + toString(vs) + ": " +
							   v1.vsCircumcircle(vs));
			Console.WriteLine(v2 + " vsCircumcircle " + toString(vs) + ": " +
							   v2.vsCircumcircle(vs));
			Console.WriteLine("Circumcenter of " + toString(vs) + " is " + circumcenter(vs));
		}
Beispiel #37
0
		/**
		 * Compute the determinant of a matrix (array of Pnts).
		 * This is not an efficient implementation, but should be adequate 
		 * for low dimension.
		 * @param matrix the matrix as an array of Pnts
		 * @return the determinnant of the input matrix
		 * @throws IllegalArgumentException if dimensions are wrong
		 */
		public static double determinant(Pnt[] matrix)
		{
			if (matrix.Length != matrix[0].dimension())
				throw new InvalidOperationException("Matrix is not square");
			var columns = new bool[matrix.Length];
			for (int i = 0; i < matrix.Length; i++) columns[i] = true;
			return determinant(matrix, 0, columns);

		}
		/* Basic Drawing Methods */

		/**
		 * Draw a point.
		 * @param point the Pnt to draw
		 */
		public void draw(Pnt point)
		{
			int r = pointRadius;
			int x = (int)point.coord(0);
			int y = (int)point.coord(1);
			g.fillOval(x - r, y - r, r + r, r + r);
		}
Beispiel #39
0
		/**
		 * Compute the determinant of a submatrix specified by starting row
		 * and by "active" columns.
		 * @param matrix the matrix as an array of Pnts
		 * @param row the starting row
		 * @param columns a boolean array indicating the "active" columns
		 * @return the determinant of the specified submatrix
		 * @throws ArrayIndexOutOfBoundsException if dimensions are wrong
		 */
		private static double determinant(Pnt[] matrix, int row, bool[] columns)
		{
			if (row == matrix.Length) return 1;
			double sum = 0;
			int sign = 1;
			for (int col = 0; col < columns.Length; col++)
			{
				// fixme: ldelem bool should be supported
				var columns_col = columns[col];
				if (columns_col)
				{
					columns[col] = false;
					sum += sign * matrix[row].coordinates[col] *
						   determinant(matrix, row + 1, columns);
					columns[col] = true;
					sign = -sign;
				}
			}
			return sum;
		}
		/**
		 * Draw a circle.
		 * @param center the center of the circle
		 * @param radius the circle's radius
		 * @param fillColor; null implies no fill
		 */
		public void draw(Pnt center, double radius, Color fillColor)
		{
			int x = (int)center.coord(0);
			int y = (int)center.coord(1);
			int r = (int)radius;
			if (fillColor != null)
			{
				Color temp = g.getColor();
				g.setColor(fillColor);
				g.fillOval(x - r, y - r, r + r, r + r);
				g.setColor(temp);
			}
			g.drawOval(x - r, y - r, r + r, r + r);
		}
Beispiel #41
0
		/**
		 * Compute generalized cross-product of the rows of a matrix.
		 * The result is a Pnt perpendicular (as a vector) to each row of
		 * the matrix.  This is not an efficient implementation, but should 
		 * be adequate for low dimension.
		 * @param matrix the matrix of Pnts (one less row than the Pnt dimension)
		 * @return a Pnt perpendicular to each row Pnt
		 * @throws IllegalArgumentException if matrix is wrong shape
		 */
		public static Pnt cross(Pnt[] matrix)
		{
			int len = matrix.Length + 1;
			if (len != matrix[0].dimension())
				throw new InvalidOperationException("Dimension mismatch");
			var columns = new bool[len];
			for (int i = 0; i < len; i++) columns[i] = true;
			double[] result = new double[len];
			int sign = 1;
			try
			{
				for (int i = 0; i < len; i++)
				{
					columns[i] = false;
					result[i] = sign * determinant(matrix, 0, columns);
					columns[i] = true;
					sign = -sign;
				}
			}
			catch //(ArrayIndexOutOfBoundsException e)
			{
				throw new InvalidOperationException("Matrix is wrong shape");
			}
			return new Pnt(result);
		}
Beispiel #42
0
		/**
		 * Dot product.
		 * @param p the other Pnt
		 * @return dot product of this Pnt and p
		 */
		public double dot(Pnt p)
		{
			int len = dimCheck(p);
			double sum = 0;
			for (int i = 0; i < len; i++)
				sum += this.coordinates[i] * p.coordinates[i];
			return sum;
		}
Beispiel #43
0
        /**
         * Relation between this Pnt and a simplex (represented as an array of Pnts).
         * Result is an array of signs, one for each vertex of the simplex, indicating
         * the relation between the vertex, the vertex's opposite facet, and this
         * Pnt. <pre>
         *   -1 means Pnt is on same side of facet
         *    0 means Pnt is on the facet
         *   +1 means Pnt is on opposite side of facet</pre>
         * @param simplex an array of Pnts representing a simplex
         * @return an array of signs showing relation between this Pnt and the simplex
         * @throws IllegalArgumentExcpetion if the simplex is degenerate
         */
        public int[] relation(Pnt[] simplex)
        {
            /* In 2D, we compute the cross of this matrix:
             *    1   1   1   1
             *    p0  a0  b0  c0
             *    p1  a1  b1  c1
             * where (a, b, c) is the simplex and p is this Pnt.  The result
             * is a vector in which the first coordinate is the signed area
             * (all signed areas are off by the same constant factor) of
             * the simplex and the remaining coordinates are the *negated*
             * signed areas for the simplices in which p is substituted for
             * each of the vertices. Analogous results occur in higher dimensions.
             */
            int dim = simplex.Length - 1;

            if (this.dimension() != dim)
            {
                throw new InvalidOperationException("Dimension mismatch");
            }

            /* Create and load the matrix */
            Pnt[] matrix = new Pnt[dim + 1];
            /* First row */
            double[] coords = new double[dim + 2];
            for (int j = 0; j < coords.Length; j++)
            {
                coords[j] = 1;
            }
            matrix[0] = new Pnt(coords);
            /* Other rows */
            for (int i = 0; i < dim; i++)
            {
                coords[0] = this.coordinates[i];
                for (int j = 0; j < simplex.Length; j++)
                {
                    coords[j + 1] = simplex[j].coordinates[i];
                }
                matrix[i + 1] = new Pnt(coords);
            }

            /* Compute and analyze the vector of areas/volumes/contents */
            Pnt    vector  = cross(matrix);
            double content = vector.coordinates[0];

            int[] result = new int[dim + 1];
            for (int i = 0; i < result.Length; i++)
            {
                double value = vector.coordinates[i + 1];
                if (Math.Abs(value) <= 1.0e-6 * Math.Abs(content))
                {
                    result[i] = 0;
                }
                else if (value < 0)
                {
                    result[i] = -1;
                }
                else
                {
                    result[i] = 1;
                }
            }
            if (content < 0)
            {
                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = -result[i];
                }
            }
            if (content == 0)
            {
                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = Math.Abs(result[i]);
                }
            }
            return(result);
        }