001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.bio.gui.glyph;
022
023import java.awt.Color;
024import java.awt.Graphics2D;
025import java.awt.Paint;
026import java.awt.Shape;
027import java.awt.geom.Point2D;
028import java.awt.geom.Rectangle2D;
029import java.util.ArrayList;
030import java.util.List;
031
032
033/**
034 * A Glyph that paints a Helix within the bounds
035 *
036 * @author Mark Southern
037 * @since 1.5
038 */
039public class HelixGlyph implements Glyph {
040    private Paint forePaint;
041    private Paint backPaint;
042    private Rectangle2D.Float bounds = new Rectangle2D.Float(0, 0, 0, 0);
043    private Shape foreShape;
044    private Shape backShape;
045
046    public HelixGlyph() {
047        forePaint = Color.RED;
048        backPaint = Color.RED.darker().darker();
049    }
050
051    public HelixGlyph(Rectangle2D.Float bounds) {
052        this();
053        setBounds(bounds);
054    }
055
056    public Rectangle2D.Float getBounds() {
057        return bounds;
058    }
059
060    public void setBounds(Rectangle2D.Float r) {
061        if (bounds.equals(r)) {
062            return;
063        }
064
065        int[] vals = null;
066        float hh = 0;
067
068        //if (r.height != bounds.height) {
069        hh = r.height / 2F;
070        vals = new int[ 2 * ( int ) hh ];
071        //System.out.println("length\t"+vals.length);
072
073        double dd = (2 * Math.PI) / vals.length;
074        //System.out.println("dd\t"+dd);
075        
076        for (int i = 0; i < vals.length; i++) {
077            double v = ( double ) hh * Math.cos(dd * ( double ) i);
078            vals[ i ] = ( int ) v;
079            //System.out.println(i + "\t" + vals[i] );
080        }
081
082        //}
083        //if(r.width != bounds.width && vals != null){
084        List p1 = new ArrayList(2 * vals.length);
085        List p2 = new ArrayList(2 * vals.length);
086
087        for (int i = 0; i < r.width; i++) {
088            int j = i % vals.length;
089
090            if (j < (vals.length / 2)) {
091                p1.add(new Point2D.Float(r.x + i, (r.y + hh) - vals[ j ]));
092            } else {
093                p1.add(new Point2D.Float(r.x + i, r.y));
094            }
095
096            if (vals[ j ] < 0) {
097                p2.add(new Point2D.Float(r.x + i, r.y + hh + vals[ j ]));
098            }
099        }
100
101        for (int i = ( int ) r.width - 1; i >= 0; i--) {
102            int j = i % vals.length;
103
104            if (j < (vals.length / 2)) {
105                p1.add(new Point2D.Float(r.x + i, r.y + r.height));
106            } else {
107                p1.add(new Point2D.Float(r.x + i, r.y + hh + vals[ j ]));
108            }
109
110            if (vals[ j ] < 0) {
111                p2.add(new Point2D.Float(r.x + i, (r.y + hh) - vals[ j ]));
112            }
113        }
114
115        foreShape = GlyphUtils.getShape(p1);
116        backShape = GlyphUtils.getShape(p2);
117
118        //}
119        bounds = r;
120    }
121
122    public void render(Graphics2D g) {
123        if (backShape != null) {
124            g.setPaint(backPaint);
125            g.fill(backShape);
126        }
127
128        if (foreShape != null) {
129            g.setPaint(forePaint);
130            g.fill(foreShape);
131        }
132    }
133}