1
2
3
4
5
6
7
8
9
10 package edu.uci.ics.jung.visualization.util;
11
12 import java.awt.Shape;
13 import java.awt.geom.AffineTransform;
14 import java.awt.geom.Ellipse2D;
15 import java.awt.geom.GeneralPath;
16 import java.awt.geom.Point2D;
17 import java.awt.geom.Rectangle2D;
18 import java.awt.geom.RoundRectangle2D;
19
20 import org.apache.commons.collections15.Transformer;
21 import org.apache.commons.collections15.functors.ConstantTransformer;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class VertexShapeFactory<V>
36 {
37 protected Transformer<V,Integer> vsf;
38 protected Transformer<V,Float> varf;
39
40
41
42
43
44 public VertexShapeFactory(Transformer<V,Integer> vsf, Transformer<V,Float> varf)
45 {
46 this.vsf = vsf;
47 this.varf = varf;
48 }
49
50
51
52
53
54 @SuppressWarnings("unchecked")
55 public VertexShapeFactory()
56 {
57 this(new ConstantTransformer(10),
58 new ConstantTransformer(1.0f));
59 }
60
61 private static final Rectangle2D theRectangle = new Rectangle2D.Float();
62
63
64
65
66
67 public Rectangle2D getRectangle(V v)
68 {
69 float width = vsf.transform(v);
70 float height = width * varf.transform(v);
71 float h_offset = -(width / 2);
72 float v_offset = -(height / 2);
73 theRectangle.setFrame(h_offset, v_offset, width, height);
74 return theRectangle;
75 }
76
77 private static final Ellipse2D theEllipse = new Ellipse2D.Float();
78
79
80
81
82
83 public Ellipse2D getEllipse(V v)
84 {
85 theEllipse.setFrame(getRectangle(v));
86 return theEllipse;
87 }
88
89 private static final RoundRectangle2D theRoundRectangle =
90 new RoundRectangle2D.Float();
91
92
93
94
95
96
97 public RoundRectangle2D getRoundRectangle(V v)
98 {
99 Rectangle2D frame = getRectangle(v);
100 float arc_size = (float)Math.min(frame.getHeight(), frame.getWidth()) / 2;
101 theRoundRectangle.setRoundRect(frame.getX(), frame.getY(),
102 frame.getWidth(), frame.getHeight(), arc_size, arc_size);
103 return theRoundRectangle;
104 }
105
106 private static final GeneralPath thePolygon = new GeneralPath();
107
108
109
110
111
112
113
114 public Shape getRegularPolygon(V v, int num_sides)
115 {
116 if (num_sides < 3)
117 throw new IllegalArgumentException("Number of sides must be >= 3");
118 Rectangle2D frame = getRectangle(v);
119 float width = (float)frame.getWidth();
120 float height = (float)frame.getHeight();
121
122
123 double angle = 0;
124 thePolygon.reset();
125 thePolygon.moveTo(0,0);
126 thePolygon.lineTo(width, 0);
127 double theta = (2 * Math.PI) / num_sides;
128 for (int i = 2; i < num_sides; i++)
129 {
130 angle -= theta;
131 float delta_x = (float) (width * Math.cos(angle));
132 float delta_y = (float) (width * Math.sin(angle));
133 Point2D prev = thePolygon.getCurrentPoint();
134 thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y);
135 }
136 thePolygon.closePath();
137
138
139 Rectangle2D r = thePolygon.getBounds2D();
140 double scale_x = width / r.getWidth();
141 double scale_y = height / r.getHeight();
142 float translationX = (float) (r.getMinX() + r.getWidth()/2);
143 float translationY = (float) (r.getMinY() + r.getHeight()/2);
144
145 AffineTransform at = AffineTransform.getScaleInstance(scale_x, scale_y);
146 at.translate(-translationX, -translationY);
147
148 Shape shape = at.createTransformedShape(thePolygon);
149 return shape;
150 }
151
152
153
154
155
156
157
158
159 public Shape getRegularStar(V v, int num_points)
160 {
161 if (num_points < 5)
162 throw new IllegalArgumentException("Number of sides must be >= 5");
163 Rectangle2D frame = getRectangle(v);
164 float width = (float) frame.getWidth();
165 float height = (float) frame.getHeight();
166
167
168 double theta = (2 * Math.PI) / num_points;
169 double angle = -theta/2;
170 thePolygon.reset();
171 thePolygon.moveTo(0,0);
172 float delta_x = width * (float)Math.cos(angle);
173 float delta_y = width * (float)Math.sin(angle);
174 Point2D prev = thePolygon.getCurrentPoint();
175 thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y);
176 for (int i = 1; i < num_points; i++)
177 {
178 angle += theta;
179 delta_x = width * (float)Math.cos(angle);
180 delta_y = width * (float)Math.sin(angle);
181 prev = thePolygon.getCurrentPoint();
182 thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y);
183 angle -= theta*2;
184 delta_x = width * (float)Math.cos(angle);
185 delta_y = width * (float)Math.sin(angle);
186 prev = thePolygon.getCurrentPoint();
187 thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y);
188 }
189 thePolygon.closePath();
190
191
192 Rectangle2D r = thePolygon.getBounds2D();
193 double scale_x = width / r.getWidth();
194 double scale_y = height / r.getHeight();
195
196 float translationX = (float) (r.getMinX() + r.getWidth()/2);
197 float translationY = (float) (r.getMinY() + r.getHeight()/2);
198
199 AffineTransform at = AffineTransform.getScaleInstance(scale_x, scale_y);
200 at.translate(-translationX, -translationY);
201
202 Shape shape = at.createTransformedShape(thePolygon);
203 return shape;
204 }
205 }