
//(c) Copyright 2005, Scott Vorthmann.  All rights reserved.

package com.vzome.core.commands;

import java.util.ArrayList;
import java.util.List;

import com.vzome.core.algebra.AlgebraicNumber;
import com.vzome.core.algebra.AlgebraicVector;
import com.vzome.core.construction.Construction;
import com.vzome.core.construction.ConstructionChanges;
import com.vzome.core.construction.ConstructionList;
import com.vzome.core.construction.Point;
import com.vzome.core.construction.PolygonFromVertices;

public class CommandPolygon extends AbstractCommand
{
    private static final Object[][] PARAM_SIGNATURE =
        new Object[][]{ { GENERIC_PARAM_NAME, Point.class } };

    private static final Object[][] ATTR_SIGNATURE = new Object[][]{};

    @Override
    public Object[][] getParameterSignature()
    {
        return PARAM_SIGNATURE;
    }

    @Override
    public Object[][] getAttributeSignature()
    {
        return ATTR_SIGNATURE;
    }
    
    @Override
    public ConstructionList apply( ConstructionList parameters, AttributeMap attrs, ConstructionChanges effects ) throws Failure
    {
        Boolean loadingFile = ((Boolean) attrs .get( Command .LOADING_FROM_FILE ) );
        boolean failed = false;
        ConstructionList result = new ConstructionList();
        final Construction[] params = parameters .getConstructions();
        List<Construction> verticesList = new ArrayList<>();
        
        AlgebraicVector normal = null, base = null;
        int numPoints = 0;
        for (Construction param : params) {
            if (param instanceof Point) {
                ++numPoints;
                verticesList.add(param);
                if (numPoints == 1) {
                    base = ((Point) verticesList .get( 0 ) ) .getLocation();
                } else if (numPoints == 3) {
                    AlgebraicVector v1 = ((Point) verticesList .get( 1 ) ) .getLocation() .minus( base );
                    AlgebraicVector v2 = ((Point) param).getLocation().minus(base);
                    normal = v1 .cross( v2 );
                    if ( normal .isOrigin() )
                        if ( loadingFile != null )
                            failed = true;
                        else
                            throw new Failure( "points are colinear" );
                } else if (numPoints > 3) {
                    AlgebraicVector loc = ((Point) param).getLocation().minus(base);
                    AlgebraicNumber dotProd = loc .dot( normal );
                    if ( ! dotProd .isZero() )
                        if ( loadingFile != null )
                            failed = true;
                        else
                            throw new Failure( "points not coplanar" );
                }
            }
        }
        if ( numPoints < 3 )
        {
            if ( loadingFile != null )
                failed = true;
            else
                throw new Failure( "A polygon requires at least three vertices." );
        }
        Point[] points = new Point[0];
        PolygonFromVertices poly = new PolygonFromVertices( verticesList .toArray( points ) );
        {
            
        }
        if ( failed )
            poly .setFailed(); // and don't add it to effects for rendering
        else
            effects .constructionAdded( poly );
        result .addConstruction( poly );
        return result;
    }
}

@@ -1357,28 +1357,21 @@
    List%3C
-Construction
+Point
 %3E vertic
@@ -1568,24 +1568,69 @@
 of Point) %7B%0A
+                Point point = (Point) param;%0A
             
@@ -1680,20 +1680,20 @@
 st.add(p
-aram
+oint
 );%0A     
@@ -1756,42 +1756,13 @@
 e = 
-((P
+p
 oint
-) verticesList .get( 0 ) ) 
 .get
@@ -1858,25 +1858,16 @@
 tor v1 =
- ((Point)
  vertice
@@ -1881,18 +1881,16 @@
 get( 1 )
- )
  .getLoc
@@ -1954,31 +1954,21 @@
 or v2 = 
-((P
+p
 oint
-) param)
 .getLoca
@@ -2234,47 +2234,1517 @@
     
-throw new Failure( %22points ar
+// DJH: As far as I can tell, the only problem with any of vertices being collinear%0A                            // is that Panel.getNormal and Face.getNormal both use the first three vertices %0A                            // to calculate their normals. At this point, even if they were changed %0A                            // to use any three points that are non-collinear (rather than just the first three points),%0A                            // they would generate files that are not readable by older versions of vzome%0A                            // unless we also automatically %22rotate%22 the points around the perimeter %0A                            // until the first three are non-collinear. Until then, it's necessary to keep this constraint.%0A                            // However, a polygon with the same collinear points in a different order %0A                            // is OK, just as long as the first three are not collinear.%0A                            // This message should imply the option of reordering the points.%0A                            // Also note that test cases, which construct Panels or Faces %0A                            // outside of this command must be careful not to introduce this problem %0A                            // since the Panel and Face classes don't check for the first three to be non-collinear. %0A                            // They expect the caller to have done that checking.%0A                            throw new Failure( %22First 3 points cannot b
 e col
+l
 inear
+.
 %22 );
@@ -3834,23 +3834,13 @@
 c = 
-((P
+p
 oint
-) param)
 .get
@@ -4147,23 +4147,27 @@
 ilure( %22
-p
+P
 oints 
+are 
 not copl
@@ -4170,16 +4170,17 @@
 coplanar
+.
 %22 );%0A   
@@ -4442,47 +4442,8 @@
   %7D%0A
-        Point%5B%5D points = new Point%5B0%5D;%0A
     
@@ -4525,52 +4525,43 @@
 ay( 
-points ) );%0A        %7B%0A            %0A        %7D
+new Point%5BverticesList.size()%5D ) );
 %0A   

Remove more unnecessary casts and clarify error message.