Commit f214dc5540d410f1ae0838d8084de791a9264320

Reached peak bad in terms of code quality.
src/org/acsa/StatefulModel.java
(54 / 15)
  
22
33import java.awt.Graphics;
44import java.awt.image.BufferedImage;
5import java.io.File;
6import java.io.IOException;
57import java.util.ArrayList;
68import java.util.List;
79
10import javax.imageio.ImageIO;
11
812import org.acsa.analyzers.BoundaryViolationFinder;
913import org.acsa.analyzers.ConvexHullFinder;
14import org.acsa.analyzers.ExtrapolationFinder;
1015import org.acsa.analyzers.FeatureFinder;
1116import org.acsa.analyzers.OuterRegionFinder;
17import org.acsa.analyzers.PartitionFinder;
1218import org.acsa.analyzers.Position;
1319import org.acsa.filters.GrayscaleFilter;
1420import org.acsa.filters.OpacityFilter;
2828 private @Maybe BufferedImage filteredImage;
2929 private @Maybe List<List<Position>> edges;
3030 private @Maybe List<List<Position>> hulls;
31 private @Maybe List<List<Position>> questionableEdges;
3132 private @Maybe List<Double> convexities;
33 private @Maybe List<Position> inflections;
3234 private @Maybe String report;
3335
3436 public Scheme getScheme
7171 return hulls;
7272 }
7373
74 public List<List<Position>> getQuestionableEdges
75 () throws MaybeException {
76 if (questionableEdges == null)
77 throw new MaybeException();
78 return questionableEdges;
79 }
80
7481 public List<Double> getConvexities
7582 () throws MaybeException {
7683 if (convexities == null)
8585 return convexities;
8686 }
8787
88 public List<Position> getInflections
89 () throws MaybeException {
90 if (inflections == null)
91 throw new MaybeException();
92 return inflections;
93 }
94
8895 public void removeEdges
8996 () {
9097 edges = null;
138138 else
139139 convexities.add(edgeArea / hullArea);
140140 }
141 // TODO Implement speck and blob filtering and more.
141 final List<List<Position>> degenerateEdges = new ArrayList<List<Position>>();
142142 /*
143143 new OverlapViolationFinder(ratio).findOverlapped(edge);
144144 */
145 inflections = new ArrayList<Position>();
146 for (int index = 0;
147 index < edges.size();
148 ++index) {
149 final List<Position> edge = edges.get(index);
150 final Double convexity = convexities.get(index);
151 if (convexity < 0.5) {
152 edges.remove(index);
153 hulls.remove(index);
154 convexities.remove(index--);
155 }
156 else if (convexity < 0.91) {
157 // TODO Make the distance from the convex hull matter.
158 inflections.addAll(new PartitionFinder(-0.3, 4, 2).grindCCW(edge));
159 final List<List<Position>> degenerateEdge = new PartitionFinder(-0.3, 4, 2).findCCW(edge);
160 degenerateEdges.addAll(degenerateEdge);
161 edges.remove(index);
162 hulls.remove(index);
163 convexities.remove(index--);
164 }
165 }
166 questionableEdges = new ArrayList<List<Position>>();
167 questionableEdges.addAll(partialEdges);
168 questionableEdges.addAll(degenerateEdges);
169 for (int index = 0;
170 index < questionableEdges.size();
171 ++index) {
172 questionableEdges.set(index, new ExtrapolationFinder(32).findCircle(questionableEdges.get(index))); // This uses mean curvature.
173 }
174 // TODO Implement speck and blob filtering and more.
145175 /*
146 new InflectionPointFinder(curvature).findExcessive(edge);
147 */
148 /*
149 new PartitionFinder(curvature).findCCW(edge);
150 */
151 /*
152 new CentroidFinder(bias).findCentroid(edge);
153 */
154 /*
155 new ExtrapolationFinder(centroid).findCurve(edge);
156 */
157 /*
158176 new FeatureFinder().findArea(extrapolation);
159177 new FeatureFinder().findCircumference(extrapolation);
178 new FeatureFinder().findCentroid(extrapolation);
160179 */
161180 }
162181
195195 public StatefulModel
196196 () {
197197 scheme = Scheme.UNIONOIDA;
198 /*
199198 try {
200199 image = ImageIO.read(new File("/home/tuplanolla/clams.png"));
201200 try {
202201 findEdges();
203202 } catch (final MaybeException exception) {}
204203 } catch (final IOException exception) {}
205 */
206204 }
207205}
src/org/acsa/analyzers/ExtrapolationFinder.java
(59 / 0)
  
1package org.acsa.analyzers;
2
3import java.util.AbstractMap;
4import java.util.AbstractMap.SimpleEntry;
5import java.util.ArrayList;
6import java.util.List;
7
8// TODO Look into numerical stability.
9public final class ExtrapolationFinder {
10 final int iterations;
11
12 public ExtrapolationFinder
13 (final int iterations) {
14 this.iterations = iterations;
15 }
16
17 // TODO Move into a general class.
18 private double rescale
19 (final double a, final double b, final double c, final double d, final double x) {
20 return ((d - c) * x - (a * d - b * c)) / (b - a);
21 }
22
23 // TODO Heal the stupid.
24 public List<Position> findCircle
25 (final List<Position> edge) {
26 final List<AbstractMap.Entry<Double, Double>> curvatures = new ArrayList<AbstractMap.Entry<Double, Double>>();
27 for (int index = 2;
28 index < edge.size();
29 ++index) {
30 final Position start = edge.get(index - 2);
31 final Position middle = edge.get(index - 1);
32 final Position end = edge.get(index);
33 final SimpleEntry<Double, Double> entry = PartitionFinder.curvature(start, middle, end);
34 curvatures.add(entry);
35 }
36 final double r = 1 / PartitionFinder.weightedMean(curvatures);
37 /*
38 Solving
39 (x - x_1) ^ 2 + (y - y_1) ^ 2 = r ^ 2
40 (x - x_2) ^ 2 + (y - y_2) ^ 2 = r ^ 2
41 leads through
42 (x_1 ^ 2 + (y - y_1) ^ 2 - r ^ 2) - 2 x_1 x + x ^ 2 = 0
43 to
44 something.
45 */
46 final double zx = 42;
47 final double zy = 207;
48 final List<Position> circle = new ArrayList<Position>(edge);
49 for (int iteration = 0;
50 iteration < iterations;
51 ++iteration) {
52 final double angle = rescale(0, iterations, -Math.PI / 2, -Math.PI / 3, iteration);
53 final double ex = zx + r * Math.cos(angle);
54 final double ey = zy + r * Math.sin(angle);
55 circle.add(new Position((int )Math.round(ex), (int )Math.round(ey)));
56 }
57 return circle;
58 }
59}
src/org/acsa/analyzers/FeatureFinder.java
(20 / 2)
  
11package org.acsa.analyzers;
22
3import java.util.Collection;
34import java.util.List;
45
6// TODO Look into numerical stability.
57public final class FeatureFinder {
68 public FeatureFinder
79 () {}
810
11 // TODO Move into a general class.
912 private double determinant
1013 (final int x11, final int x12, final int x21, final int x22) {
1114 return x11 * x22 - x12 * x21;
1215 }
1316
14 public double findCircumference
17 // TODO Move into a general class.
18 public Position mean
19 (final Collection<Position> list) {
20 Position sum = new Position(0, 0);
21 for (final Position position : list) {
22 sum = sum.add(position);
23 }
24 return new Position(sum.getX() / list.size(), sum.getY() / list.size()); // This can be wrong.
25 }
26
27 public double findCircumference // The circumference is always a cyclotomic number.
1528 (final List<Position> edge) {
1629 double circumference = 0;
1730 for (int index = 1;
3636 return circumference;
3737 }
3838
39 public double findArea
39 public double findArea // The area is always a half integer.
4040 (final List<Position> edge) {
4141 if (edge.size() < 3)
4242 return 0;
5151 area += determinant(pi1.getX(), pi.getX(), pi1.getY(), pi.getY());
5252 }
5353 return area / 2;
54 }
55
56 public Position findCentroid
57 (final List<Position> edge) {
58 return mean(edge);
5459 }
5560}
src/org/acsa/analyzers/PartitionFinder.java
(117 / 0)
  
1package org.acsa.analyzers;
2
3import java.util.AbstractMap;
4import java.util.AbstractMap.SimpleEntry;
5import java.util.ArrayList;
6import java.util.Collection;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.Map.Entry;
10import java.util.Queue;
11
12// TODO Look into numerical stability.
13public final class PartitionFinder {
14 private final double curvature; // This is in radians per arc length.
15 private final int smoothness; // This is in unit lengths.
16 private final int density; // This is in unit lengths.
17
18 public PartitionFinder
19 (final double curvature, final int smoothness, final int density) {
20 this.curvature = curvature;
21 this.smoothness = smoothness;
22 this.density = density;
23 }
24
25 // TODO Move into a general class.
26 public static AbstractMap.SimpleEntry<Double, Double> curvature
27 (final Position start, final Position middle, final Position end) {
28 /*
29 For parametric curves the curvature
30 k = (x' y'' - x'' y') / (x' ^ 2 + y' ^ 2) ^ (3 / 2),
31 where x, y and k are functions of t.
32 Discretizing the domain makes the derivatives obey
33 z'(t) = (z(t + 1) - z(t)) / c
34 z''(t) = (z'(t + 1) - z'(t)) / d
35 = (z(t + 2) - 2 z(t + 1) + z(t)) / (c d)
36 for all z in {x, y}.
37 */
38 final int xt0 = start.getX();
39 final int xt1 = middle.getX();
40 final int xt2 = end.getX();
41 final int yt0 = start.getY();
42 final int yt1 = middle.getY();
43 final int yt2 = end.getY();
44 final int dxt01 = xt1 - xt0;
45 final int dxt12 = xt2 - xt1;
46 final int dyt01 = yt1 - yt0;
47 final int dyt12 = yt2 - yt1;
48 final double c01 = Math.sqrt(dxt01 * dxt01 + dyt01 * dyt01);
49 final double c12 = Math.sqrt(dxt12 * dxt12 + dyt12 * dyt12);
50 final double dx = dxt01 / c01;
51 final double dy = dyt01 / c01;
52 final double ddx = (dxt12 - dxt01) / (c01 * c12);
53 final double ddy = (dyt12 - dyt01) / (c01 * c12);
54 final double k = (dx * ddy - ddx * dy) / Math.pow(dx * dx + dy * dy, (double )3 / 2);
55 return new AbstractMap.SimpleEntry<Double, Double>(c01 + c12, k);
56 }
57
58 // TODO Move into a general class.
59 public static double weightedMean
60 (final Collection<AbstractMap.Entry<Double, Double>> list) {
61 AbstractMap.Entry<Double, Double> mean = new AbstractMap.SimpleEntry<Double, Double>(Double.valueOf(0), Double.valueOf(0));
62 for (final Entry<Double, Double> entry : list) {
63 final double key = mean.getKey() + entry.getKey();
64 mean = new AbstractMap.SimpleEntry<Double, Double>(key, (mean.getKey() * mean.getValue() + entry.getKey() * entry.getValue()) / key);
65 }
66 return mean.getValue(); // This can be wrong.
67 }
68
69 // TODO Replace the running average with a proper smoothing function that emphasizes negative condensation.
70 public List<Position> grindCCW
71 (final List<Position> edge) {
72 final List<Position> inflections = new ArrayList<Position>();
73 if (edge.size() < 3)
74 return inflections;
75 final Queue<AbstractMap.Entry<Double, Double>> curvatures = new LinkedList<AbstractMap.Entry<Double, Double>>();
76 int ignorance = density;
77 for (int index = 2;
78 index < edge.size();
79 ++index) {
80 final Position start = edge.get(index - 2);
81 final Position middle = edge.get(index - 1);
82 final Position end = edge.get(index);
83 final SimpleEntry<Double, Double> entry = curvature(start, middle, end);
84 curvatures.offer(entry);
85 if (curvatures.size() > smoothness)
86 curvatures.poll();
87 final double mean = weightedMean(curvatures);
88 if (ignorance > 0)
89 --ignorance;
90 else if (mean < curvature) {
91 inflections.add(middle);
92 ignorance += density;
93 }
94 }
95 return inflections;
96 }
97
98 // TODO Consider removing explicit inflection point finding.
99 public List<List<Position>> findCCW
100 (final List<Position> edge) {
101 final List<Position> inflections = grindCCW(edge);
102 final List<List<Position>> partitions = new ArrayList<List<Position>>();
103 List<Position> partition = new ArrayList<Position>();
104 for (final Position position : edge) {
105 partition.add(position);
106 if (inflections.contains(position)) {
107 partitions.add(partition);
108 partition = new ArrayList<Position>();
109 partition.add(position);
110 }
111 }
112 final List<Position> lastPartition = new ArrayList<Position>(partition);
113 lastPartition.addAll(partitions.get(0));
114 partitions.set(0, lastPartition);
115 return partitions;
116 }
117}
src/org/acsa/analyzers/Position.java
(5 / 0)
  
2020 this.y = y;
2121 }
2222
23 public double length
24 () {
25 return Math.sqrt(x * x + y * y);
26 }
27
2328 public Position add
2429 (final Position position) {
2530 return new Position(x + position.x, y + position.y);
src/org/acsa/interfaces/swing/SwingMediator.java
(5 / 0)
  
112112 if (state == JFileChooser.APPROVE_OPTION) {
113113 final File file = fileChooser.getSelectedFile();
114114 try {
115 getView().getPropertyLabelPane().setText(file.getName());
115116 getViewModel().setZoom(1);
116117 getModel().setImage(ImageIO.read(file));
117118 getModel().removeEdges();
301301 graphics.drawString(formatter.format("%1.3f", getModel().getConvexities().get(index)).toString(), position.getX(), position.getY());
302302 formatter.close();
303303 }
304 graphics.setColor(Color.GREEN);
305 for (final Position position : getModel().getInflections())
306 graphics.drawOval(position.getX() - 2, position.getY() - 2, 4, 4);
304307 hedges.addAll(getModel().getHulls());
308 hedges.addAll(getModel().getQuestionableEdges());
305309 for (int index = 0;
306310 index < hedges.size();
307311 ++index) {