Package simtools.diagram.gate

Source Code of simtools.diagram.gate.RightAnglePath$Segment

/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 1999-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Claude Cazenave
*      Nicolas Brodu
*
*
* $Id: RightAnglePath.java,v 1.2 2009/01/19 16:39:24 ogor Exp $
*
* Changes
* -------
* 08-Sep-2008 : Initial public release (RO);
*
*/
package simtools.diagram.gate;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


/**
* A RightAnglePath manages right-angle paths. All segments are either vertical or horizontal
* @author zxpletran007
*
*/
public class RightAnglePath extends Path {

    private static final long serialVersionUID = -4559945676352181808L;

    /**
     * The list of right angle segments
     */
    protected List segments;

    /**
     * The first node position
     */
    protected Point firstPoint;


    /**
     * Create a right angle path from 2 points
     * @param firstEnd
     * @param lastEnd
     */
    public RightAnglePath(Point firstEnd, Point lastEnd){
        super();

        segments = new ArrayList();

        // Create first segments
        createFirstSegments(firstEnd, lastEnd);

        // Path simplification
        updatePath();
    }

    /**
     * Return the number of segments
     * @return
     */
    public int getSegmentNumber(){
        return segments.size();
    }

    /**
     * Return the segment at given index
     * @param segmentIndex
     * @return
     */
    public Segment getSegment(int segmentIndex){
        return (Segment)segments.get(segmentIndex);
    }


    /**
     * Initialize the list of segments with 2 segments created from 2 points.
     */
    private void createFirstSegments(Point firstEnd, Point lastEnd) {

        // Clear the list of segments
        segments.clear();

        firstPoint = firstEnd;

        // Create 2 segments
        boolean horizontalFirst = Math.abs(firstEnd.x-lastEnd.x) > Math.abs(firstEnd.y-lastEnd.y);
        if (horizontalFirst){
            segments.add(new HorizontalSegment(lastEnd.x - firstEnd.x));
            segments.add(new VerticalSegment(lastEnd.y - firstEnd.y));

        } else {
            segments.add(new VerticalSegment(lastEnd.y - firstEnd.y));
            segments.add(new HorizontalSegment(lastEnd.x - firstEnd.x));  
        }
    }



    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#translateNode(int, int, int)
     */
    public int translateNode(int nodeIndex, int dx, int dy) {
       
       
        if (segments.size()==1){   
            Segment s = (Segment)segments.get(0);

            Point secondPoint = new Point(firstPoint);
            if (s instanceof HorizontalSegment){
                secondPoint.x += s.length;
            } else {
                secondPoint.y += s.length;
            }
            if (nodeIndex==0){
                firstPoint.x += dx;
                firstPoint.y += dy;

            } else {
                secondPoint.x += dx;
                secondPoint.y += dy;
            }

            createFirstSegments(firstPoint, secondPoint);

            if (nodeIndex == 1){
                nodeIndex = 2;
            }

        } else {

            Segment ls = nodeIndex!=0? (Segment)segments.get(nodeIndex-1) : null;
            Segment ns = (nodeIndex!=segments.size())(Segment)segments.get(nodeIndex) : null;

            boolean canSlitSegments = nodeIndex!= 0 && nodeIndex!= getNodeNumber()-1;
           
            if (ls != null){     // Translate the segment before
                if (ls instanceof HorizontalSegment){
                    nodeIndex = translateSegment(nodeIndex-1, dy, canSlitSegments) + 1;
                } else {
                    nodeIndex = translateSegment(nodeIndex-1, dx, canSlitSegments) + 1;
                }

            } else { // translate the first point
                if (ns instanceof HorizontalSegment){
                    firstPoint.x += dx;
                    ns.length -= dx;
                } else {
                    firstPoint.y += dy;
                    ns.length -= dy;
                }
            }

            if (ns != null){     // Translate the segment after
                if (ns instanceof HorizontalSegment){
                    translateSegment(nodeIndex, dy, canSlitSegments);
                } else {
                    translateSegment(nodeIndex, dx, canSlitSegments);
                }

            } else { // the last point
                if (ls instanceof HorizontalSegment){
                    ls.length += dx;
                } else {
                    ls.length += dy;
                }
            }
        }

        return nodeIndex;
    }

    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#translateSegment(int, int, boolean)
     */
    protected int translateSegment(int segmentIndex, int dl, boolean canSlitSegment) {
        Segment s = (Segment)segments.get(segmentIndex);
        boolean isHorizontal = s instanceof HorizontalSegment;
        int segmentLength = s.length;
       
        Segment ls = segmentIndex!=0? (Segment)segments.get(segmentIndex-1) : null;
        Segment ns = (segmentIndex!=segments.size()-1)(Segment)segments.get(segmentIndex+1) : null;

        boolean splitFirstEnd = canSlitSegment && segmentIndex == 0 && firstNodeIsLocked;
        boolean splitLastEnd = canSlitSegment && segmentIndex == segments.size()-1 && lastNodeIsLocked;
       
        if (splitFirstEnd){
            if (isHorizontal) {
                segments.add(0,new HorizontalSegment(segmentLength/3));
                segments.add(1,new VerticalSegment(dl));
                s.length -= segmentLength/3;
            } else {
                segments.add(0,new VerticalSegment(segmentLength/3));
                segments.add(1,new HorizontalSegment(dl));
                s.length -= segmentLength/3;
            }

            segmentIndex += 2;
           
        } else {
            if (ls != null){
                ls.length  += dl;  // previous segment

            } else {
                if (s instanceof HorizontalSegment){   // translate first point
                    firstPoint.y += dl;
                } else {
                    firstPoint.x += dl;
                }
            }
        }
       
        if (splitLastEnd){
            if (isHorizontal) {
                segments.add(new VerticalSegment(-dl));
                segments.add(new HorizontalSegment(segmentLength/3));

                s.length -= segmentLength/3;
            } else {
                segments.add(new HorizontalSegment(-dl));
                segments.add(new VerticalSegment(segmentLength/3));

                s.length -= segmentLength/3;
            }
           
        } else {
            if (ns != null){
                ns.length  -= dl;  // next segment
            }
        }
       
        return segmentIndex;
    }

    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#translateEnd()
     */
    public void  updatePath(){
        while( (removeNearNodes() || merveAlignedSegments() )){  
        }
    }

    /**
     * Simplifies the list of nodes, performing following operations:
     * <ul>
     <li>Take off point at same position than the previous one
     * </ul>
     * @return true if the node list has changed
     */
    private boolean removeNearNodes(){
        List segmentToDelete = new ArrayList();

        int segmentNumber = getSegmentNumber();
        if (segmentNumber > 1){
            for (int i=0; i< segmentNumber; i++){
                Segment s1 = (Segment)segments.get(i);
                if ( Math.abs(s1.length) <= MAX_DISTANCE_FOR_MERGING){ 

                    // Re-adjust the node after S1
                    if (i+2 < segmentNumber){
                        ((Segment)segments.get(i+2)).length += s1.length;
                    }

                    // Delete S
                    segmentToDelete.add(s1);
                }
            }
            for (int i=segmentToDelete.size()-1; i>=0; i--){
                if (segments.size()>1){ // We keep at least one segment
                    segments.remove( segmentToDelete.get(i));
               
            }
        }
        return !segmentToDelete.isEmpty();
    }


    /**
     * Simplifies the list of nodes, performing following operations:
     * <ul>
     <li>Merge consecutive segments with same direction
     * </ul>
     * @return true if the node list has changed
     */
    private boolean merveAlignedSegments(){
        List segmentToDelete = new ArrayList();

        int segmentNumber = getSegmentNumber();
        if (segmentNumber > 1){
            for (int i=0; i< segmentNumber-1; i++){
                Segment s1 = (Segment)segments.get(i);
                Segment s2 = (Segment)segments.get(i+1);

                if ( ((s1 instanceof HorizontalSegment && s2 instanceof HorizontalSegment)
                        || (s1 instanceof VerticalSegment && s2 instanceof VerticalSegment))){ 
                    //
                    s1.length += s2.length;
                    // Delete S2
                    segmentToDelete.add(s2);
                    i++; // skip s2
                }
            }
            for (int i=0; i< segmentToDelete.size(); i++){
                segments.remove( segmentToDelete.get(i));
            }
        }
        return !segmentToDelete.isEmpty();
    }


    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#getNode(int)
     */
    public Point getNode(int index) {
        Point res = new Point(firstPoint);

        for(int i=0; i<index;i++){
            Segment s = getSegment(i);
            if( s instanceof HorizontalSegment){
                res.x += s.length;
               
            }else {
                res.y += s.length;
            }
        }
        return res;
    }

    public int getNodeNumber() {
        return segments.size() + 1 ;
    }

    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#translatePath(int, int)
     */
    public void translatePath(int dx, int dy) {
        firstPoint.x += dx;
        firstPoint.y += dy;
    }

    protected static abstract class Segment implements Cloneable, Serializable{

        private static final long serialVersionUID = -7123666248196877431L;
        int length;

        public Segment(int length){
            this.length = length;
        }

        public Segment cloneSegment(){
            Segment clone = null;
            try {
                clone = (Segment)super.clone();
                clone.length = length;

            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }

            return clone;
        }
    }

    protected static class HorizontalSegment extends Segment {

        private static final long serialVersionUID = 6523450410131472274L;

        public HorizontalSegment(int length) {
            super(length);
        }

        public boolean equals(Object o){
            return(o instanceof HorizontalSegment) && ( (HorizontalSegment)o).length==length;
        }

    }

    protected static class VerticalSegment extends Segment{

        private static final long serialVersionUID = 6292061906391248549L;

        public VerticalSegment(int length) {
            super(length);
        }

        public boolean equals(Object o){
            return(o instanceof VerticalSegment) && ( (VerticalSegment)o).length==length;
        }
    }


    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#drawPath(java.awt.Graphics2D)
     */
    public void drawPath(Graphics2D g) {
        Point p1 = new Point(firstPoint);
        Point p2;

        for(int i=0;i< getSegmentNumber();i++){
            Segment s = getSegment(i);
            p2 = new Point(p1);

            if(s instanceof HorizontalSegment){
                p2.x += s.length;
            } else {
                p2.y += s.length;
            }
            g.draw(new Line2D.Double(p1, p2));

            p1 = p2;
        }
    }


    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString(){
        String res ="";

        Point p = new Point(firstPoint);
        res+= "Node 0"  + " : X=" + p.x + " : Y=" + p.y + "\n";

        for(int i=0;i< getSegmentNumber();i++){
            Segment s = getSegment(i);

            if(s instanceof HorizontalSegment){
                p.x += s.length;
            } else {
                p.y += s.length;
            }
            res+= "Node " + (i+1) + " : X=" + p.x + " : Y=" + p.y + "\n";           
        }
        return res;
    }


    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#cloneConnectionPath()
     */
    public Path clonePath(){
        RightAnglePath clone = null;
        try {
            clone = (RightAnglePath)super.clone();
            clone.firstPoint = new Point(firstPoint);

            clone.segments = new ArrayList();
            for(int i=0;i<getSegmentNumber(); i++){
                Segment s = getSegment(i);
                clone.segments.add(s.cloneSegment());  
            }

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return clone;
    }

   
   
  

    /* (non-Javadoc)
     * @see simtools.diagram.gate.ConnectionPath#contains(double, double)
     */
    public boolean contains(double ox, double oy){
        boolean res = false;

        Rectangle2D area;
        Point p = new Point(firstPoint);
        for(int i=0;i< getSegmentNumber() && !res;i++){
            Segment s = getSegment(i);
            if (s instanceof HorizontalSegment){

                area = new Rectangle2D.Double(
                        p.x + (s.length<0? s.length : 0) - MAX_DISTANCE_FROM_SEGMENT,
                        p.y - MAX_DISTANCE_FROM_SEGMENT,
                        Math.abs(s.length) + 2* MAX_DISTANCE_FROM_SEGMENT,
                        2 * MAX_DISTANCE_FROM_SEGMENT
                );

                p.x += s.length;

            } else {
                area = new Rectangle2D.Double(
                        p.x - MAX_DISTANCE_FROM_SEGMENT,
                        p.y + (s.length<0? s.length : 0) - MAX_DISTANCE_FROM_SEGMENT,
                        2 * MAX_DISTANCE_FROM_SEGMENT,
                        Math.abs(s.length) + 2* MAX_DISTANCE_FROM_SEGMENT
                );

                p.y += s.length;
            }
            if (area.contains(ox, oy)){
                res = true;
            }
        }
        return res;
    }
   
    public boolean equals(Object o){
        boolean res = false;

        if (o instanceof RightAnglePath){

            RightAnglePath otherPath = (RightAnglePath)o;
            res = firstPoint.equals(otherPath.firstPoint) && getSegmentNumber()==otherPath.getSegmentNumber();

            for(int i=0;i < getSegmentNumber() && res;i++){
                Segment p1 = getSegment(i);
                Segment p2 = otherPath.getSegment(i);
                res &= p1.equals(p2);
            }
        }
        return res;
    }
}
TOP

Related Classes of simtools.diagram.gate.RightAnglePath$Segment

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.