Package es.iiia.shapegrammar.shape

Source Code of es.iiia.shapegrammar.shape.ShapeModel

package es.iiia.shapegrammar.shape;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import es.iiia.shapegrammar.model.GeometryModel;
import es.iiia.shapegrammar.model.NodeModel;
import es.iiia.shapegrammar.model.ShapeGrammarModel;
import es.iiia.shapegrammar.shape.guides.LineDefinition;
import es.iiia.shapegrammar.utils.ShapeTools;
import es.iiia.shapegrammar.utils.XmlUtils;


public class ShapeModel extends GeometryModel implements Cloneable  {
  private int id;
    private String description;
    
    private Rectangle2D bounds;
    private ArrayList<Point2D> points;
    private ArrayList<LineModel> lines;
    private ArrayList<LineModel> maximalLines;
    private ArrayList<MarkerModel> markers;
    private ArrayList<CarrierModel> carriers;
    private ArrayList<IntersectionModel> intersections;
    private ArrayList<CurveModel> curves;

    private AffineTransform initialTransform;
  

    // [start] Constructors
    public ShapeModel() {
      super();
    }
   
    public ShapeModel(ShapeGrammarModel parent) {
      super();
     
      this.setParent(parent);
        this.description = "";
    }

    public ShapeModel(ShapeGrammarModel grammar, Element configuration) {
      // init parts
        this.setParent(grammar);
       
        // set id
    this.id = Integer.parseInt(configuration.getAttribute("id"));
    // update ticket
    grammar.updateTicket(this.id);
   
        super.setName(XmlUtils.getTextValue(configuration, "name"));
        this.description = XmlUtils.getTextValue(configuration, "description");

        // init startShape
        if (configuration.getAttribute("main").equals("true")) {
            this.getGrammar().setStartShape(this);
        }

        // select all shapes within this shape
        NodeList content = configuration.getElementsByTagName("content").item(0).getChildNodes();

        // browse through elements and create shapes
        String name;
        for (int i = 0; i < content.getLength(); i++) {
            name = content.item(i).getNodeName();
            if (name.equals("polyLine")) {
                this.addChild(new LineModel((Element) content.item(i)));
            } else if (name.equals("lineGroup")) {
                LineGroupModel lineGroup = new LineGroupModel((Element) content.item(i));
                this.addChild(lineGroup);             
            } else if (name.equals("marker")) {
                MarkerModel marker = new MarkerModel((Element) content.item(i));
                this.addMarker(marker);             
            } else if (name.equals("quadCurve")) {
                CurveModel curve = new CurveModel((Element) content.item(i));
                this.addChild(curve);            
            } else if (name.equals(BezierCurveModel.XmlName)) {
                BezierCurveModel curve = new BezierCurveModel((Element) content.item(i));
                this.addChild(curve);            
            }
        }
       
    }
   
    // [end]

    // [start] Getters / Setters
 
    public ShapeGrammarModel getGrammar() {
      if (this.getRootModel() != null && this.getRootModel() instanceof ShapeGrammarModel) {
        return (ShapeGrammarModel) this.getRootModel();
      }
      return null;
    }
   
  public AffineTransform getInitialTransform() {
        return initialTransform;
    }

    public void setInitialTransform(AffineTransform initialTransform) {
        this.initialTransform = initialTransform;
    }  
   
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
   
//    public Rectangle2D getBounds() {
//        if (this.bounds == null) {
//            //this.bounds = new PrecisionRectangle();
//
//            if (this.getChildrenArray().size() > 0) {
//              this.bounds = (Rectangle) ((GeometryModel)this.getChildrenArray().get(0)).getBounds().clone();
//            }
//
//            for (NodeModel geom : this.getChildrenArray()) {
//              this.bounds.add(((GeometryModel) geom).getBounds());                    
//            }
//        }
//        return this.bounds;
//    }
   
    public ArrayList<Point2D> getPoints() {
        if (this.points == null || this.points.size() == 0) {
            this.points = new ArrayList<Point2D>();
           
            for (NodeModel model : this.getChildrenArray()) {
          if (model instanceof LineModel) {
            LineModel line = (LineModel) model;
          for (int i=0; i<line.getPoints().size(); i++) {
            this.points.add((Point2D) line.getPoints().get(i).clone());
          }
           
          }
        }
        }
        return points;
    }
   
    public void setPoints(ArrayList<Point2D> points) {
    // TODO: Optimize
    this.points.clear();
    for (int i = 0; i < points.size(); i++) {
      this.points.add((Point2D) points.get(i).clone());
    }
  }
   
    public ArrayList<MarkerModel> getMarkers() {
      if (this.markers == null) {
        this.markers = new ArrayList<MarkerModel>();
        for (NodeModel model : this.getChildrenArray()) {
            if (model instanceof MarkerModel) {
              markers.add((MarkerModel) model);
            }
          }
          return markers;
      }
      return this.markers;  
    }
   
    private ArrayList<CurveModel> getCurves() {
      if (this.curves == null) {
        this.curves = new ArrayList<CurveModel>();
        for (NodeModel model : this.getChildrenArray()) {
          if (model instanceof CurveModel) {
            curves.add((CurveModel) model);
          }
        }
      }
      return curves;
    }
   
    public ArrayList<LineModel> getLines() {
      if (this.lines == null) {
        this.lines = new ArrayList<LineModel>();
       
        for (NodeModel model : this.getChildrenArray()) {
          if (model instanceof LineModel) {
            for (LineModel line : ((LineModel) model).getLines()) {
              //System.out.println(line);
              this.lines.add((LineModel) line.clone());
            }
          } else if (model instanceof LineGroupModel) {
            for (NodeModel subline : model.getChildrenArray()) {
                if (subline instanceof LineModel) {
                  for (LineModel line : ((LineModel) subline).getLines()) {
                    this.lines.add((LineModel) line.clone());
                  }
                }
            }
          }
        }
      }
      return this.lines;
    }
   
    // [end]
   
    // [start] Structure Modifiers
 
  public boolean addChild(GeometryModel child) {
    boolean b = this.getChildrenArray().add(child);
    if (b) {
      child.setParent(this);
      this.reset();
     
      getListeners().firePropertyChange(PROPERTY_ADD, null, child);
    }   
    return b;
  }
 
  // markers are stored in separate collection
  public boolean addMarker(MarkerModel child) {
    boolean b = this.addChild(child);
    if (b) {
      child.setParent(this);
      this.getMarkers().add(child);     
    }
    return b;
  }

  public boolean removeChild(GeometryModel child) {
    boolean b = this.getChildrenArray().remove(child);
    if (b)
      this.reset();
      getListeners().firePropertyChange(PROPERTY_REMOVE, child, null);
    return b;
  }
 
  protected ShapeModel createInstance() {
      return new ShapeModel(this.getGrammar());
    }
 
  public ShapeModel clone() {
      return this.clone(false);
    }
   
    public ShapeModel clone(boolean forceParent) {
      ShapeModel model = this.createInstance();
      model.setId(this.getId());
      model.setName(this.getName() + "_clone");
      model.setDescription(this.getDescription());
     
      // clone all subparts
      for (NodeModel part : this.getChildrenArray()) {
        GeometryModel copy = ((GeometryModel) part).clone();
        model.addChild(copy);
       
        // this is option to override the parent to be the original one from the copy
        // otherwise the parent is set to be the "model"
        // this is used when cloning subshape and lines keep parents their maximal lines
        if (forceParent) {
          copy.setParent(part.getParent());
        }
        }
     
      // clone initial transform
      if (this.initialTransform != null) {
        model.setInitialTransform(new AffineTransform(this.initialTransform));
        }          
        return model;
    }
 
  public void merge(ShapeModel shape) {
      this.merge(shape, true);
    }
   
    public void merge(ShapeModel shape, boolean addMarkers) {
        // add geometry
        for (NodeModel model : shape.clone().getChildrenArray()) {
            if (!addMarkers && model instanceof MarkerModel) {
              continue;
            }
            this.addChild(model);
        }
        this.reset();
    }  
 
  // [end]
 
  // [start] Layout Modifiers

    public void moveToCenter() {
        // move to center
        int centerX = (int) this.getBounds().getCenterX();
        int centerY = (int) this.getBounds().getCenterY();
       
        this.translate(-centerX, -centerY);
    }

    public void translate(double x, double y) {
      for (NodeModel part : this.getChildrenArray()) {
        part.translate(x, y);
        }
      this.reset();
    }

    public void rotate(double theta, Point2D rotationCenter) {
      for (NodeModel part : this.getChildrenArray()) {
            part.rotate(rotationCenter, theta);
        }
      this.reset();
    }

    public void scale(double x, double y) {
      for (NodeModel part : this.getChildrenArray()) {
            part.scale(x, y);
       
      this.reset();
    }

    public void transform(AffineTransform transform) {
      for (NodeModel part : this.getChildrenArray()) {
            part.transform(transform);
        }
      this.reset();
    }
   
    // [end]
   
    // [start] Subshape Detection Methods

   
    public void maximize() {  
      // Get the list of curves
      ArrayList<CurveModel> curves = this.getCurves();
     
      // Get List of maximal lines
      ArrayList<LineModel> maximals = this.getMaximalLines();
     
      // Get Markers
      ArrayList<MarkerModel> markers = this.getMarkers();
     
      // Clean everything
      this.getChildrenArray().clear();
     
      // Add curves
      for (CurveModel curve : curves) {
            this.getChildrenArray().add(curve);
        }      
       
        // Add markers  
        for (MarkerModel marker : markers) {
            this.getChildrenArray().add(marker);
        }
       
        // Add maximal lines  
        for (LineModel maximalLine : maximals) {
            this.getChildrenArray().add(maximalLine);
        }
       
        // We reinitialize the list of maximal lines
      this.lines = null;
      this.points = null;
    }
  

   

    // properties

   
   
    public ArrayList<IntersectionModel> getIntersections() {
      return getIntersections(0, true);
    }
   
    public ArrayList<IntersectionModel> getIntersections(double angle) {
      return getIntersections(angle, true);
    }

    public ArrayList<IntersectionModel> getIntersections(double angle, boolean includeOuter) {
        if (this.intersections == null || this.intersections.size() == 0) {
            this.intersections = new ArrayList<IntersectionModel>();

            IntersectionModel intersection;
            boolean exists;

            IntersectionModel.naming = 0;

            for (int i = 0; i < this.getCarriers().size(); i++) {
                for (int j = 0; j < this.getCarriers().size(); j++) {
                    if (i <= j) continue;

                    intersection = new IntersectionModel(this.getCarriers().get(i), this.getCarriers().get(j), includeOuter);

//                    // test if intersection point has been added
//                    // TODO: Maybe some other way ?
//                    exists = false;
//                    for (IntersectionModel intersect : this.intersections) {
//                        if (intersect.getIntersection().getX() == intersection.getIntersection().getX() &&
//                            intersect.getIntersection().getY() == intersection.getIntersection().getY()) {
//                            exists = true;
//                        }
//                    }
                    if (intersection.getIntersection() != null &&
                      (angle == 0 || intersection.getAngle() == angle)) {
//                    if (!exists) {
                        intersections.add(intersection);
//                    }
                    }
                }
            }

            // sort intersections by raising angle
            Collections.sort(this.intersections);
        }
        return this.intersections;
    }

    public ArrayList<CarrierModel> getCarriers() {
        if (this.carriers == null) {
            // init carriers
            this.carriers = new ArrayList<CarrierModel>();
            CarrierModel found;

//            System.out.println("STARTING SEARCH FOR CARRIERS");
            for (LineModel line : this.getMaximalLines()) {
                // search if we've already found this carrier
                found = this.findCarrier(line.getDefinition());

                if (found != null) {
                    found.addLine(line);
//                    System.out.println("EXISTING CARRIER FOR " + line.getDefinition().toString());
                } else {
                    this.carriers.add(new CarrierModel(line));
//                    System.out.println("NEW CARRIER: " + line.getDefinition().toString());
                }
            }
//            System.out.println("END SEARCH CARRIERS: " + this.carriers.size());
        }
        return this.carriers;
    }

    public CarrierModel findCarrier(LineDefinition definition) {
        // TODO: Maybe binary search ?
        for (CarrierModel car : this.carriers) {
            if (car.getDefinition().equals(definition)) {
                return car;
            }
        }
        return null;
    }

    private ArrayList<LineModel> getMaximalLines() {
        if (this.maximalLines == null || this.maximalLines.size() == 0) {
            this.maximalLines = this.cloneLines();
            try {
                ShapeTools.createMaximalLines(this.maximalLines);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return this.maximalLines;
    }  
   
//    public String toString() {
//      return this.getName();
////        StringBuffer bf = new StringBuffer();
////        bf.append(this.getName() + ": ");
////        for (LineModel line : this.getLines()) {
////            bf.append(line.toString() + "->");
////        }
////        return bf.toString() + "\r\n";
//    }
   
    // private methods
   
    private ArrayList<LineModel> cloneLines() {
      ArrayList<LineModel> target = new ArrayList<LineModel>();
     
      for (LineModel model : this.getLines()) {
        target.add(model.clone());
      }
     
      return target;
    }
   
     
   
    public void reset() {
      this.bounds = null;
      this.points = null;
        this.lines = null;
        this.maximalLines = null;
        this.carriers = null;
        this.intersections = null;
        this.markers = null;
        this.curves = null;
    }
   
    // [start] Overridden Methods
 
  @Override
  public String toString() {
    StringBuffer bf = new StringBuffer();
   
    for (LineModel line : this.getLines()) {
      bf.append(line.toString());
      bf.append(",");
    }
    return bf.toString();
  }
 
  public int compareTo(Object o) {
        if (this.id < ((ShapeModel) o).id)
            return -1;
        else if (this.id > ((ShapeModel) o).id)
            return 1;
        return 0;
    }
 
  public boolean isEqualTo(ShapeModel shape) {
    // we do this by comparing the lines
    ArrayList<LineModel> myLines = (ArrayList<LineModel>) this.getLines().clone();
    ArrayList<LineModel> hisLines = (ArrayList<LineModel>) shape.getLines().clone();
   
    // do initial check
    if (myLines.size() != hisLines.size()) {
      return false;
    }
   
    // now compare lines
    boolean found;
    LineModel myLine, hisLine;
    for (int i=myLines.size()-1; i>=0; i--) {
      found = false;
      myLine = myLines.get(i);
     
      for (int j=hisLines.size()-1; j>=0; j--) {
        hisLine = hisLines.get(j);
        // now search for this line;
        if (myLine.isEqualTo(hisLine)) {
          found = true;
          myLines.remove(myLine);
          hisLines.remove(hisLine);
          break;
        }
      }
      // now check
      if (!found) {
        return false;
      }
     
    }
   
    // we needed to use all of the lines
    if (myLines.size() != 0 || hisLines.size() != 0) {
      return false;
    }
    return true;
  }
 
  // [end]
 
  // [start] Persistence Methods
 
  public Element getXml() {
        Element root = XmlUtils.createXml("shape");
        Document owner = root.getOwnerDocument();

        root.setAttribute("id", Integer.toString(this.getId()));

        // check if it's main element
        if (this.getGrammar() != null && this.getGrammar().getStartShape() == this) {
            root.setAttribute("main", "true");
        }

        Node child = root.appendChild(owner.createElement("name"));
        child.appendChild(owner.createTextNode(this.getName()));
        child = root.appendChild(owner.createElement("description"));
        child.appendChild(owner.createTextNode(this.getDescription()));
        child = root.appendChild(owner.createElement("content"));

        for (NodeModel geom : this.getChildrenArray()) {
            child.appendChild(owner.importNode(((GeometryModel)geom).getXml(), true));
        }
      

        return root;
    }
  // [end]
}
TOP

Related Classes of es.iiia.shapegrammar.shape.ShapeModel

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.