Package es.iiia.shapegrammar.utils

Source Code of es.iiia.shapegrammar.utils.ShapeTools

package es.iiia.shapegrammar.utils;

import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;

import org.eclipse.core.runtime.IProgressMonitor;

import Jama.Matrix;
import es.iiia.shapegrammar.execution.ExecutionReport;
import es.iiia.shapegrammar.model.ShapeGrammarModel;
import es.iiia.shapegrammar.shape.CarrierModel;
import es.iiia.shapegrammar.shape.IntersectionModel;
import es.iiia.shapegrammar.shape.LineModel;
import es.iiia.shapegrammar.shape.MarkerModel;
import es.iiia.shapegrammar.shape.ShapeModel;
import es.iiia.shapegrammar.shape.guides.IntersectionTriplet;
import es.iiia.shapegrammar.shape.guides.LineDefinition;

/**
* Created by Tomas Trescak, @ IIIA, UAB Barcelona.
* Date: Oct 22, 2008
* Time: 1:59:47 PM
*/
public class ShapeTools {

//    private static ArrayList<String> pairs;
//    private static Random random = new Random();
   
       public static void createMaximalLines(ArrayList<LineModel> currentLines) throws Exception {
        LineModel leftLine = null;
      LineModel rightLine = null;
        int rightIndex;

        for (int i = 0; i < currentLines.size(); i++) {
            for (int j = 0; j < currentLines.size(); j++) {
                // avoid duplicate testing
                if (i >= j) continue;

                // sort lines left to right
        rightIndex = (
            MathUtils.compare(currentLines.get(i).getP1(),
            currentLines.get(j).getP1()) == 1) ? i : j;
        leftLine = currentLines.get(rightIndex == i ? j : i);
        rightLine = currentLines.get(rightIndex);
               
                // proceed to test the lines
                if (MathUtils.compare(leftLine.getP2(), rightLine.getP1()) != -1 &&
                        MathUtils.vectorsEqual(leftLine, rightLine) &&
                        MathUtils.vectorsEqual(
                                leftLine.getP1(), leftLine.getP2(),
                                leftLine.getP1(), rightLine.getP2()
                        )) {

                  // set the line to the longest possible
                  if (MathUtils.compare(leftLine.getP2(), rightLine.getP2()) == -1) {
                    flipPoints(leftLine.getP2(), rightLine.getP2());
                  }
                 
                    Debugger.getInstance().addMessage("REMOVING: " + currentLines.get(rightIndex).toString());
                    currentLines.remove(rightIndex);
                    //decrease iterator
                    j--;
                   
                }
            }
        }
    }



    /**
     * Finds instences of subshape in shape. Returns number of results depending on randomization fator
     *
     * @param subShape      Subshape to be found
     * @param shape         Shape where we're finding subshape
     * @param randomization (0: all instances, 1: first found, >1 modulo randomization)
     * @param useMarkers    checks if markers are used
     * @return
     */
    public static ArrayList<ShapeModel> findSubShape
       (ShapeModel subShape,
        ShapeModel shape,
        ArrayList<ShapeModel> excludeShapeList,
        int randomization,
        boolean useMarkers,
        int maximumSubshapes,
        IProgressMonitor monitor) throws Exception {

        // we limit the smallest possible shape
        if (subShape.getIntersections().size() == 0) {
            String message = "Shape size exption! The smallest shape has to have at least 3 points";
            Debugger.getInstance().addMessage(message);
            throw new Exception(message);
        }
       
        // init return list
        ArrayList<ShapeModel> subShapes = new ArrayList<ShapeModel>();

        if (shape.getIntersections().size() < subShape.getIntersections().size()) {
            Debugger.getInstance().addMessage("ERROR: Shape has smaller ammount of intersections");
            return subShapes;
        }
       
        ExecutionReport.shapeTested();
       
        //monitor.beginTask("Detecting intersections", 1);      
        // Get the intersection we will use to find a transformation
        IntersectionModel from = subShape.getIntersections().get(0);
        // Get the list of intersection in the subshape
        ArrayList<IntersectionModel> fromIntersections = subShape.getIntersections();
        // Get the list of intersection in the shape
        ArrayList<IntersectionModel> toIntersections = shape.getIntersections();
        //monitor.worked(1);
        //monitor.beginTask("Checking " + shape.getIntersections().size() + " intersections", shape.getIntersections().size());
    
        ExecutionReport.setIntersections(toIntersections.size());
        ExecutionReport.setCombinations(fromIntersections.size(), toIntersections.size());      
       
        // Point pairing tester allows detection of unpaired poins upon transformation
        PointPairingTester pairTester = new PointPairingTester(subShape, shape);
        ShapeModel lastFound = null;
        boolean markerFound, exclusionFound;      

        /* create all non identical permutations of points
          1. Take first transformation from subShape (has smallest angle)
          2. Create second triplets
          3. For each combination of points create transformation and test
        */

        Matrix A = new Matrix(6, 6);
        Matrix b = new Matrix(6, 1);
        Matrix solution;
        Matrix subsolution = new Matrix(2, 2);
        Point2D transformedPoint = new Point2D.Double();

        // output transform
        AffineTransform outTransform = new AffineTransform();

        int[] fromIndexes = new int[3];

        // TODO: REDO
        fromIndexes[0] = 0;
        fromIndexes[1] = 1;
        fromIndexes[2] = 2;

        // create left matrix
        // 1st row
        IntersectionTriplet fromTriplet = from.getTriplet();

        A.set(0, 0, from.getIntersection().getX());
        A.set(0, 1, from.getIntersection().getY());
        A.set(0, 2, 1);
        // 2nd
        A.set(1, 3, from.getIntersection().getX());
        A.set(1, 4, from.getIntersection().getY());
        A.set(1, 5, 1);
        // 3rd
        A.set(2, 0, fromTriplet.getPointA().getX());
        A.set(2, 1, fromTriplet.getPointA().getY());
        A.set(2, 2, 1);
        // 4th
        A.set(3, 3, fromTriplet.getPointA().getX());
        A.set(3, 4, fromTriplet.getPointA().getY());
        A.set(3, 5, 1);
        // 5th
        A.set(4, 0, fromTriplet.getPointB().getX());
        A.set(4, 1, fromTriplet.getPointB().getY());
        A.set(4, 2, 1);
        // 6th
        A.set(5, 3, fromTriplet.getPointB().getX());
        A.set(5, 4, fromTriplet.getPointB().getY());
        A.set(5, 5, 1);

        // now find all intersection points in shape with same angle and ratio as original intersection
        IntersectionModel to;
        ArrayList<IntersectionTriplet> intersectionPairs;
        IntersectionTriplet currentPair;

        //Debugger.getInstance().addMessage("Init pair: " + from.getIntersection().toString() + fromTriplet.toString());

        // show markers
        //System.out.println("MARKERS");
        for (MarkerModel model : shape.getMarkers()) {
          Debugger.getInstance().addMessage(model.getLocation().toString());
        }
       
        // get itersections with the same angle
        toIntersections = shape.getIntersections(from.getAngle());     
       
        ExecutionReport.setGoodIntersections(toIntersections.size());
        long triplets = 0;
        for (IntersectionModel intr : toIntersections) {
          ArrayList<IntersectionTriplet> arr = intr.getTriplets(fromTriplet.getRatio());
          if (arr != null) {
            triplets += arr.size();
          }
        }
        ExecutionReport.setTriplets(triplets);
       
        // intersections are ordered by the angle
        // we start with the smallest angle and continue to the top limit
        for (int tos = 0; tos < toIntersections.size(); tos++) {
            ExecutionReport.intersectionTested();
           
          //monitor.setTaskName("Checking " + (tos + 1) + ". intersection");       
            if (monitor.isCanceled()) {
              return subShapes;
            }
           
          // initial validation
            to = toIntersections.get(tos);

            Debugger.getInstance().addMessage("=================================");
            Debugger.getInstance().addMessage("Intersection: " + to.getIntersection());
           
//            // we stop if we've reached bigger angle
//            if (to.getAngle() > from.getAngle()) {
//                break;
//            }
//
//            // we continue to search for the exact angle and ratio
//            if (to.getAngle() < from.getAngle()) {
//                continue;
//            }

            // now we have an intersection with the good angle
            // we will search for all points on carriers that have the same ratio as the
            // initial intersection triplet
            // intersection is defined by point and two carriers
            intersectionPairs = to.getTriplets(fromTriplet.getRatio());
                    
           
            // there exist no triplets on carriers with given ratio
            if (intersectionPairs == null)
                continue;

            // iterate for all found pairs
            for (int pair = 0; pair < intersectionPairs.size(); pair++) {
              ExecutionReport.tripletTested();
             
              //monitor.subTask("Checking intersection triplets");
              if (monitor.isCanceled()) {
                  return subShapes;
                }
             
                // get current pair
                currentPair = intersectionPairs.get(pair);                           
               
                Debugger.getInstance().addMessage("Pair: " + currentPair);             
                Debugger.getInstance().addMessage("TESTING: " + to.getIntersection().toString() + currentPair.toString());
               
                // we test this 2 times (once when we flip pointA and pointB (symmetry))
                // TODO: Test ratio .. if by flip does not change continue
                for (int j = 0; j < 1; j++) {
//                  if (monitor.isCanceled()) {
//                      return subShapes;
//                    }
                 
                  // this counter is to see how much transformations were tested


                    b.set(0, 0, to.getIntersection().getX());
                    b.set(1, 0, to.getIntersection().getY());
                    b.set(2, 0, j == 0 ? currentPair.getPointA().getX() : currentPair.getPointB().getX());
                    b.set(3, 0, j == 0 ? currentPair.getPointA().getY() : currentPair.getPointB().getY());
                    b.set(4, 0, j == 0 ? currentPair.getPointB().getX() : currentPair.getPointA().getX());
                    b.set(5, 0, j == 0 ? currentPair.getPointB().getY() : currentPair.getPointA().getY());

                    // create transformation by solving equation of 6 unknowns
                    try {
                        solution = A.solve(b);
                    }
                    catch (Exception ex) {
                      Debugger.getInstance().addMessage("Solution exception");
                        continue;
                    }

                    // check if it's symmetry
                    // first check determinant .. must be -1
                    subsolution.set(0, 0, solution.get(0, 0));
                    subsolution.set(0, 1, solution.get(1, 0));
                    subsolution.set(1, 0, solution.get(3, 0));
                    subsolution.set(1, 1, solution.get(4, 0));

                    // Symmetry: MathUtils.round(subsolution.det()) == -1)
                    // Inverse: MathUtils.isIdentity(subsolution.times(subsolution.transpose()))
                    if (MathUtils.round(subsolution.det()) == 0)
                        continue;

                    // we round transformations to 3 decimal places
                    outTransform.setTransform(
                        solution.get(0, 0),
                            solution.get(3, 0),
                            solution.get(1, 0),
                            solution.get(4, 0),
                            solution.get(2, 0),
                            solution.get(5, 0)
//                            MathUtils.round(solution.get(0, 0), 6),
//                            MathUtils.round(solution.get(3, 0), 6),
//                            MathUtils.round(solution.get(1, 0), 6),
//                            MathUtils.round(solution.get(4, 0), 6),
//                            MathUtils.round(solution.get(2, 0), 6),
//                            MathUtils.round(solution.get(5, 0), 6)
                    );
                   
                    //Debugger.getInstance().addMessage(outTransform.toString());

                    // TODO : Think how can i know which other intersection points are paired
                    // that means .. how to pair info about information point of:
                    // from.pointA with to.PointA and get index in original intersection collection

                    // We can decide if to use to use not markers                 
                    if (useMarkers) {
                      //monitor.subTask("Checking marker images");
                        markerFound = true;

                        if (subShape.getMarkers().size() > 0) {
                            markerFound = false;
                            for (MarkerModel subMarker : subShape.getMarkers()) {
                                // first transform this marker
                              MarkerModel transformedMarker = new MarkerModel(subMarker.getLocation());
                              transformedMarker.transform(outTransform);

                              Debugger.getInstance().addMessage("M:" + transformedMarker.getLocation());
                             
                                // now try to find this marker
                                for (MarkerModel marker : shape.getMarkers()) {
                                    if (marker.compareTo(transformedMarker) == 0) {
                                        markerFound = true;
                                    }
                                }
                            }
                        }

                        if (!markerFound) {
                          Debugger.getInstance().addMessage("Marker not found");
                            break;
                        }
                    }

                    // Test remaining points
                    pairTester.reset();
                    pairTester.setPair(0, tos);

                    Point2D testPoint;
                    int testPointIndex;
                    boolean imageMissing = false;

                    // now start pairing all other intersection points to see if their images exist
                    //monitor.subTask("Checking point images");
                    while ((testPointIndex = pairTester.getFirstUnpaired()) != -1) {
                        // get image of point according to tranformation
                        testPoint = fromIntersections.get(testPointIndex).getIntersection();

                        // transform point and try to set pair
                        transformedPoint.setLocation(testPoint.getX(), testPoint.getY());
                        outTransform.transform(transformedPoint, transformedPoint);

                        if (!pairTester.setPair(testPointIndex, transformedPoint.getX(), transformedPoint.getY())) {
                          Debugger.getInstance().addMessage("Image not found");
                          imageMissing = true;
                            break;
                        }
                    }

                    if (imageMissing || !pairTester.isPaired())  {
                      Debugger.getInstance().addMessage("Continuing");
                      continue;
                    }

                    // now check this transform
                    //monitor.subTask("Checking line images");
                    ShapeModel testShape = checkTransformation(shape, subShape, new AffineTransform(outTransform));

                    // check if this shape can be returned and return this shape
                    //monitor.subTask("Checking duplicate subshape");
                   
                    if (testShape == null) {
                      Debugger.getInstance().addMessage("Boundary not found: " + testShape);
                    }
                   
                    if (testShape != null) {
                        // check if we want to exclude this transformation
                        if (excludeShapeList != null) {
                            exclusionFound = false;
                            for (ShapeModel excludedShape : excludeShapeList) {
                                if (ShapeTools.compareTransformations(excludedShape.getInitialTransform(), testShape.getInitialTransform())) {
                                    exclusionFound = true;
                                    break;
                                }
                            }
                            if (exclusionFound) {
                              ExecutionReport.shapeDuplicated();
                              Debugger.getInstance().addMessage("Already found: " + testShape);
                                continue;
                            }
                        }

                        Debugger.getInstance().addMessage("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        lastFound = testShape;
                       
                        // returns all shapes
                        if (randomization == 0) {
                          //monitor.subTask("Adding sub-shape");
                          subShapes.add(testShape);
                          Debugger.getInstance().addMessage("Adding: " + testShape);
                            ExecutionReport.shapeFound();
                        } else if (randomization == 1 || (new Random()).nextInt(1000) % randomization == 0) {
                          //monitor.subTask("Adding sub-shape");
                            subShapes.add(testShape);
                            Debugger.getInstance().addMessage("Adding: " + testShape);
                            ExecutionReport.shapeFound();
                            //return subShapes;
                        } else {
                          Debugger.getInstance().addMessage("Skipping");
                          ExecutionReport.skipShape();
                          //monitor.subTask("Skipping sub-shape");
                          //subShapes.clear();
                        }
                       
                        if (subShapes.size() >= maximumSubshapes) {
                          return subShapes;
                        }
                    }
                }
            }
           
            //monitor.subTask("Starting new sub-shape");
            //monitor.worked(tos);
        }     
       
        if (lastFound != null) {
          //subShapes.add(lastFound);
          return subShapes;
        }
        return null;
    }

    static LineDefinition carrier;
    static ArrayList<LineModel> originalCarrierLines;
    static ArrayList<LineModel> imageCarrierLines;

    static LineModel imageLine;
    static CarrierModel imageCarrier;

    private static ShapeModel getShapeInstance(ShapeModel subShape) {
        // init help test shape
      ShapeModel shape = new ShapeModel((ShapeGrammarModel) subShape.getParent());
      shape.setParent(subShape.getParent());
      shape.setId(subShape.getId());
      shape.setName(subShape.getName() + "_subshape");
     
      return shape;
    }
   
    private static ShapeModel checkTransformation(ShapeModel shape, ShapeModel subShape, AffineTransform transformation) {
        // 2. check transformation of carriers

        boolean boundaryFound = false;
        // we'll scan transformation by transformation and we'll try to find
        // transformed carrier and later if transformed line is within carrier

        // init searching subshape
        ShapeModel foundSubShape = getShapeInstance(subShape);
       
        // test all carriers from left shape
//            System.out.println(pairs.get(i).toString());
        for (CarrierModel originalCarrierDefinition : subShape.getCarriers()) {

            // transform carrier
            carrier = originalCarrierDefinition.getDefinition().transform(transformation);
            // try to find carrier in right shape
            imageCarrier = shape.findCarrier(carrier);

            // test if carrier exists
            if (imageCarrier == null) {
//                    System.out.println("CARRIER DOES NOT EXISTS");
                return null;
            }

            // 3. find if end points of current lines are within maximal lines of the image

            // retreive all lines of current carrier
            imageCarrierLines = imageCarrier.getLines();
            originalCarrierLines = originalCarrierDefinition.getLines();

            // scan all lines and find boundaries
            for (LineModel line : originalCarrierLines) {
                imageLine = line.transformTo(transformation);

                boundaryFound = false;
                for (LineModel image : imageCarrierLines) {
                    // TEST Ys
                    if (image.contains(
                            MathUtils.round(imageLine.getP1().getX()),
                            MathUtils.round(imageLine.getP1().getY()),
                            MathUtils.round(imageLine.getP2().getX()),
                            MathUtils.round(imageLine.getP2().getY()))) {
                        boundaryFound = true;

                        // add this line to resulting shape and recreate shape
                        imageLine.setParent(image);

                        // add line to subshape
                        foundSubShape.getChildrenArray().add(imageLine);
                        break;
                    }

                }
                if (!boundaryFound) break;
            }

            if (!boundaryFound) {
//                    System.out.println("BOUNDARY DOES NOT EXISTS");
                return null;
            }
//                System.out.println("Carrier OK");
        }

        foundSubShape.setInitialTransform(transformation);
        return foundSubShape.clone(true);
    }
   
   

//    // TODO: Study how to flip refernces instead
//
//    public static boolean orderLines(LineModel expectedLeft, LineModel expectedRight) {
//        if (expectedLeft.getP1().getX() > expectedRight.getP1().getX()) {
//            return false;
//        } else if (expectedLeft.getP1().getX() == expectedRight.getP1().getX()) {
//            if (expectedLeft.getP1().getY() > expectedRight.getP1().getY()) {
//                return false;
//            }
//        }
//        return true;
//    }

    public static boolean compareTransformations(AffineTransform trans1, AffineTransform trans2) {
        return trans1.getScaleX() == trans2.getScaleX() &&
               trans1.getScaleY() == trans2.getScaleY() &&
               trans1.getShearX() == trans2.getShearX() &&
               trans1.getShearY() == trans2.getShearY() &&
               trans1.getTranslateX() == trans2.getTranslateX() &&
               trans1.getTranslateY() == trans2.getTranslateY();

    }
   
    public static void orderPoints(Point2D expectedLeft, Point2D expectedRight) {
      if (MathUtils.compare(expectedLeft, expectedRight) == 1) {
            flipPoints(expectedLeft, expectedRight);
        }
    }
   
    public static void flipPoints(Point2D pt1, Point2D pt2) {
      double x = pt2.getX();
      double y = pt2.getY();
      pt2.setLocation(pt1.getX(), pt1.getY());
        pt1.setLocation(x, y);
    }

    public static boolean orderPoints(double x1, double y1, double x2, double y2) {
        if (x1 > x2) {
            return false;
        } else if (x1 == x2) {
            if (y1 > y2) {
                return false;
            }
        }
        return true;
    }

    public static void createRectangle(Rectangle2D rectangle, int x1, int y1, int x2, int y2) {
        if (x1 < x2) {
            if (y1 < y2) {
                rectangle.setFrame(x1, y1, x2 - x1, y2 - y1);
            } else {
                rectangle.setFrame(x1, y2, x2 - x1, y1 - y2);
            }
        } else {
            if (y1 < y2) {
                rectangle.setFrame(x2, y1, x1 - x2, y2 - y1);
            } else {
                rectangle.setFrame(x2, y2, x1 - x2, y1 - y2);
            }
        }
    }

}
TOP

Related Classes of es.iiia.shapegrammar.utils.ShapeTools

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.