+++ /dev/null
-package fr.orsay.lri.varna.applications.templateEditor;
-
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Shape;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import fr.orsay.lri.varna.exceptions.ExceptionInvalidRNATemplate;
-import fr.orsay.lri.varna.models.rna.RNA;
-import fr.orsay.lri.varna.models.templates.RNATemplate;
-import fr.orsay.lri.varna.models.templates.RNATemplate.EdgeEndPointPosition;
-import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateHelix;
-import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateElement.EdgeEndPoint;
-
-
-public class Helix extends GraphicalTemplateElement{
-
- RNATemplateHelix _h;
-
- public Helix(double x, double y, RNATemplate tmp, List<GraphicalTemplateElement> existingRNAElements)
- {
- this(x,y,getNextAutomaticCaption(existingRNAElements),tmp);
- }
-
- public Helix(double x, double y, String cap, RNATemplate tmp)
- {
- _h = tmp.new RNATemplateHelix(cap);
- _h.setStartPosition(new Point2D.Double(x,y));
- _h.setEndPosition(new Point2D.Double(x,y));
- _h.setLength(1);
- _h.setCaption(cap);
- }
-
- public Helix(RNATemplateHelix templateHelix) {
- _h = templateHelix;
- }
-
-
- private static String getNextAutomaticCaption(List<GraphicalTemplateElement> existingRNAElements) {
- // Find which captions are already used
- Set<String> captions = new HashSet<String>();
- for (GraphicalTemplateElement element: existingRNAElements) {
- if (element instanceof Helix) {
- Helix helix = (Helix) element;
- if (helix.getCaption() != null) {
- captions.add(helix.getCaption());
- }
- }
- }
- // Find a non-conflicting name for this helix
- for (int i=1;;i++) {
- String candidateCaption = "H" + i;
- if (! captions.contains(candidateCaption)) {
- return candidateCaption;
- }
- }
- }
-
- public void toggleFlipped()
- {
- _h.setFlipped(!_h.isFlipped());
- updateAttachedUnpairedRegions();
- }
-
-
- /**
- * When an helix is moved/resized/etc... it is necessary to update
- * the positions of endpoints from unpaired regions that are attached
- * to the helix. This function updates the endpoints positions of
- * attached unpaired regions.
- */
- public void updateAttachedUnpairedRegions() {
- for (RelativePosition rpos: getConnectedEdges()) {
- Couple<RelativePosition,GraphicalTemplateElement> c = getAttachedElement(rpos);
- if (c != null && c.second instanceof UnpairedRegion) {
- UnpairedRegion unpairedRegion = (UnpairedRegion) c.second;
- Point2D.Double pos = getEdgePosition(rpos);
- if (c.first == RelativePosition.RP_CONNECT_START5) {
- unpairedRegion.setEdge5(pos);
- } else if (c.first == RelativePosition.RP_CONNECT_END3) {
- unpairedRegion.setEdge3(pos);
- }
- }
- }
- }
-
- public double getPosX()
- {
- return _h.getStartPosition().x;
- }
-
- public String getCaption()
- {
- return _h.getCaption();
- }
-
- public double getPosY()
- {
- return _h.getStartPosition().y;
- }
-
- public RNATemplateHelix getTemplateElement()
- {
- return _h;
- }
-
- public void setX(double x)
- {
- _h.getStartPosition().x = x;
- }
-
- public void setY(double y)
- {
- _h.getStartPosition().y = y;
- }
-
- public void setPos(Point2D.Double p)
- {
- _h.setStartPosition(p);
- updateLength();
- }
-
- public void setPos(double x, double y)
- {
- setPos(new Point2D.Double(x,y));
- }
-
- public Point2D.Double getPos()
- {
- return _h.getStartPosition();
- }
-
- public void moveCenter(double x, double y)
- {
- Point2D.Double center = new Point2D.Double((_h.getStartPosition().x+_h.getEndPosition().x)/2.0,(_h.getStartPosition().y+_h.getEndPosition().y)/2.0);
- double dx = x-center.x;
- double dy = y-center.y;
- _h.setStartPosition(new Point2D.Double(_h.getStartPosition().x+dx,_h.getStartPosition().y+dy));
- _h.setEndPosition(new Point2D.Double(_h.getEndPosition().x+dx,_h.getEndPosition().y+dy));
- }
-
-
- public void setExtent(double x, double y)
- {
- setExtent(new Point2D.Double(x,y));
- }
-
- private void updateLength()
- {
- _h.setLength(getNbBP());
- }
-
- public void setExtent(Point2D.Double p)
- {
- _h.setEndPosition(p);
- updateLength();
- }
-
- public double getExtentX()
- {
- return _h.getEndPosition().x;
- }
-
- public Point2D.Double getExtent()
- {
- return _h.getEndPosition();
- }
-
- public double getExtentY()
- {
- return _h.getEndPosition().y;
- }
-
- public static final double BASE_PAIR_DISTANCE = RNA.BASE_PAIR_DISTANCE;
- public static final double LOOP_DISTANCE = RNA.LOOP_DISTANCE;
- public static final double SELECTION_RADIUS = 15.0;
-
-
-
-
- public Point2D.Double getAbsStart5()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Point2D.Double start5 = new Point2D.Double((getPosX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()-Helix.BASE_PAIR_DISTANCE*ny/2.0));
- return start5;
- }
-
- public Point2D.Double getAbsStart3()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Point2D.Double start3 = new Point2D.Double((getPosX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()+Helix.BASE_PAIR_DISTANCE*ny/2.0));
- return start3;
- }
-
- public Point2D.Double getAbsEnd5()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Point2D.Double end5 = new Point2D.Double((getExtentX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()-Helix.BASE_PAIR_DISTANCE*ny/2.0));
- return end5;
- }
-
- public Point2D.Double getAbsEnd3()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Point2D.Double end3 = new Point2D.Double((getExtentX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()+Helix.BASE_PAIR_DISTANCE*ny/2.0));
- return end3;
- }
-
- public Point2D.Double getStart5()
- {
- if (_h.isFlipped())
- return getAbsStart3();
- else
- return getAbsStart5();
-
- }
-
- public Point2D.Double getStart3()
- {
- if (_h.isFlipped())
- return getAbsStart5();
- else
- return getAbsStart3();
- }
-
- public Point2D.Double getEnd5()
- {
- if (_h.isFlipped())
- return getAbsEnd3();
- else
- return getAbsEnd5();
- }
-
- public Point2D.Double getEnd3()
- {
- if (_h.isFlipped())
- return getAbsEnd5();
- else
- return getAbsEnd3();
- }
-
- public Polygon getBoundingPolygon()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Point2D.Double start5 = new Point2D.Double((getPosX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()+Helix.BASE_PAIR_DISTANCE*ny/2.0));
- Point2D.Double end5 = new Point2D.Double((getExtentX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()+Helix.BASE_PAIR_DISTANCE*ny/2.0));
- Point2D.Double start3 = new Point2D.Double((getPosX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()-Helix.BASE_PAIR_DISTANCE*ny/2.0));
- Point2D.Double end3 = new Point2D.Double((getExtentX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()-Helix.BASE_PAIR_DISTANCE*ny/2.0));
- Polygon p = new Polygon();
- p.addPoint((int)start5.x, (int)start5.y);
- p.addPoint((int)end5.x, (int)end5.y);
- p.addPoint((int)end3.x, (int)end3.y);
- p.addPoint((int)start3.x, (int)start3.y);
- return p;
- }
-
-
- public Point2D.Double getCenter()
- {
- return new Point2D.Double((int)((_h.getStartPosition().x+_h.getEndPosition().x)/2.0),
- (int)((_h.getStartPosition().y+_h.getEndPosition().y)/2.0));
- }
-
-
- public Point2D.Double getCenterEditStart()
- {
- double dist = _h.getStartPosition().distance(_h.getEndPosition());
- double dx = (_h.getEndPosition().x-_h.getStartPosition().x)/(dist);
- double dy = (_h.getEndPosition().y-_h.getStartPosition().y)/(dist);
- return new Point2D.Double((int)(_h.getStartPosition().x+(dist-10.0)*dx),
- (int)(_h.getStartPosition().y+(dist-10.0)*dy));
- }
-
- public Point2D.Double getCenterEditEnd()
- {
- double dist = _h.getStartPosition().distance(_h.getEndPosition());
- double dx = (_h.getEndPosition().x-_h.getStartPosition().x)/(dist);
- double dy = (_h.getEndPosition().y-_h.getStartPosition().y)/(dist);
- return new Point2D.Double((int)(_h.getStartPosition().x+(10.0)*dx),
- (int)(_h.getStartPosition().y+(10.0)*dy));
- }
-
-
- public Shape getSelectionBox()
- {
- double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
- double nx = dy;
- double ny = -dx;
- Polygon hbox = getBoundingPolygon();
- Polygon p = new Polygon();
- Point2D.Double start5 = new Point2D.Double(hbox.xpoints[0]+SELECTION_RADIUS*(dx+nx),hbox.ypoints[0]+SELECTION_RADIUS*(dy+ny));
- Point2D.Double end5 = new Point2D.Double(hbox.xpoints[1]+SELECTION_RADIUS*(-dx+nx),hbox.ypoints[1]+SELECTION_RADIUS*(-dy+ny));
- Point2D.Double end3 = new Point2D.Double(hbox.xpoints[2]+SELECTION_RADIUS*(-dx-nx),hbox.ypoints[2]+SELECTION_RADIUS*(-dy-ny));;
- Point2D.Double start3 = new Point2D.Double(hbox.xpoints[3]+SELECTION_RADIUS*(dx-nx),hbox.ypoints[3]+SELECTION_RADIUS*(dy-ny));;
- p.addPoint((int)start5.x, (int)start5.y);
- p.addPoint((int)end5.x, (int)end5.y);
- p.addPoint((int)end3.x, (int)end3.y);
- p.addPoint((int)start3.x, (int)start3.y);
- return p;
- }
-
- public Shape getArea()
- {
- return getSelectionBox();
- }
-
-
- public static final double EDIT_RADIUS = 10.0;
- public static final double MOVE_RADIUS = 13.0;
- public static final double BASE_RADIUS = 8.0;
- public static final double EDGE_BASE_RADIUS = 7.0;
-
-
- public RelativePosition getRelativePosition(double x, double y)
- {
- Point2D.Double current = new Point2D.Double(x,y);
- Shape p = getSelectionBox();
- if (p.contains(current))
- {
- if (getCenterEditStart().distance(current)<EDIT_RADIUS)
- {
- return RelativePosition.RP_EDIT_START;
- }
- else if (getCenterEditEnd().distance(current)<EDIT_RADIUS)
- {
- return RelativePosition.RP_EDIT_END;
- }
- else if (getCenter().distance(current)<MOVE_RADIUS)
- {
- return RelativePosition.RP_INNER_MOVE;
- }
- else if (getEnd3().distance(current)<EDGE_BASE_RADIUS)
- {
- return RelativePosition.RP_CONNECT_END3;
- }
- else if (getEnd5().distance(current)<EDGE_BASE_RADIUS)
- {
- return RelativePosition.RP_CONNECT_END5;
- }
- else if (getStart3().distance(current)<EDGE_BASE_RADIUS)
- {
- return RelativePosition.RP_CONNECT_START3;
- }
- else if (getStart5().distance(current)<EDGE_BASE_RADIUS)
- {
- return RelativePosition.RP_CONNECT_START5;
- }
-
- return RelativePosition.RP_INNER_GENERAL;
- }
- else
- return RelativePosition.RP_OUTER;
- }
-
- public RelativePosition getClosestEdge(double x, double y)
- {
- RelativePosition result = RelativePosition.RP_OUTER;
- double dist = Double.MAX_VALUE;
- Point2D.Double current = new Point2D.Double(x,y);
- double dcand = getStart5().distance(current);
- if (dcand<dist)
- {
- dist = dcand;
- result = RelativePosition.RP_CONNECT_START5;
- }
- dcand = getStart3().distance(current);
- if (dcand<dist)
- {
- dist = dcand;
- result = RelativePosition.RP_CONNECT_START3;
- }
- dcand = getEnd5().distance(current);
- if (dcand<dist)
- {
- dist = dcand;
- result = RelativePosition.RP_CONNECT_END5;
- }
- dcand = getEnd3().distance(current);
- if (dcand<dist)
- {
- dist = dcand;
- result = RelativePosition.RP_CONNECT_END3;
- }
- return result;
- }
-
- public Point2D.Double getEdgePosition(Helix.RelativePosition edge)
- {
- switch (edge)
- {
- case RP_CONNECT_END3:
- return getEnd3();
- case RP_CONNECT_END5:
- return getEnd5();
- case RP_CONNECT_START5:
- return getStart5();
- case RP_CONNECT_START3:
- return getStart3();
- case RP_EDIT_START:
- return getPos();
- case RP_EDIT_END:
- return getExtent();
- case RP_INNER_MOVE:
- return getCenter();
- }
- return getCenter();
- }
-
- public RelativePosition getConnectedEdge(RelativePosition edge)
- {
- switch (edge)
- {
- case RP_CONNECT_END3:
- return RelativePosition.RP_CONNECT_START3;
- case RP_CONNECT_END5:
- return RelativePosition.RP_CONNECT_START5;
- case RP_CONNECT_START5:
- return RelativePosition.RP_CONNECT_END5;
- case RP_CONNECT_START3:
- return RelativePosition.RP_CONNECT_END3;
- }
- return RelativePosition.RP_OUTER;
- }
-
- public boolean isAnchored5Start()
- {
- return (_h.getIn1().getOtherElement()!=null);
- }
-
- public boolean isAnchored5End()
- {
- return (_h.getOut1().getOtherElement()!=null);
- }
-
- public boolean isAnchored3Start()
- {
- return (_h.getOut2().getOtherElement()!=null);
- }
-
- public boolean isAnchored3End()
- {
- return (_h.getIn2().getOtherElement()!=null);
- }
-
- public int getNbBP()
- {
- Point2D.Double pos = getPos();
- Point2D.Double extent = getExtent();
- double helLength = pos.distance(extent);
- return Math.max((int)Math.round(helLength/Helix.LOOP_DISTANCE) + 1, 2);
- }
-
- public void draw(Graphics2D g2d,boolean isSelected)
- {
- g2d.setStroke(_solidStroke);
- Point2D.Double pos = getPos();
- Point2D.Double extent = getExtent();
- double dx = (pos.x-extent.x)/pos.distance(extent);
- double dy = (pos.y-extent.y)/pos.distance(extent);
- double nx = Helix.BASE_PAIR_DISTANCE*dy/2.0;
- double ny = -Helix.BASE_PAIR_DISTANCE*dx/2.0;
- Point2D.Double start5 = getStart5();
- Point2D.Double end5 = getEnd5();
- Point2D.Double start3 = getStart3();
- Point2D.Double end3 = getEnd3();
-
- for (RelativePosition e:this.getConnectedEdges())
- {
- g2d.setStroke(_solidStroke);
- g2d.setColor(BACKBONE_COLOR);
- Point2D.Double p1 = this.getEdgePosition(e);
- Point2D.Double p2 = this.getEdgePosition(getConnectedEdge(e));
- if (_mainColors.containsKey(e))
- {
- g2d.setColor(_mainColors.get(e));
- g2d.setStroke(this._boldStroke);
- }
- g2d.drawLine((int)p1.x,(int)p1.y,(int)(p1.x+p2.x)/2,(int)(p1.y+p2.y)/2);
- }
-
- g2d.setColor(NUMBER_COLOR);
- double captionx = (_h.isFlipped()?-1.0:1.0)*1.5*nx+(start3.x+end3.x)/2.0;
- double captiony = (_h.isFlipped()?-1.0:1.0)*1.5*ny+(start3.y+end3.y)/2.0;
- drawStringCentered(g2d, getCaption(),captionx,captiony);
-
- int nbBasePairs = _h.getLength();
-
- g2d.setStroke(_solidStroke);
-
- for (int i=0;i<nbBasePairs;i++)
- {
- g2d.setColor(BASE_PAIR_COLOR);
- Point2D.Double p5 = new Point2D.Double(
- (i*start5.x+(nbBasePairs-1-i)*end5.x)/(nbBasePairs-1),
- (i*start5.y+(nbBasePairs-1-i)*end5.y)/(nbBasePairs-1));
- Point2D.Double p3 = new Point2D.Double(
- (i*start3.x+(nbBasePairs-1-i)*end3.x)/(nbBasePairs-1),
- (i*start3.y+(nbBasePairs-1-i)*end3.y)/(nbBasePairs-1));
- g2d.drawLine((int)p3.x,(int)p3.y,(int)p5.x,(int)p5.y);
- if (i==0)
- {
- if (isAnchored5End())
- { drawMagnet(g2d, p5); }
- else
- { drawAnchor3(g2d, p5); }
-
- if (isAnchored3End())
- { drawMagnet(g2d, p3); }
- else
- { drawAnchor5(g2d, p3); }
- }
- else if (i==nbBasePairs-1)
- {
- if (isAnchored5Start())
- { drawMagnet(g2d, p5); }
- else
- { drawAnchor5(g2d, p5); }
-
- if (isAnchored3Start())
- { drawMagnet(g2d, p3); }
- else
- { drawAnchor3(g2d, p3); }
- }
- else
- {
- drawBase(g2d, p3);
- drawBase(g2d, p5);
- }
- }
-
- if (isSelected)
- {
- nx = dy;
- ny = -dx;
- Shape p = getSelectionBox();
- g2d.setColor(BACKBONE_COLOR);
- g2d.setStroke(_dashedStroke);
- g2d.draw(p);
- Point2D.Double center = getCenter();
- g2d.setStroke(_solidStroke);
- drawMove(g2d,center);
- drawEditStart(g2d,this,-dx,-dy,nx,ny);
- drawEditEnd(g2d,this,-dx,-dy,nx,ny);
- }
- }
-
-
- public void translate(double x, double y) {
- Point2D.Double pos = getPos();
- Point2D.Double extent = getExtent();
- setPos(pos.x+x,pos.y+y);
- setExtent(extent.x+x,extent.y+y);
- }
-
- public RNATemplateHelix getHelix() {
- return _h;
- }
-
-
- public EdgeEndPoint getEndPoint(RelativePosition r) {
- switch(r)
- {
- case RP_CONNECT_START5:
- return _h.getIn1();
- case RP_CONNECT_START3:
- return _h.getOut2();
- case RP_CONNECT_END3:
- return _h.getIn2();
- case RP_CONNECT_END5:
- return _h.getOut1();
- }
- return null;
- }
-
- public boolean isIn(RelativePosition r) {
- switch(r)
- {
- case RP_CONNECT_START5:
- return true;
- case RP_CONNECT_START3:
- return false;
- case RP_CONNECT_END3:
- return true;
- case RP_CONNECT_END5:
- return false;
- }
- return true;
- }
-
-
- public void attach(GraphicalTemplateElement e, RelativePosition edgeOrig, RelativePosition edgeDest) throws ExceptionInvalidRNATemplate
- {
- super.attach(e,edgeOrig,edgeDest);
- EdgeEndPoint e1 = this.getEndPoint(edgeOrig);
- EdgeEndPoint e2 = e.getEndPoint(edgeDest);
- boolean parity1 = this.isIn(edgeOrig);
- boolean parity2 = e.isIn(edgeDest);
- if ((e1!=null)&&(e2!=null)&&(parity1!=parity2))
- {
- e1.disconnect();
- e2.disconnect();
- e1.connectTo(e2);
- }
- }
-
-
-
- public void detach(RelativePosition edge)
- {
- // If the underlying template element is still connected, disconnect it
- if (getEndPoint(edge).isConnected())
- {
- getEndPoint(edge).disconnect();
- }
-
- // Call the parent class detach function, which will also take care to disconnect this other endpoint of this edge
- super.detach(edge);
- }
-
- public void setEdgePosition(RelativePosition edge, java.awt.geom.Point2D.Double pos) {
- switch (edge)
- {
- case RP_EDIT_START:
- setPos(pos);
- break;
- case RP_EDIT_END:
- setExtent(pos);
- break;
- case RP_INNER_MOVE:
- moveCenter(pos.x,pos.y);
- break;
- }
- updateAttachedUnpairedRegions();
- }
-
- public ArrayList<RelativePosition> getConnectedEdges() {
- ArrayList<RelativePosition> result = new ArrayList<RelativePosition>();
- result.add(RelativePosition.RP_CONNECT_START5);
- result.add(RelativePosition.RP_CONNECT_START3);
- result.add(RelativePosition.RP_CONNECT_END5);
- result.add(RelativePosition.RP_CONNECT_END3);
- return result;
- }
-
- public String toString()
- {
- return "Helix " + getCaption();
- }
-
- public RelativePosition relativePositionFromEdgeEndPointPosition(
- EdgeEndPointPosition pos) {
- switch (pos) {
- case IN1:
- return RelativePosition.RP_CONNECT_START5;
- case OUT1:
- return RelativePosition.RP_CONNECT_END5;
- case IN2:
- return RelativePosition.RP_CONNECT_END3;
- case OUT2:
- return RelativePosition.RP_CONNECT_START3;
- default:
- return null;
- }
- }
-
-}
-