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