\r
import java.awt.BorderLayout;\r
import java.awt.Color;\r
+import java.awt.Font;\r
import java.lang.reflect.InvocationTargetException;\r
import java.lang.reflect.Method;\r
import java.util.Collection;\r
import org.jfree.chart.plot.ValueMarker;\r
import org.jfree.data.xy.XYSeries;\r
import org.jfree.data.xy.XYSeriesCollection;\r
+import org.jfree.ui.RectangleInsets;\r
+import org.jfree.ui.TextAnchor;\r
import org.jscience.physics.amount.Amount;\r
\r
import com.billkuker.rocketry.motorsim.Burn;\r
Object source;\r
Method f;\r
\r
- @SuppressWarnings("unchecked")\r
public Chart(Unit<X> xUnit, Unit<Y> yUnit, Object source, String method)\r
throws NoSuchMethodException {\r
super(new BorderLayout());\r
marker = new ValueMarker(m.doubleValue(xUnit));\r
marker.setPaint(Color.blue);\r
marker.setAlpha(0.8f);\r
+ marker.setLabel(RocketScience.approx(getNear(m)));\r
+ \r
+ marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);\r
+ marker.setLabelOffset(new RectangleInsets(0,-5,0,0));\r
+ \r
+ marker.setLabelFont(new Font(Font.DIALOG, Font.BOLD, 12));\r
chart.getXYPlot().addDomainMarker(marker);\r
}\r
}\r
+ \r
+ /**\r
+ * Get the Y value at or near a given X\r
+ * For display use only!\r
+ * \r
+ * @param ax\r
+ * @return\r
+ */\r
+ private Amount<Y> getNear(final Amount<X> ax){\r
+ if ( dataset.getSeriesCount() != 1 )\r
+ return null;\r
+ final XYSeries s = dataset.getSeries(0);\r
+ final double x = ax.doubleValue(xUnit);\r
+ int idx = s.getItemCount() / 2;\r
+ int delta = s.getItemCount() / 4;\r
+ while(true){\r
+ if ( s.getX(idx).doubleValue() < x ){\r
+ idx += delta;\r
+ } else {\r
+ idx -= delta;\r
+ }\r
+ delta = delta / 2;\r
+ if ( delta < 1 ){\r
+ int idxL = idx-1;\r
+ int idxH = idx;\r
+ final double lowerX = s.getX(idxL).doubleValue();\r
+ final double higherX = s.getX(idxH).doubleValue();\r
+ final double sampleXDiff = higherX - lowerX;\r
+ final double xDiff = x - lowerX;\r
+ final double dist = xDiff / sampleXDiff;\r
+ final double lowerY = s.getY(idxL).doubleValue();\r
+ final double higherY = s.getY(idxH).doubleValue();\r
+ final double y = lowerY + dist * (higherY - lowerY);\r
+ \r
+ \r
+ return Amount.valueOf( y, yUnit);\r
+ }\r
+ }\r
+ }\r
\r
public void setDomain(final Iterable<Amount<X>> d) {\r
stop = true;\r
stop = false;\r
int sz = 0;\r
if (d instanceof Collection) {\r
- sz = ((Collection) d).size();\r
+ sz = ((Collection<Amount<X>>) d).size();\r
int sk2 = sz / 200;\r
if (skip < sk2)\r
skip = sk2;\r