Regenerate multiport geometry
[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.Quantity;
15
16 import org.jscience.physics.amount.Amount;
17
18 public class GraphSimplifier<X extends Quantity, Y extends Quantity> {
19         Method f;
20         
21         private static final int CHOOSE = 10;
22         private static final int EVEN = 10;
23         
24         private class Entry {
25                 Amount<X> x;
26                 Amount<Y> y;
27         }
28
29         @SuppressWarnings("rawtypes")
30         private class DDEntry implements Comparable<DDEntry> {
31                 Amount<X> x;
32                 Amount dd;
33
34                 @SuppressWarnings("unchecked")
35                 @Override
36                 public int compareTo(DDEntry o) {
37                         return o.dd.compareTo(dd);
38                 }
39         }
40
41         private SortedMap<Amount<X>, Amount<Y>> out = new TreeMap<Amount<X>, Amount<Y>>();
42
43         public Amount<Y> value(Amount<X> x) {
44                 return out.get(x);
45         }
46
47         public Iterable<Amount<X>> getDomain() {
48                 return out.keySet();
49         }
50
51         public GraphSimplifier(Object source, String method,
52                         Iterator<Amount<X>> domain) throws NoSuchMethodException,
53                         IllegalArgumentException, IllegalAccessException,
54                         InvocationTargetException {
55                 f = source.getClass().getMethod(method, Amount.class);
56
57                 Vector<Entry> oldEntries = new Vector<Entry>();
58                 Entry max = null;
59                 while (domain.hasNext()) {
60                         Amount<X> x = domain.next();
61                         @SuppressWarnings("unchecked")
62                         Amount<Y> y = (Amount<Y>) f.invoke(source, x);
63                         Entry e = new Entry();
64                         e.x = x;
65                         e.y = y;
66                         oldEntries.add(e);
67                         if ( max == null || e.y.isGreaterThan(max.y) )
68                                 max = 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                         //if this is one of the N even stepped
80                         //samples include it.
81                         if ( i % (oldEntries.size()/EVEN) == 0 ){
82                                 out.put(middle.x, middle.y);
83                         }
84
85                         @SuppressWarnings("rawtypes")
86                         Amount d1, d2, dd;
87
88                         d1 = middle.y.minus(low.y).divide(middle.x.minus(low.x));
89                         d2 = high.y.minus(middle.y).divide(high.x.minus(middle.x));
90                         
91                         //dd = (d1.isGreaterThan(d2))?d1:d2;
92                         
93                         
94                         dd = d2.minus(d1).divide(high.x.minus(low.x));
95
96                         DDEntry dde = new DDEntry();
97                         dde.dd = dd.abs();
98                         dde.x = middle.x;
99
100                         byDD.add(dde);
101                         byX.put(middle.x, middle.y);
102
103                 }
104
105                 Collections.sort(byDD);
106
107                 //always include the first, MAX and last
108                 out.put(oldEntries.elementAt(0).x, oldEntries.elementAt(0).y);
109                 out.put(max.x, max.y);
110                 int last = oldEntries.size() - 1;
111                 out.put(oldEntries.elementAt(last).x, oldEntries.elementAt(last).y);
112                 
113                 int count = 0;
114                 for (DDEntry dde : byDD) {
115                         if ( out.containsKey(dde.x) )
116                                 continue;
117                         out.put(dde.x, byX.get(dde.x));
118                         if (++count >= CHOOSE)
119                                 break;
120                 }
121                 
122         }
123         
124 }