Improved Test Code
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / GraphSimplifier.java
1 package com.billkuker.rocketry.motorsim;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.lang.reflect.Method;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.SortedMap;
11 import java.util.TreeMap;
12 import java.util.Vector;
13
14 import javax.measure.quantity.Area;
15 import javax.measure.quantity.Length;
16 import javax.measure.quantity.Quantity;
17 import javax.measure.unit.SI;
18 import javax.swing.JFrame;
19 import javax.swing.JSplitPane;
20
21 import org.jscience.physics.amount.Amount;
22
23 import com.billkuker.rocketry.motorsim.grain.CoredCylindricalGrain;
24 import com.billkuker.rocketry.motorsim.visual.Chart;
25
26 public class GraphSimplifier<X extends Quantity, Y extends Quantity> {
27         Method f;
28
29         private class Entry {
30                 Amount<X> x;
31                 Amount<Y> y;
32         }
33
34         private class DDEntry implements Comparable<DDEntry> {
35                 Amount<X> x;
36                 Amount dd;
37
38                 @Override
39                 public int compareTo(DDEntry o) {
40                         return dd.compareTo(o.dd);
41                 }
42         }
43
44         private SortedMap<Amount<X>, Amount<Y>> out = new TreeMap<Amount<X>, Amount<Y>>();
45
46         public Amount<Y> value(Amount<X> x) {
47                 return out.get(x);
48         }
49
50         public Iterable<Amount<X>> getDomain() {
51                 return out.keySet();
52         }
53
54         public GraphSimplifier(Object source, String method,
55                         Iterator<Amount<X>> domain) throws NoSuchMethodException,
56                         IllegalArgumentException, IllegalAccessException,
57                         InvocationTargetException {
58                 f = source.getClass().getMethod(method, Amount.class);
59
60                 Vector<Entry> oldEntries = new Vector<Entry>();
61
62                 while (domain.hasNext()) {
63                         Amount<X> x = domain.next();
64                         Amount<Y> y = (Amount<Y>) f.invoke(source, x);
65                         Entry e = new Entry();
66                         e.x = x;
67                         e.y = y;
68                         oldEntries.add(e);
69                 }
70
71                 List<DDEntry> byDD = new Vector<DDEntry>();
72                 Map<Amount<X>, Amount<Y>> byX = new HashMap<Amount<X>, Amount<Y>>();
73
74                 for (int i = 1; i < oldEntries.size() - 1; i++) {
75                         Entry low = oldEntries.elementAt(i - 1);
76                         Entry middle = oldEntries.elementAt(i);
77                         Entry high = oldEntries.elementAt(i + 1);
78
79                         Amount<?> d1, d2, dd;
80
81                         d1 = middle.y.minus(low.y).divide(middle.x.minus(low.x));
82                         d2 = high.y.minus(middle.y).divide(high.x.minus(middle.x));
83                         dd = d2.minus(d1).divide(high.x.minus(low.x));
84
85                         DDEntry dde = new DDEntry();
86                         dde.dd = dd.abs();
87                         dde.x = middle.x;
88
89                         byDD.add(dde);
90                         byX.put(middle.x, middle.y);
91
92                 }
93
94                 Collections.sort(byDD);
95
96                 out.put(oldEntries.elementAt(0).x, oldEntries.elementAt(0).y);
97                 int count = 0;
98                 for (DDEntry dde : byDD) {
99                         out.put(dde.x, byX.get(dde.x));
100                         if (++count >= 20)
101                                 break;
102                 }
103                 int last = oldEntries.size() - 1;
104                 out.put(oldEntries.elementAt(last).x, oldEntries.elementAt(last).y);
105
106         }
107
108         public static void main(String args[]) throws Exception {
109                 CoredCylindricalGrain g = new CoredCylindricalGrain();
110                 g.setLength(Amount.valueOf(70, SI.MILLIMETER));
111                 g.setOD(Amount.valueOf(30, SI.MILLIMETER));
112                 g.setID(Amount.valueOf(10, SI.MILLIMETER));
113                 
114                 JFrame f = new JFrame();
115                 f.setSize(1024, 768);
116                 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
117                 JSplitPane jsp = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
118                 f.add(jsp);
119
120                 Chart<Length, Area> c = new Chart<Length, Area>(SI.MILLIMETER,
121                                 SI.MILLIMETER.pow(2).asType(Area.class), g, "surfaceArea");
122                 c.setDomain(c.new IntervalDomain(Amount.valueOf(0, SI.CENTIMETER), g
123                                 .webThickness()));
124                 jsp.setTopComponent(c);
125
126                 GraphSimplifier<Length, Area> gs = new GraphSimplifier(g,
127                                 "surfaceArea", c.new IntervalDomain(Amount.valueOf(0,
128                                                 SI.CENTIMETER), g.webThickness()).iterator());
129
130                 Chart<Length, Area> d = new Chart<Length, Area>(SI.MILLIMETER,
131                                 SI.MILLIMETER.pow(2).asType(Area.class), gs, "value");
132                 d.setDomain(gs.getDomain());
133                 jsp.setBottomComponent(d);
134                 
135                 f.setVisible(true);
136                 jsp.setDividerLocation(.5);
137                 jsp.revalidate();
138         }
139 }