├── .gitignore ├── README.md ├── logo.png ├── pom.xml └── src ├── doc ├── applet-demo.jar ├── demo.html ├── demo.jnlp ├── demo.xml └── sample_capture.png ├── main ├── java │ └── net │ │ └── ericaro │ │ └── surfaceplotter │ │ ├── AbstractSurfaceModel.java │ │ ├── DefaultSurfaceModel.java │ │ ├── JSurfaceApplet.java │ │ ├── JSurfacePanel.java │ │ ├── JSurfacePanel.jfd │ │ ├── Mapper.java │ │ ├── ProgressiveSurfaceModel.java │ │ ├── beans │ │ ├── BeanProperty.java │ │ ├── JBindedCheckBox.java │ │ ├── JBindedRadioButton.java │ │ ├── JEnumComboBox.java │ │ ├── JGridBagScrollPane.java │ │ ├── JPlotColorComboBox.java │ │ ├── JPlotTypeComboBox.java │ │ ├── JScrollablePanel.java │ │ ├── ModelBindedBeanProperty.java │ │ └── ModelSource.java │ │ └── surface │ │ ├── AbstractSurfaceModel.java │ │ ├── ArraySurfaceModel.java │ │ ├── ColorModel.java │ │ ├── ColorModelSet.java │ │ ├── JSurface.java │ │ ├── LineAccumulator.java │ │ ├── Projector.java │ │ ├── SurfaceColor.java │ │ ├── SurfaceModel.java │ │ ├── SurfaceUtils.java │ │ ├── SurfaceVertex.java │ │ ├── VerticalConfigurationPanel.java │ │ └── VerticalConfigurationPanel.jfd └── resources │ └── net │ └── ericaro │ └── surfaceplotter │ ├── JSurfacePanel.properties │ └── surface │ └── VerticalConfigurationPanel.properties └── test └── java ├── Sample.java ├── Sample.jfd └── SimpleRun.java /.gitignore: -------------------------------------------------------------------------------- 1 | # maven 2 | target 3 | 4 | # eclipse 5 | .project 6 | .classpath 7 | .settings 8 | .externalToolBuilders 9 | 10 | # java 11 | *.class 12 | 13 | # python 14 | *.pyc 15 | 16 | # gedit backup files 17 | *~ 18 | *.*~ 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # surfaceplotter 2 | 3 | A nice, simple, zoomable 3D surface plot in Java/Swing, designed for reuse 4 | 5 | ![screenshot](https://github.com/ericaro/surfaceplotter/raw/master/src/doc/sample_capture.png) 6 | 7 | 8 | Initially written by Yanto Suryono 9 | 10 | # Getting Started 11 | 12 | using maven: net.ericaro:surfaceplotter:2.0.1 13 | 14 | - group ID *net.ericaro* 15 | - Artifact ID *surfaceplotter* 16 | - version *2.0.1* 17 | - Available at : 18 | - Releases : maven central repo 19 | - Snapshots : https://oss.sonatype.org/content/repositories/snapshots/ 20 | 21 | If you are not a maven user then it is available for [download](http://oss.sonatype.org/content/groups/public/net/ericaro/surfaceplotter). 22 | 23 | # Status 24 | 25 | You can track progress looking at the issues. 26 | 27 | - 2015 04 16 : moving to github 28 | - 2012 04 04 : moving to git, and fixing some high priority issues 29 | - 2011 10 03 : released 2.0.1 a bug fix release. 30 | - 2011 06 23 : after a month testing on a real life app, version 2.0.0 is released 31 | - 2011 05 18 : Simplified the way to pass plots, and released beta3. 32 | - 2011 05 17 : Demo applet. Export to SVG. Code reorganization/documentation. Bug fixes. Getting ready for release 33 | - 2010 10 05 : version 2.0.0.beta2 first release. Enjoy 34 | - 2010 10 04 : version 2.0.0-SNAPSHOT first release. You can now give it a try. 35 | - 2010 01 24 : Version 1.3.1 is a simple port to maven of the orginal project, and a change in the license from GPL to LGPL, as agreed with Yanto. 36 | 37 | # Plans 38 | 39 | No more plans, if you are interested in continuing this effort, feel free to contact me. 40 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericaro/surfaceplotter/05bd93ac908e5cf9ace63cfdffccdf2dc782fd55/logo.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | net.ericaro 4 | surfaceplotter 5 | Surface Plotter 6 | 2.0.2-SNAPSHOT 7 | 8 | org.sonatype.oss 9 | oss-parent 10 | 7 11 | 12 | Simple, reusable, 3D surface-plotter library in Java/Swing. 13 | 14 | 15 | 16 | junit 17 | junit 18 | 3.8.2 19 | jar 20 | test 21 | 22 | 23 | org.apache.xmlgraphics 24 | batik-svggen 25 | 1.7 26 | jar 27 | compile 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | ${project.artifactId} 36 | 37 | 38 | 39 | http://${googlecode}.googlecode.com/ 40 | 41 | 42 | sonatype-nexus-snapshots 43 | Sonatype Nexus Snapshots 44 | http://oss.sonatype.org/content/repositories/snapshots 45 | 46 | 47 | sonatype-nexus-staging 48 | Nexus Release Repository 49 | http://oss.sonatype.org/service/local/staging/deploy/maven2/ 50 | 51 | 52 | 53 | 54 | release 55 | 56 | 57 | performRelease 58 | true 59 | 60 | 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-gpg-plugin 66 | 1.0 67 | 68 | 69 | sign-artifacts 70 | verify 71 | 72 | sign 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | applet 82 | 83 | 84 | 85 | maven-assembly-plugin 86 | 2.2.1 87 | 88 | 89 | jar-with-dependencies 90 | 91 | 92 | true 93 | 94 | true 95 | 96 | 97 | 98 | 99 | 100 | make-my-applet-jar 101 | package 102 | 103 | single 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | scm:git:http://surfaceplotter.googlecode.com/git/ 116 | 117 | 118 | 119 | GNU LGPL 120 | www.gnu.org/licenses/lgpl.txt 121 | repo 122 | 123 | 124 | 125 | 126 | ericaro 127 | eric@ericaro.net 128 | Personal 129 | 130 | Owner 131 | 132 | 133 | 134 | yanto.suryono 135 | 136 | Contributor 137 | First Author 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | org.apache.maven.plugins 146 | maven-source-plugin 147 | 148 | 149 | org.apache.maven.plugins 150 | maven-resources-plugin 151 | 152 | 153 | org.apache.maven.plugins 154 | maven-javadoc-plugin 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | org.apache.maven.plugins 165 | maven-compiler-plugin 166 | 2.3.2 167 | 168 | 1.5 169 | 1.5 170 | 171 | 172 | 173 | org.apache.maven.plugins 174 | maven-resources-plugin 175 | 2.5 176 | 177 | 178 | 179 | 180 | org.apache.maven.plugins 181 | maven-source-plugin 182 | 2.1.2 183 | 184 | 185 | attach-sources 186 | 187 | jar 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | org.apache.maven.plugins 196 | maven-javadoc-plugin 197 | 2.8 198 | 199 | 200 | 201 | 202 | 203 | attach-javadocs 204 | 205 | jar 206 | 207 | 208 | 209 | 210 | 211 | 212 | org.apache.maven.plugins 213 | maven-release-plugin 214 | 2.1 215 | 216 | 217 | https://${googlecode}.googlecode.com/svn/tags 218 | false 219 | clean install 220 | deploy 221 | -Prelease,deploy 222 | true 223 | forked-path 224 | 225 | 226 | 227 | org.apache.maven.plugins 228 | maven-gpg-plugin 229 | 1.0-alpha-4 230 | 231 | 232 | sign-artifacts 233 | verify 234 | 235 | sign 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /src/doc/applet-demo.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericaro/surfaceplotter/05bd93ac908e5cf9ace63cfdffccdf2dc782fd55/src/doc/applet-demo.jar -------------------------------------------------------------------------------- /src/doc/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | If you can read this, your browser can't display ChView 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/doc/demo.jnlp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Surface Plotter Demo 5 | ericaro.net 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/doc/demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/doc/sample_capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericaro/surfaceplotter/05bd93ac908e5cf9ace63cfdffccdf2dc782fd55/src/doc/sample_capture.png -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/AbstractSurfaceModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter; 2 | 3 | import java.beans.PropertyChangeSupport; 4 | import java.io.File; 5 | import java.io.IOException; 6 | 7 | import javax.swing.event.ChangeEvent; 8 | import javax.swing.event.ChangeListener; 9 | import javax.swing.event.SwingPropertyChangeSupport; 10 | 11 | import net.ericaro.surfaceplotter.surface.ColorModelSet; 12 | import net.ericaro.surfaceplotter.surface.Projector; 13 | import net.ericaro.surfaceplotter.surface.SurfaceColor; 14 | import net.ericaro.surfaceplotter.surface.SurfaceModel; 15 | import net.ericaro.surfaceplotter.surface.SurfaceVertex; 16 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotColor; 17 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotType; 18 | 19 | 20 | /** 21 | * {@link AbstractSurfaceModel} provides a writable implementation of the {@link SurfaceModel} interface. 22 | * Writting is available throught setters for any properties, and through a simple "Plotter" interface, to fill the curves. 23 | */ 24 | public class AbstractSurfaceModel implements SurfaceModel { 25 | 26 | /** 27 | * Interface returned by this object to write values in this model 28 | * 29 | * @author eric 30 | */ 31 | public interface Plotter { 32 | public int getHeight(); 33 | 34 | public int getWidth(); 35 | 36 | public float getX(int i); 37 | 38 | public float getY(int j); 39 | 40 | public void setValue(int i, int j, float v1, float v2); 41 | 42 | } 43 | 44 | /** 45 | * Parses defined functions and calculates surface vertices 46 | */ 47 | class PlotterImpl implements Plotter { 48 | int calcDivisions; 49 | boolean f1, f2; 50 | int i, j, total; 51 | int imgheight = 0; 52 | int imgwidth = 0; 53 | 54 | float min1, max1, min2, max2; 55 | int[] pixels = null; 56 | float stepx, stepy; 57 | float xfactor; 58 | float xi, xx, yi, yx; 59 | 60 | float yfactor; 61 | 62 | public PlotterImpl() { 63 | // reads the calcDivision that will be used 64 | calcDivisions = getCalcDivisions(); 65 | setDataAvailable(false); // clean space 66 | total = (calcDivisions + 1) * (calcDivisions + 1); // compute total size 67 | f1 = hasFunction1; 68 | f2 = hasFunction2; // define the size of the plot 69 | surfaceVertex = allocateMemory(f1, f2, total); // allocate surfaceVertex 70 | setSurfaceVertex(surfaceVertex); // define as the current surfaceVertex 71 | setDataAvailable(true); 72 | min1 = max1 = min2 = max2 = Float.NaN; 73 | getProjector(); 74 | try { 75 | xi = getXMin(); 76 | yi = getYMin(); 77 | xx = getXMax(); 78 | yx = getYMax(); 79 | if ((xi >= xx) || (yi >= yx)) 80 | throw new NumberFormatException(); 81 | } catch (NumberFormatException e) { 82 | setMessage("Error in ranges"); 83 | return; 84 | } 85 | stepx = (xx - xi) / calcDivisions; 86 | stepy = (yx - yi) / calcDivisions; 87 | xfactor = 20 / (xx - xi); 88 | yfactor = 20 / (yx - yi); 89 | 90 | // fill the surface surfaceVertex with NaN 91 | for (int i = 0; i <= calcDivisions; i++) 92 | for (int j = 0; j <= calcDivisions; j++) { 93 | int k = i * (calcDivisions + 1) + j; 94 | 95 | float x = getX(i); 96 | float y = getY(j); 97 | if (f1) { 98 | surfaceVertex[0][k] = new SurfaceVertex((x - xi) * xfactor - 10, (y - yi) * yfactor - 10, Float.NaN); 99 | } 100 | if (f2) { 101 | surfaceVertex[1][k] = new SurfaceVertex((x - xi) * xfactor - 10, (y - yi) * yfactor - 10, Float.NaN); 102 | } 103 | } 104 | 105 | } 106 | 107 | public int getHeight() { 108 | return calcDivisions + 1; 109 | } 110 | 111 | public int getWidth() { 112 | return calcDivisions + 1; 113 | } 114 | 115 | /** 116 | * Get the x float value that can be used to compute the fonction at 117 | * position i. 118 | * 119 | * @param i 120 | * index 0<=i<=calcDivisions. 121 | * @author eric 122 | */ 123 | public float getX(int i) { 124 | return xi + i * stepx; 125 | } 126 | 127 | /** 128 | * Get the x float value that can be used to compute the fonction at 129 | * position i. 130 | * 131 | * @param j 132 | * index 0<=j<=calcDivisions. 133 | * @author eric 134 | */ 135 | public float getY(int j) { 136 | return yi + j * stepy; 137 | } 138 | 139 | /** 140 | * Put an actual value at the (i,j) position for both first and second curve 141 | * 142 | * @param i 143 | * index 0<=i<=calcDivisions. 144 | * @param j 145 | * index 0<=j<=calcDivisions. 146 | * @param v 147 | * value at that point. 148 | * @see package.class 149 | * @author eric 150 | */ 151 | public void setValue(int i, int j, float v1, float v2) { 152 | // v contains the value, and i, j the coordinate in the array 153 | float x = getX(i); 154 | float y = getY(j); 155 | int k = i * (calcDivisions + 1) + j; 156 | if (f1) { 157 | 158 | // v = compute(x,y); 159 | if (Float.isInfinite(v1)) 160 | v1 = Float.NaN; 161 | if (!Float.isNaN(v1)) { 162 | if (Float.isNaN(max1) || (v1 > max1)) 163 | max1 = v1; 164 | else if (Float.isNaN(min1) || (v1 < min1)) 165 | min1 = v1; 166 | } 167 | surfaceVertex[0][k] = new SurfaceVertex((x - xi) * xfactor - 10, (y - yi) * yfactor - 10, v1); 168 | } 169 | if (f2) { 170 | // v = (float)parser2.evaluate(); 171 | if (Float.isInfinite(v2)) 172 | v2 = Float.NaN; 173 | if (!Float.isNaN(v2)) { 174 | if (Float.isNaN(max2) || (v2 > max2)) 175 | max2 = v2; 176 | else if (Float.isNaN(min2) || (v2 < min2)) 177 | min2 = v2; 178 | } 179 | surfaceVertex[1][k] = new SurfaceVertex((x - xi) * xfactor - 10, (y - yi) * yfactor - 10, v2); 180 | } 181 | z1Min = (float) floor(min1, 2); 182 | z1Max = (float) ceil(max1, 2); 183 | z2Min = (float) floor(min2, 2); 184 | z2Max = (float) ceil(max2, 2); 185 | 186 | autoScale(); 187 | fireStateChanged(); 188 | } 189 | } 190 | 191 | private static final int INIT_CALC_DIV = 20; 192 | private static final int INIT_DISP_DIV = 20; 193 | 194 | /** 195 | * internally used to ceil values 196 | * 197 | * @param d 198 | * @param digits 199 | * @return 200 | */ 201 | public static synchronized double ceil(double d, int digits) { 202 | if (d == 0) 203 | return d; 204 | long og = (long) Math.ceil((Math.log(Math.abs(d)) / Math.log(10))); 205 | double factor = Math.pow(10, digits - og); 206 | double res = Math.ceil((d * factor)) / factor; 207 | return res; 208 | } 209 | 210 | /** 211 | * internally used to floor values 212 | * 213 | * @param d 214 | * @param digits 215 | * @return 216 | */ 217 | public static synchronized double floor(double d, int digits) { 218 | if (d == 0) 219 | return d; 220 | // computes order of magnitude 221 | long og = (long) Math.ceil((Math.log(Math.abs(d)) / Math.log(10))); 222 | 223 | double factor = Math.pow(10, digits - og); 224 | // the matissa 225 | double res = Math.floor((d * factor)) / factor; 226 | // res contains the closed power of ten 227 | return res; 228 | } 229 | 230 | protected boolean autoScaleZ = true; 231 | 232 | /** 233 | * Determines whether to show bounding box. 234 | * 235 | * @return true if to show bounding box 236 | */ 237 | protected boolean boxed; 238 | protected int calcDivisions = INIT_CALC_DIV; 239 | protected ColorModelSet colorModel; 240 | protected int contourLines; 241 | /** 242 | * Sets data availability flag 243 | */ 244 | protected boolean dataAvailable; 245 | protected int dispDivisions = INIT_DISP_DIV; 246 | /** 247 | * Determines whether to show face grids. 248 | * 249 | * @return true if to show face grids 250 | */ 251 | protected boolean displayGrids; 252 | /** 253 | * Determines whether to show x-y ticks. 254 | * 255 | * @return true if to show x-y ticks 256 | */ 257 | protected boolean displayXY; 258 | 259 | /** 260 | * Determines whether to show z ticks. 261 | * 262 | * @return true if to show z ticks 263 | */ 264 | protected boolean displayZ; 265 | 266 | /** 267 | * Determines whether the delay regeneration checkbox is checked. 268 | * 269 | * @return true if the checkbox is checked, false otherwise 270 | */ 271 | protected boolean expectDelay = false; 272 | 273 | /** 274 | * Determines whether the first function is selected. 275 | * 276 | * @return true if the first function is checked, false otherwise 277 | */ 278 | 279 | protected boolean hasFunction1 = true; 280 | 281 | /** 282 | * Determines whether the first function is selected. 283 | * 284 | * @return true if the first function is checked, false otherwise 285 | */ 286 | protected boolean hasFunction2 = true; 287 | 288 | javax.swing.event.EventListenerList listenerList = new javax.swing.event.EventListenerList(); 289 | 290 | /** 291 | * Determines whether to show x-y mesh. 292 | * 293 | * @return true if to show x-y mesh 294 | */ 295 | protected boolean mesh; 296 | 297 | protected PlotColor plotColor; 298 | 299 | protected boolean plotFunction1 = hasFunction1; 300 | 301 | protected boolean plotFunction2 = hasFunction2; 302 | 303 | protected PlotType plotType = PlotType.SURFACE; 304 | 305 | private Projector projector; 306 | 307 | protected PropertyChangeSupport property; 308 | 309 | /** 310 | * Determines whether to scale axes and bounding box. 311 | * 312 | * @return true if to scale bounding box 313 | */ 314 | 315 | protected boolean scaleBox; 316 | 317 | protected SurfaceVertex[][] surfaceVertex; 318 | protected float xMax; 319 | 320 | protected float xMin; 321 | protected float yMax; 322 | 323 | protected float yMin; 324 | protected float z1Max;// the max computed 325 | 326 | protected float z1Min;// the min computed 327 | protected float z2Max;// the max computed 328 | 329 | protected float z2Min;// the min computed 330 | protected float zMax; 331 | 332 | protected float zMin; 333 | 334 | /** 335 | * Empty Surface Model 336 | */ 337 | public AbstractSurfaceModel() { 338 | super(); 339 | property = new SwingPropertyChangeSupport(this); 340 | setColorModel(new ColorModelSet()); 341 | } 342 | 343 | public void addChangeListener(ChangeListener ol) { 344 | listenerList.add(ChangeListener.class, ol); 345 | } 346 | 347 | public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { 348 | property.addPropertyChangeListener(listener); 349 | } 350 | 351 | public void addPropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener) { 352 | property.addPropertyChangeListener(propertyName, listener); 353 | } 354 | 355 | /** 356 | * Allocates Memory 357 | */ 358 | 359 | private SurfaceVertex[][] allocateMemory(boolean f1, boolean f2, int total) { 360 | SurfaceVertex[][] vertex = null; 361 | try { 362 | vertex = new SurfaceVertex[2][total]; 363 | if (!f1) 364 | vertex[0] = null; 365 | if (!f2) 366 | vertex[1] = null; 367 | } catch (OutOfMemoryError e) { 368 | setMessage("Not enough memory"); 369 | } catch (Exception e) { 370 | setMessage("Error: " + e.toString()); 371 | } 372 | return vertex; 373 | } 374 | 375 | /** 376 | * Autoscale based on actual values 377 | */ 378 | public void autoScale() { 379 | // compute auto scale and repaint 380 | if (!autoScaleZ) 381 | return; 382 | if (plotFunction1 && plotFunction2) { 383 | setZMin(Math.min(z1Min, z2Min)); 384 | setZMax(Math.max(z1Max, z2Max)); 385 | } else { 386 | if (plotFunction1) { 387 | setZMin(z1Min); 388 | setZMax(z1Max); 389 | } 390 | if (plotFunction2) { 391 | setZMin(z2Min); 392 | setZMax(z2Max); 393 | } 394 | } 395 | } 396 | 397 | public void exportCSV(File file) throws IOException { 398 | 399 | if (file == null) 400 | return; 401 | java.io.FileWriter w = new java.io.FileWriter(file); 402 | float stepx, stepy, x, y, v; 403 | float xi, xx, yi, yx; 404 | float min, max; 405 | boolean f1, f2; 406 | int i, j, k, total; 407 | 408 | f1 = true; 409 | f2 = true; // until no method is defined to set functions ... 410 | // image conversion 411 | 412 | int[] pixels = null; 413 | int imgwidth = 0; 414 | int imgheight = 0; 415 | 416 | try { 417 | xi = getXMin(); 418 | yi = getYMin(); 419 | xx = getXMax(); 420 | yx = getYMax(); 421 | if ((xi >= xx) || (yi >= yx)) 422 | throw new NumberFormatException(); 423 | } catch (NumberFormatException e) { 424 | setMessage("Error in ranges"); 425 | return; 426 | } 427 | 428 | calcDivisions = getCalcDivisions(); 429 | // func1calc = f1; func2calc = f2; 430 | 431 | stepx = (xx - xi) / calcDivisions; 432 | stepy = (yx - yi) / calcDivisions; 433 | 434 | total = (calcDivisions + 1) * (calcDivisions + 1); 435 | if (surfaceVertex == null) 436 | return; 437 | 438 | max = Float.NaN; 439 | min = Float.NaN; 440 | 441 | // canvas.destroyImage(); 442 | i = 0; 443 | j = 0; 444 | k = 0; 445 | x = xi; 446 | y = yi; 447 | 448 | float xfactor = 20 / (xx - xi); 449 | float yfactor = 20 / (yx - yi); 450 | 451 | w.write("X\\Y->Z;"); 452 | while (j <= calcDivisions) { 453 | 454 | w.write(Float.toString(y)); 455 | if (j != calcDivisions) 456 | w.write(';'); 457 | j++; 458 | y += stepy; 459 | k++; 460 | } 461 | w.write("\n"); 462 | // first line written 463 | i = 0; 464 | j = 0; 465 | k = 0; 466 | x = xi; 467 | y = yi; 468 | 469 | while (i <= calcDivisions) { 470 | w.write(Float.toString(x)); 471 | w.write(';'); 472 | while (j <= calcDivisions) { 473 | w.write(Float.toString(surfaceVertex[0][k].z)); 474 | if (j != calcDivisions) 475 | w.write(';'); 476 | j++; 477 | y += stepy; 478 | k++; 479 | // setMessage("Calculating : " + k*100/total + "% completed"); 480 | } 481 | w.write('\n'); 482 | // first line written 483 | j = 0; 484 | y = yi; 485 | i++; 486 | x += stepx; 487 | } 488 | w.flush(); 489 | w.close(); 490 | 491 | } 492 | 493 | private void fireAllFunction(boolean oldHas1, boolean oldHas2) { 494 | property.firePropertyChange("firstFunctionOnly", (!oldHas2) && oldHas1, (!plotFunction2) && plotFunction1); 495 | property.firePropertyChange("secondFunctionOnly", (!oldHas1) && oldHas2, (!plotFunction1) && plotFunction2); 496 | property.firePropertyChange("bothFunction", oldHas1 && oldHas2, plotFunction1 && plotFunction2); 497 | autoScale(); 498 | 499 | } 500 | 501 | private void fireAllMode(PlotColor oldValue, PlotColor newValue) { 502 | for (PlotColor c : PlotColor.values()) 503 | property.firePropertyChange(c.getPropertyName(), oldValue == c, newValue == c); 504 | } 505 | 506 | private void fireAllType(PlotType oldValue, PlotType newValue) { 507 | for (PlotType c : PlotType.values()) 508 | property.firePropertyChange(c.getPropertyName(), oldValue == c, newValue == c); 509 | } 510 | 511 | protected void fireStateChanged() { 512 | // Guaranteed to return a non-null array 513 | Object[] listeners = listenerList.getListenerList(); 514 | // Process the listeners last to first, notifying 515 | // those that are interested in this event 516 | ChangeEvent e = null; 517 | for (int i = listeners.length - 2; i >= 0; i -= 2) { 518 | if (listeners[i] == ChangeListener.class) { 519 | // Lazily create the event: 520 | if (e == null) 521 | e = new ChangeEvent(this); 522 | ((ChangeListener) listeners[i + 1]).stateChanged(e); 523 | } 524 | } 525 | } 526 | 527 | public int getCalcDivisions() { 528 | return calcDivisions; 529 | } 530 | 531 | public SurfaceColor getColorModel() { 532 | return colorModel; 533 | } 534 | 535 | public int getContourLines() { 536 | return contourLines; 537 | } 538 | 539 | public int getDispDivisions() { 540 | if (dispDivisions > calcDivisions) 541 | dispDivisions = calcDivisions; 542 | while ((calcDivisions % dispDivisions) != 0) 543 | dispDivisions++; 544 | return dispDivisions; 545 | } 546 | 547 | public PlotColor getPlotColor() { 548 | return plotColor; 549 | } 550 | 551 | public PlotType getPlotType() { 552 | return plotType; 553 | } 554 | 555 | public Projector getProjector() { 556 | if (projector == null) { 557 | projector = new Projector(); 558 | projector.setDistance(70); 559 | projector.set2DScaling(15); 560 | projector.setRotationAngle(125); 561 | projector.setElevationAngle(10); 562 | } 563 | return projector; 564 | } 565 | 566 | public PropertyChangeSupport getPropertyChangeSupport() { 567 | if (property == null) 568 | property = new SwingPropertyChangeSupport(this); 569 | return property; 570 | } 571 | 572 | public SurfaceVertex[][] getSurfaceVertex() { 573 | return surfaceVertex; 574 | } 575 | 576 | public float getXMax() { 577 | return xMax; 578 | } 579 | 580 | public float getXMin() { 581 | return xMin; 582 | } 583 | 584 | public float getYMax() { 585 | return yMax; 586 | } 587 | 588 | public float getYMin() { 589 | return yMin; 590 | } 591 | 592 | public float getZMax() { 593 | return zMax; 594 | } 595 | 596 | public float getZMin() { 597 | return zMin; 598 | } 599 | 600 | public boolean isAutoScaleZ() { 601 | return autoScaleZ; 602 | } 603 | 604 | public boolean isBothFunction() { 605 | return plotFunction1 && plotFunction2; 606 | } 607 | 608 | public boolean isBoxed() { 609 | return boxed; 610 | } 611 | 612 | public boolean isContourType() { 613 | return plotType == PlotType.CONTOUR; 614 | } 615 | 616 | public boolean isDataAvailable() { 617 | return dataAvailable; 618 | } 619 | 620 | public boolean isDensityType() { 621 | return plotType == PlotType.DENSITY; 622 | } 623 | 624 | public boolean isDisplayGrids() { 625 | return displayGrids; 626 | } 627 | 628 | public boolean isDisplayXY() { 629 | return displayXY; 630 | } 631 | 632 | public boolean isDisplayZ() { 633 | return displayZ; 634 | } 635 | 636 | public boolean isDualShadeMode() { 637 | return plotColor == PlotColor.DUALSHADE; 638 | } 639 | 640 | public boolean isExpectDelay() { 641 | return expectDelay; 642 | } 643 | 644 | public boolean isFirstFunctionOnly() { 645 | return plotFunction1 && !plotFunction2; 646 | } 647 | 648 | public boolean isFogMode() { 649 | return plotColor == PlotColor.FOG; 650 | } 651 | 652 | public boolean isGrayScaleMode() { 653 | return plotColor == PlotColor.GRAYSCALE; 654 | } 655 | 656 | public boolean isHiddenMode() { 657 | return plotColor == PlotColor.OPAQUE; 658 | } 659 | 660 | public boolean isMesh() { 661 | return mesh; 662 | } 663 | 664 | public boolean isPlotFunction1() { 665 | return plotFunction1; 666 | } 667 | 668 | public boolean isPlotFunction2() { 669 | return plotFunction2; 670 | } 671 | 672 | public boolean isScaleBox() { 673 | return scaleBox; 674 | } 675 | 676 | public boolean isSecondFunctionOnly() { 677 | return (!plotFunction1) && plotFunction2; 678 | } 679 | 680 | public boolean isSpectrumMode() { 681 | return plotColor == PlotColor.SPECTRUM; 682 | } 683 | 684 | public boolean isSurfaceType() { 685 | return plotType == PlotType.SURFACE; 686 | } 687 | 688 | public boolean isWireframeType() { 689 | return plotType == PlotType.WIREFRAME; 690 | } 691 | 692 | /** 693 | * factory to get a plotter, i.e. the best way to append data to this surface model 694 | * 695 | * @param calcDivisions 696 | * @return 697 | */ 698 | public Plotter newPlotter(int calcDivisions) { 699 | setCalcDivisions(calcDivisions); 700 | return new PlotterImpl(); 701 | } 702 | 703 | public void removeChangeListener(ChangeListener ol) { 704 | listenerList.remove(ChangeListener.class, ol); 705 | } 706 | 707 | public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { 708 | property.removePropertyChangeListener(listener); 709 | } 710 | 711 | public void removePropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener) { 712 | property.removePropertyChangeListener(propertyName, listener); 713 | } 714 | 715 | /** 716 | * Called when automatic rotation stops 717 | */ 718 | 719 | public void rotationStops() { 720 | 721 | // setting_panel.rotationStops(); 722 | } 723 | 724 | public void setAutoScaleZ(boolean autoScaleZ) { 725 | getPropertyChangeSupport().firePropertyChange("this.autoScaleZ", this.autoScaleZ, this.autoScaleZ = autoScaleZ); 726 | autoScale(); 727 | } 728 | 729 | public void setBothFunction(boolean val) { 730 | setPlotFunction12(val, val); 731 | } 732 | 733 | public void setBoxed(boolean boxed) { 734 | getPropertyChangeSupport().firePropertyChange("boxed", this.boxed, this.boxed = boxed); 735 | } 736 | 737 | protected void setColorModel(ColorModelSet colorModel) { 738 | getPropertyChangeSupport().firePropertyChange("colorModel", this.colorModel, this.colorModel = colorModel); 739 | if (colorModel != null) { 740 | colorModel.setPlotColor(plotColor); // this shouls be handled by the model itself, without any 741 | colorModel.setPlotType(plotType); 742 | } 743 | } 744 | 745 | public void setContourLines(int contourLines) { 746 | getPropertyChangeSupport().firePropertyChange("contourLines", this.contourLines, this.contourLines = contourLines); 747 | } 748 | 749 | public void setContourType(boolean val) { 750 | setPlotType(val ? PlotType.CONTOUR : PlotType.SURFACE); 751 | } 752 | 753 | public void setDataAvailable(boolean dataAvailable) { 754 | getPropertyChangeSupport().firePropertyChange("dataAvailable", this.dataAvailable, this.dataAvailable = dataAvailable); 755 | } 756 | 757 | public void setDensityType(boolean val) { 758 | setPlotType(val ? PlotType.DENSITY : PlotType.SURFACE); 759 | } 760 | 761 | public void setDispDivisions(int dispDivisions) { 762 | getPropertyChangeSupport().firePropertyChange("dispDivisions", this.dispDivisions, this.dispDivisions = dispDivisions); 763 | } 764 | 765 | public void setDualShadeMode(boolean val) { 766 | setPlotColor(val ? PlotColor.DUALSHADE : PlotColor.SPECTRUM); 767 | } 768 | 769 | public void setFirstFunctionOnly(boolean val) { 770 | setPlotFunction12(val, !val); 771 | } 772 | 773 | public void setFogMode(boolean val) { 774 | setPlotColor(val ? PlotColor.FOG : PlotColor.SPECTRUM); 775 | } 776 | 777 | public void setGrayScaleMode(boolean val) { 778 | setPlotColor(val ? PlotColor.GRAYSCALE : PlotColor.SPECTRUM); 779 | } 780 | 781 | public void setHiddenMode(boolean val) { 782 | setPlotColor(val ? PlotColor.OPAQUE : PlotColor.SPECTRUM); 783 | } 784 | 785 | /** 786 | * Sets the text of status line 787 | * 788 | * @param text 789 | * new text to be displayed 790 | */ 791 | 792 | public void setMessage(String text) { 793 | // @todo 794 | // System.out.println("Message"+text); 795 | } 796 | 797 | public void setPlotFunction1(boolean plotFunction1) { 798 | setPlotFunction12(plotFunction1, plotFunction2); 799 | } 800 | 801 | public void setPlotColor(PlotColor plotColor) { 802 | PlotColor old = this.plotColor; 803 | getPropertyChangeSupport().firePropertyChange("plotColor", this.plotColor, this.plotColor = plotColor); 804 | fireAllMode(old, this.plotColor); 805 | if (colorModel != null) 806 | colorModel.setPlotColor(plotColor); // this should be handled by the model itself, without any 807 | } 808 | 809 | public void setPlotFunction12(boolean p1, boolean p2) { 810 | boolean o1 = this.plotFunction1; 811 | boolean o2 = this.plotFunction2; 812 | 813 | this.plotFunction1 = hasFunction1 && p1; 814 | property.firePropertyChange("plotFunction1", o1, p1); 815 | 816 | this.plotFunction2 = hasFunction2 && p2; 817 | property.firePropertyChange("plotFunction1", o2, p2); 818 | fireAllFunction(o1, o2); 819 | } 820 | 821 | public void setPlotFunction2(boolean v) { 822 | setPlotFunction12(plotFunction1, plotFunction2); 823 | } 824 | 825 | public void setPlotType(PlotType plotType) { 826 | PlotType o = this.plotType; 827 | this.plotType = plotType; 828 | if (colorModel != null) 829 | colorModel.setPlotType(plotType); // this should be handled by the model itself, without any 830 | property.firePropertyChange("plotType", o, this.plotType); 831 | fireAllType(o, this.plotType); 832 | } 833 | 834 | public void setSecondFunctionOnly(boolean val) { 835 | setPlotFunction12(!val, val); 836 | } 837 | 838 | public void setSpectrumMode(boolean val) { 839 | setPlotColor(val ? PlotColor.SPECTRUM : PlotColor.GRAYSCALE); 840 | } 841 | 842 | public void setSurfaceType(boolean val) { 843 | setPlotType(val ? PlotType.SURFACE : PlotType.WIREFRAME); 844 | } 845 | 846 | public void setSurfaceVertex(SurfaceVertex[][] surfaceVertex) { 847 | getPropertyChangeSupport().firePropertyChange("surfaceVertex", this.surfaceVertex, this.surfaceVertex = surfaceVertex); 848 | } 849 | 850 | public void setWireframeType(boolean val) { 851 | if (val) 852 | setPlotType(PlotType.WIREFRAME); 853 | else 854 | setPlotType(PlotType.SURFACE); 855 | } 856 | 857 | public void setXMax(float xMax) { 858 | getPropertyChangeSupport().firePropertyChange("xMax", this.xMax, this.xMax = xMax); 859 | } 860 | 861 | public void setXMin(float xMin) { 862 | getPropertyChangeSupport().firePropertyChange("xMin", this.xMin, this.xMin = xMin); 863 | } 864 | 865 | public void setYMax(float yMax) { 866 | getPropertyChangeSupport().firePropertyChange("yMax", this.yMax, this.yMax = yMax); 867 | } 868 | 869 | public void setYMin(float yMin) { 870 | getPropertyChangeSupport().firePropertyChange("yMin", this.yMin, this.yMin = yMin); 871 | } 872 | 873 | public void setZMax(float zMax) { 874 | if (zMax <= zMin) 875 | return; 876 | getPropertyChangeSupport().firePropertyChange("zMax", this.zMax, this.zMax = zMax); 877 | } 878 | 879 | public void setZMin(float zMin) { 880 | if (zMin >= zMax) 881 | return; 882 | getPropertyChangeSupport().firePropertyChange("zMin", this.zMin, this.zMin = zMin); 883 | } 884 | 885 | public void setDisplayGrids(boolean displayGrids) { 886 | getPropertyChangeSupport().firePropertyChange("displayGrids", this.displayGrids, this.displayGrids = displayGrids); 887 | } 888 | 889 | public void setDisplayXY(boolean displayXY) { 890 | getPropertyChangeSupport().firePropertyChange("displayXY", this.displayXY, this.displayXY = displayXY); 891 | } 892 | 893 | public void setDisplayZ(boolean displayZ) { 894 | getPropertyChangeSupport().firePropertyChange("displayZ", this.displayZ, this.displayZ = displayZ); 895 | } 896 | 897 | public void setExpectDelay(boolean expectDelay) { 898 | getPropertyChangeSupport().firePropertyChange("expectDelay", this.expectDelay, this.expectDelay = expectDelay); 899 | } 900 | 901 | public void setMesh(boolean mesh) { 902 | getPropertyChangeSupport().firePropertyChange("mesh", this.mesh, this.mesh = mesh); 903 | } 904 | 905 | public void setScaleBox(boolean scaleBox) { 906 | getPropertyChangeSupport().firePropertyChange("scaleBox", this.scaleBox, this.scaleBox = scaleBox); 907 | } 908 | 909 | public void toggleAutoScaleZ() { 910 | setAutoScaleZ(!isAutoScaleZ()); 911 | } 912 | 913 | public void toggleBoxed() { 914 | setBoxed(!isBoxed()); 915 | } 916 | 917 | 918 | 919 | public void setCalcDivisions(int calcDivisions) { 920 | getPropertyChangeSupport().firePropertyChange("calcDivisions", this.calcDivisions, this.calcDivisions = calcDivisions); 921 | } 922 | 923 | /** 924 | * Processes menu events 925 | * 926 | * @param item 927 | * the selected menu item 928 | */ 929 | 930 | public void toggleDisplayGrids() { 931 | setDisplayGrids(!isDisplayGrids()); 932 | } 933 | 934 | /** 935 | * Sets file name 936 | */ 937 | 938 | public void toggleDisplayXY() { 939 | setDisplayXY(!isDisplayXY()); 940 | } 941 | 942 | public void toggleDisplayZ() { 943 | setDisplayZ(!isDisplayZ()); 944 | } 945 | 946 | public void toggleExpectDelay() { 947 | setExpectDelay(!isExpectDelay()); 948 | } 949 | 950 | public void toggleMesh() { 951 | setMesh(!isMesh()); 952 | } 953 | 954 | public void togglePlotFunction1() { 955 | setPlotFunction1(!isPlotFunction1()); 956 | 957 | } 958 | 959 | public void togglePlotFunction2() { 960 | setPlotFunction2(!isPlotFunction2()); 961 | 962 | } 963 | 964 | public void toggleScaleBox() { 965 | setScaleBox(!isScaleBox()); 966 | } 967 | 968 | }// end of class 969 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/DefaultSurfaceModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | import javax.swing.SwingWorker; 7 | 8 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 9 | import net.ericaro.surfaceplotter.surface.SurfaceModel; 10 | import net.ericaro.surfaceplotter.surface.SurfaceVertex; 11 | 12 | 13 | /** 14 | * {@link DefaultSurfaceModel} provides a simple way to fill the {@link AbstractSurfaceModel} using the Plotter interface. 15 | */ 16 | public class DefaultSurfaceModel extends AbstractSurfaceModel implements SurfaceModel { 17 | 18 | 19 | 20 | private Mapper mapper; 21 | protected SurfaceVertex[][] surfaceVertex; 22 | /** 23 | * Empty Surface Model 24 | */ 25 | public DefaultSurfaceModel() { 26 | super(); 27 | } 28 | 29 | 30 | public SwingWorker plot() { 31 | if ((xMin >= xMax) || (yMin >= yMax)) 32 | throw new NumberFormatException(); 33 | setDataAvailable(false); // clean space 34 | // reads the calcDivision that will be used 35 | final float stepx = (xMax - xMin) / calcDivisions; 36 | final float stepy = (yMax - yMin) / calcDivisions; 37 | final float xfactor = 20 / (xMax - xMin); // 20 aint magic: surface vertex requires a value in [-10 ; 10] 38 | final float yfactor = 20 / (yMax - yMin); 39 | 40 | final int total = (calcDivisions + 1) * (calcDivisions + 1); // compute total size 41 | surfaceVertex = allocateMemory(hasFunction1,hasFunction2, total); // allocate surfaceVertex 42 | 43 | // fill the surface surfaceVertex with NaN 44 | for (int i = 0; i <= calcDivisions; i++) 45 | for (int j = 0; j <= calcDivisions; j++) { 46 | int k = i * (calcDivisions + 1) + j; 47 | 48 | float x = xMin + i * stepx; 49 | float y = yMin + j * stepy; 50 | if (hasFunction1) 51 | surfaceVertex[0][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, Float.NaN); 52 | if (hasFunction2) 53 | surfaceVertex[1][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, Float.NaN); 54 | } 55 | 56 | 57 | setSurfaceVertex(surfaceVertex); // define as the current surfaceVertex 58 | setDataAvailable(true); // cause the JSurface to display an empty plot 59 | 60 | getProjector(); 61 | 62 | 63 | return new SwingWorker(){ 64 | 65 | @Override 66 | protected Void doInBackground() throws Exception { 67 | // fill the surface surfaceVertex with NaN 68 | setProgress(0); 69 | setProgress(1) ; 70 | for (int i = 0; i <= calcDivisions; i++) 71 | for (int j = 0; j <= calcDivisions; j++) { 72 | int k = i * (calcDivisions + 1) + j; 73 | 74 | float x = xMin + i * stepx; 75 | float y = yMin + j * stepy; 76 | if (hasFunction1) { 77 | float v1 = mapper.f1(x,y); 78 | if (Float.isInfinite(v1)) 79 | v1 = Float.NaN; 80 | if (!Float.isNaN(v1)) { 81 | if (Float.isNaN(z1Max) || (v1 > z1Max)) 82 | z1Max = v1; 83 | else if (Float.isNaN(z1Min) || (v1 < z1Min)) 84 | z1Min = v1; 85 | } 86 | 87 | surfaceVertex[0][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, v1); 88 | } 89 | if (hasFunction2) { 90 | float v2 = mapper.f2(x, y); 91 | if (Float.isInfinite(v2)) 92 | v2 = Float.NaN; 93 | if (!Float.isNaN(v2)) { 94 | if (Float.isNaN(z2Max) || (v2 > z2Max)) 95 | z2Max = v2; 96 | else if (Float.isNaN(z2Min) || (v2 < z2Min)) 97 | z2Min = v2; 98 | } 99 | 100 | surfaceVertex[1][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, v2); 101 | } 102 | publish(); 103 | setProgress((100*k)/total); 104 | } 105 | setProgress(100); 106 | return null; 107 | } 108 | 109 | @Override 110 | protected void done() { 111 | try { 112 | get(); 113 | } catch (InterruptedException e) { 114 | e.printStackTrace(); 115 | } catch (ExecutionException e) { 116 | e.printStackTrace(); 117 | } 118 | z1Min = (float) floor(z1Min, 2); 119 | z1Max = (float) ceil(z1Max, 2); 120 | z2Min = (float) floor(z2Min, 2); 121 | z2Max = (float) ceil(z2Max, 2); 122 | 123 | autoScale(); 124 | fireStateChanged(); 125 | } 126 | 127 | @Override 128 | protected void process(List chunks) { 129 | fireStateChanged(); 130 | } 131 | 132 | }; 133 | 134 | 135 | 136 | } 137 | 138 | 139 | /** 140 | * Allocates Memory 141 | */ 142 | 143 | private SurfaceVertex[][] allocateMemory(boolean f1, boolean f2, int total) { 144 | SurfaceVertex[][] vertex = null; 145 | try { 146 | vertex = new SurfaceVertex[2][total]; 147 | if (!f1) 148 | vertex[0] = null; 149 | if (!f2) 150 | vertex[1] = null; 151 | } catch (OutOfMemoryError e) { 152 | setMessage("Not enough memory"); 153 | } catch (Exception e) { 154 | setMessage("Error: " + e.toString()); 155 | } 156 | return vertex; 157 | } 158 | 159 | 160 | 161 | 162 | public Mapper getMapper() { 163 | return mapper; 164 | } 165 | 166 | 167 | public void setMapper(Mapper mapper) { 168 | getPropertyChangeSupport().firePropertyChange("mapper", this.mapper, this.mapper = mapper); 169 | } 170 | 171 | 172 | public SurfaceVertex[][] getSurfaceVertex() { 173 | return surfaceVertex; 174 | } 175 | 176 | protected void setSurfaceVertex(SurfaceVertex[][] surfaceVertex) { 177 | getPropertyChangeSupport().firePropertyChange("surfaceVertex", this.surfaceVertex, this.surfaceVertex = surfaceVertex); 178 | } 179 | }// end of class 180 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/JSurfaceApplet.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Color; 5 | import java.awt.Font; 6 | 7 | import javax.swing.JApplet; 8 | 9 | public class JSurfaceApplet extends JApplet { 10 | 11 | 12 | 13 | @Override 14 | public void init() { 15 | //initComponents(); 16 | try { 17 | 18 | javax.swing.SwingUtilities.invokeAndWait(new Runnable() { 19 | public void run() { 20 | initComponents(); 21 | } 22 | }); 23 | } catch (Exception e) { 24 | System.err.println("createGUI didn't successfully complete"+ e); 25 | e.printStackTrace(); 26 | } 27 | } 28 | 29 | private void initComponents() { 30 | surfacePanel1 = new JSurfacePanel(); 31 | 32 | //======== this ======== 33 | setLayout(new BorderLayout()); 34 | 35 | //---- surfacePanel1 ---- 36 | surfacePanel1.setTitleText("Demo Applet"); 37 | surfacePanel1.setBackground(Color.white); 38 | surfacePanel1.setTitleFont(surfacePanel1.getTitleFont().deriveFont(surfacePanel1.getTitleFont().getStyle() | Font.BOLD, surfacePanel1.getTitleFont().getSize() + 6f)); 39 | surfacePanel1.setConfigurationVisible(false); 40 | add(surfacePanel1, BorderLayout.CENTER); 41 | 42 | } 43 | 44 | private JSurfacePanel surfacePanel1; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/JSurfacePanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Tue May 17 09:54:22 CEST 2011 3 | */ 4 | 5 | package net.ericaro.surfaceplotter; 6 | 7 | import java.awt.BorderLayout; 8 | import java.awt.Color; 9 | import java.awt.Font; 10 | import java.awt.GridBagConstraints; 11 | import java.awt.GridBagLayout; 12 | import java.awt.Insets; 13 | import java.awt.event.ActionEvent; 14 | import java.awt.event.KeyEvent; 15 | import java.awt.event.MouseAdapter; 16 | import java.awt.event.MouseEvent; 17 | import java.util.ResourceBundle; 18 | 19 | import javax.swing.AbstractAction; 20 | import javax.swing.Action; 21 | import javax.swing.Icon; 22 | import javax.swing.JLabel; 23 | import javax.swing.JPanel; 24 | import javax.swing.KeyStroke; 25 | import javax.swing.SwingConstants; 26 | 27 | import net.ericaro.surfaceplotter.beans.JGridBagScrollPane; 28 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 29 | import net.ericaro.surfaceplotter.surface.JSurface; 30 | import net.ericaro.surfaceplotter.surface.SurfaceModel; 31 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotColor; 32 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotType; 33 | import net.ericaro.surfaceplotter.surface.VerticalConfigurationPanel; 34 | 35 | 36 | /** Main panel to display a surface plot. 37 | * 38 | * @author eric 39 | */ 40 | public class JSurfacePanel extends JPanel { 41 | 42 | 43 | public JSurfacePanel() { 44 | this(createDefaultSurfaceModel()); 45 | } 46 | 47 | 48 | /** 49 | * @return 50 | */ 51 | private static SurfaceModel createDefaultSurfaceModel() { 52 | final DefaultSurfaceModel sm = new DefaultSurfaceModel(); 53 | 54 | sm.setPlotFunction2(false); 55 | 56 | sm.setCalcDivisions(50); 57 | sm.setDispDivisions(50); 58 | sm.setContourLines(10); 59 | 60 | sm.setXMin(-3); 61 | sm.setXMax(3); 62 | sm.setYMin(-3); 63 | sm.setYMax(3); 64 | 65 | sm.setBoxed(false); 66 | sm.setDisplayXY(false); 67 | sm.setExpectDelay(false); 68 | sm.setAutoScaleZ(true); 69 | sm.setDisplayZ(false); 70 | sm.setMesh(false); 71 | sm.setPlotType(PlotType.SURFACE); 72 | sm.setFirstFunctionOnly(true); 73 | //sm.setPlotType(PlotType.WIREFRAME); 74 | //sm.setPlotType(PlotType.CONTOUR); 75 | //sm.setPlotType(PlotType.DENSITY); 76 | 77 | sm.setPlotColor(PlotColor.SPECTRUM); 78 | //sm.setPlotColor(PlotColor.DUALSHADE); 79 | //sm.setPlotColor(PlotColor.FOG); 80 | //sm.setPlotColor(PlotColor.OPAQUE); 81 | sm.setMapper(new Mapper() { 82 | public float f1( float x, float y) 83 | { 84 | float r = x*x+y*y; 85 | 86 | if (r == 0 ) return 1f; 87 | return (float)( Math.sin(r)/(r)); 88 | } 89 | 90 | public float f2( float x, float y) 91 | { 92 | return (float)(Math.sin(x*y)); 93 | } 94 | }); 95 | sm.plot().execute(); 96 | return sm; 97 | 98 | } 99 | 100 | public JSurfacePanel(SurfaceModel model) { 101 | super(new BorderLayout()); 102 | initComponents(); 103 | 104 | String name = (String) configurationToggler.getValue(Action.NAME); 105 | getActionMap().put(name, configurationToggler); 106 | getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), name); 107 | 108 | setModel(model); 109 | 110 | } 111 | 112 | 113 | 114 | public void setModel(SurfaceModel model) { 115 | if (model instanceof AbstractSurfaceModel) 116 | configurationPanel.setModel((AbstractSurfaceModel) model); 117 | else { 118 | scrollpane.setVisible(false); 119 | configurationPanel.setModel(null); 120 | } 121 | surface.setModel(model); 122 | } 123 | 124 | /** 125 | * @return 126 | * @see java.awt.Component#getFont() 127 | */ 128 | public Font getTitleFont() { 129 | return title.getFont(); 130 | } 131 | 132 | /** 133 | * @return 134 | * @see javax.swing.JLabel#getIcon() 135 | */ 136 | public Icon getTitleIcon() { 137 | return title.getIcon(); 138 | } 139 | 140 | /** 141 | * @return 142 | * @see javax.swing.JLabel#getText() 143 | */ 144 | public String getTitleText() { 145 | return title.getText(); 146 | } 147 | 148 | /** 149 | * @return 150 | * @see java.awt.Component#isVisible() 151 | */ 152 | public boolean isTitleVisible() { 153 | return title.isVisible(); 154 | } 155 | 156 | /** 157 | * @param font 158 | * @see javax.swing.JComponent#setFont(java.awt.Font) 159 | */ 160 | public void setTitleFont(Font font) { 161 | title.setFont(font); 162 | } 163 | 164 | /** 165 | * @param icon 166 | * @see javax.swing.JLabel#setIcon(javax.swing.Icon) 167 | */ 168 | public void setTitleIcon(Icon icon) { 169 | title.setIcon(icon); 170 | } 171 | 172 | /** 173 | * @param text 174 | * @see javax.swing.JLabel#setText(java.lang.String) 175 | */ 176 | public void setTitleText(String text) { 177 | title.setText(text); 178 | } 179 | 180 | /** 181 | * @param aFlag 182 | * @see javax.swing.JComponent#setVisible(boolean) 183 | */ 184 | public void setTitleVisible(boolean aFlag) { 185 | title.setVisible(aFlag); 186 | } 187 | 188 | /** 189 | * @return 190 | * @see java.awt.Component#isVisible() 191 | */ 192 | public boolean isConfigurationVisible() { 193 | return scrollpane.isVisible(); 194 | } 195 | 196 | /** 197 | * @param aFlag 198 | * @see javax.swing.JComponent#setVisible(boolean) 199 | */ 200 | public void setConfigurationVisible(boolean aFlag) { 201 | scrollpane.setVisible(aFlag); 202 | invalidate(); 203 | revalidate(); 204 | } 205 | 206 | 207 | private void toggleConfiguration() { 208 | setConfigurationVisible(!isConfigurationVisible()); 209 | if ( !isConfigurationVisible()) 210 | surface.requestFocusInWindow(); 211 | } 212 | 213 | public JSurface getSurface() { 214 | return surface; 215 | } 216 | 217 | private void mousePressed() { 218 | surface.requestFocusInWindow(); 219 | } 220 | 221 | private void surfaceMouseClicked(MouseEvent e) { 222 | if (e.getClickCount()>=2) 223 | toggleConfiguration(); 224 | } 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | private void initComponents() { 233 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 234 | ResourceBundle bundle = ResourceBundle.getBundle("net.ericaro.surfaceplotter.JSurfacePanel"); 235 | title = new JLabel(); 236 | surface = new JSurface(); 237 | scrollpane = new JGridBagScrollPane(); 238 | configurationPanel = new VerticalConfigurationPanel(); 239 | configurationToggler = new AbstractAction(){public void actionPerformed(ActionEvent e){toggleConfiguration();}}; 240 | 241 | //======== this ======== 242 | setName("this"); 243 | setLayout(new GridBagLayout()); 244 | ((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0}; 245 | ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0, 0}; 246 | ((GridBagLayout)getLayout()).columnWeights = new double[] {1.0, 0.0, 1.0E-4}; 247 | ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0, 1.0E-4}; 248 | 249 | //---- title ---- 250 | title.setText(bundle.getString("title.text")); 251 | title.setHorizontalTextPosition(SwingConstants.CENTER); 252 | title.setHorizontalAlignment(SwingConstants.CENTER); 253 | title.setBackground(Color.white); 254 | title.setOpaque(true); 255 | title.setFont(title.getFont().deriveFont(title.getFont().getSize() + 4f)); 256 | title.setName("title"); 257 | add(title, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 258 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 259 | new Insets(0, 0, 0, 0), 0, 0)); 260 | 261 | //---- surface ---- 262 | surface.setToolTipText(bundle.getString("surface.toolTipText")); 263 | surface.setInheritsPopupMenu(true); 264 | surface.setName("surface"); 265 | surface.addMouseListener(new MouseAdapter() { 266 | @Override 267 | public void mouseClicked(MouseEvent e) { 268 | surfaceMouseClicked(e); 269 | } 270 | @Override 271 | public void mousePressed(MouseEvent e) { 272 | JSurfacePanel.this.mousePressed(); 273 | } 274 | }); 275 | add(surface, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 276 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 277 | new Insets(0, 0, 0, 0), 0, 0)); 278 | 279 | //======== scrollpane ======== 280 | { 281 | scrollpane.setWidthFixed(true); 282 | scrollpane.setName("scrollpane"); 283 | 284 | //---- configurationPanel ---- 285 | configurationPanel.setNextFocusableComponent(this); 286 | configurationPanel.setName("configurationPanel"); 287 | scrollpane.setViewportView(configurationPanel); 288 | } 289 | add(scrollpane, new GridBagConstraints(1, 0, 1, 2, 0.0, 0.0, 290 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 291 | new Insets(0, 0, 0, 0), 0, 0)); 292 | 293 | //---- configurationToggler ---- 294 | configurationToggler.putValue(Action.NAME, bundle.getString("configurationToggler.Name")); 295 | // JFormDesigner - End of component initialization //GEN-END:initComponents 296 | } 297 | 298 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 299 | private JLabel title; 300 | private JSurface surface; 301 | private JGridBagScrollPane scrollpane; 302 | private VerticalConfigurationPanel configurationPanel; 303 | private AbstractAction configurationToggler; 304 | // JFormDesigner - End of variables declaration //GEN-END:variables 305 | 306 | } 307 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/JSurfacePanel.jfd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | i18n.autoExternalize 6 | true 7 | 8 | 9 | i18n.bundlePackage 10 | net.ericaro.surfaceplotter 11 | 12 | 13 | i18n.bundleName 14 | JSurfacePanel 15 | 16 | 17 | form/swing 18 | 19 | 20 | 21 | 22 | 23 | javax.swing.JPanel 24 | 25 | java.awt.GridBagLayout 26 | 27 | $columnSpecs 28 | 0:1.0, 0 29 | 30 | 31 | $rowSpecs 32 | 0, 0:1.0 33 | 34 | 35 | $alignLeft 36 | true 37 | 38 | 39 | $alignTop 40 | true 41 | 42 | 43 | 44 | this 45 | 46 | 47 | 48 | javax.swing.JLabel 49 | 50 | text 51 | 52 | 53 | title.text 54 | 55 | 56 | 57 | horizontalTextPosition 58 | 0 59 | 60 | 61 | horizontalAlignment 62 | 0 63 | 64 | 65 | background 66 | 67 | 255 68 | 255 69 | 255 70 | 255 71 | 72 | 73 | 74 | opaque 75 | true 76 | 77 | 78 | font 79 | 80 | 81 | 0 82 | 4 83 | false 84 | 85 | 86 | 87 | title 88 | 89 | 90 | 91 | com.jformdesigner.runtime.GridBagConstraintsEx 92 | 93 | 94 | 95 | 96 | net.ericaro.surfaceplotter.surface.JSurface 97 | 98 | toolTipText 99 | 100 | 101 | surface.toolTipText 102 | 103 | 104 | 105 | inheritsPopupMenu 106 | true 107 | 108 | 109 | surface 110 | 111 | 112 | 113 | JavaCodeGenerator.variableGetter 114 | true 115 | 116 | 117 | 118 | 119 | java.awt.event.MouseListener 120 | mousePressed 121 | mousePressed 122 | false 123 | 124 | 125 | 126 | 127 | java.awt.event.MouseListener 128 | mouseClicked 129 | surfaceMouseClicked 130 | true 131 | 132 | 133 | 134 | 135 | com.jformdesigner.runtime.GridBagConstraintsEx 136 | 137 | gridy 138 | 1 139 | 140 | 141 | 142 | 143 | 144 | net.ericaro.surfaceplotter.beans.JGridBagScrollPane 145 | 146 | javax.swing.JScrollPane 147 | 148 | 149 | widthFixed 150 | true 151 | 152 | 153 | scrollpane 154 | 155 | 156 | 157 | net.ericaro.surfaceplotter.surface.VerticalConfigurationPanel 158 | 159 | nextFocusableComponent 160 | 161 | this 162 | 163 | 164 | 165 | configurationPanel 166 | 167 | 168 | 169 | 170 | 171 | com.jformdesigner.runtime.GridBagConstraintsEx 172 | 173 | gridx 174 | 1 175 | 176 | 177 | gridheight 178 | 2 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | location 187 | 188 | 0 189 | 0 190 | 191 | 192 | 193 | size 194 | 195 | 620 196 | 705 197 | 198 | 199 | 200 | 201 | 202 | 203 | javax.swing.AbstractAction 204 | 205 | $action.Name 206 | 207 | 208 | configurationToggler.Name 209 | 210 | 211 | 212 | 213 | JavaCodeGenerator.customCreateCode 214 | new AbstractAction(){public void actionPerformed(ActionEvent e){toggleConfiguration();}}; 215 | 216 | 217 | 218 | configurationToggler 219 | 220 | 221 | 222 | 223 | 224 | location 225 | 226 | 640 227 | 135 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/Mapper.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter; 2 | 3 | /** 4 | * Implements a Mapper to pass to a plotter. 5 | * 6 | * @author eric 7 | */ 8 | public interface Mapper { 9 | 10 | public float f1(float x, float y); 11 | 12 | public float f2(float x, float y); 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/ProgressiveSurfaceModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter; 2 | 3 | import java.util.List; 4 | 5 | import javax.swing.SwingWorker; 6 | 7 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 8 | import net.ericaro.surfaceplotter.surface.SurfaceModel; 9 | import net.ericaro.surfaceplotter.surface.SurfaceVertex; 10 | 11 | /** 12 | * {@link ProgressiveSurfaceModel} fills the surface with increasing "definition". 13 | *

14 | * It allocate an HD array , and start with a single face, then 4, then 16 etc. until reaching the goal HD definition. 15 | *

16 | * This defines the 17 | * 18 | *

 19 |  * def
 20 |  * 
21 | * 22 | * variable: def=0 means 1 face, def=1 means 4 faces etc. 23 | */ 24 | public class ProgressiveSurfaceModel extends AbstractSurfaceModel implements SurfaceModel { 25 | 26 | protected SurfaceVertex[][] highDefinitionVertex; 27 | protected SurfaceVertex[][] surfaceVertex; 28 | protected Mapper mapper; 29 | int currentDefinition = -1; 30 | int availableDefinition = -1; 31 | int maxDefinition = 6; 32 | 33 | /** 34 | * Empty Surface Model 35 | */ 36 | public ProgressiveSurfaceModel() { 37 | super(); 38 | } 39 | 40 | public void setMapper(Mapper mapper) { 41 | this.mapper = mapper; 42 | } 43 | 44 | 45 | public SwingWorker plot() { 46 | return plot(null); 47 | } 48 | 49 | public SwingWorker plot(final Runnable callback) { 50 | highDefinitionVertex = allocateMemory(hasFunction1, hasFunction2, maxDefinition); 51 | currentDefinition = -1; 52 | availableDefinition = -1; 53 | 54 | return new SwingWorker() { 55 | 56 | @Override 57 | protected Void doInBackground() throws Exception { 58 | setProgress(0); 59 | while (maxDefinition > availableDefinition) { 60 | increaseDefinition(); 61 | // Thread.sleep(1000); 62 | if (isCancelled()) return null; 63 | publish(); 64 | } 65 | setProgress(100); 66 | return null; 67 | } 68 | 69 | @Override 70 | protected void process(List chunks) { 71 | setCurrentDefinition(availableDefinition); 72 | } 73 | 74 | /** 75 | * computes all the vertices, and increase the current definition. 76 | */ 77 | private void increaseDefinition() throws Exception{ 78 | int def = availableDefinition + 1; // increasing the def (but not offically to not propagate the consequences 79 | 80 | int max = 2+vertices(def)-vertices(def-1); // number of calls to compute 81 | int ci =1; 82 | setProgress(ci); 83 | // loop over all values BUT computes only for the ones in the current def 84 | 85 | int k = segments(maxDefinition) + 1; 86 | for (int i = 0; i < k; i++) 87 | for (int j = 0; j < k; j++) 88 | if (definition(i, j) == def){ 89 | if (isCancelled()) return; 90 | compute(i, j); 91 | setProgress(( ci++ *100 )/ max ) ; 92 | } 93 | availableDefinition = def; 94 | 95 | z1Min = (float) floor(z1Min, 2); 96 | z1Max = (float) ceil(z1Max, 2); 97 | z2Min = (float) floor(z2Min, 2); 98 | z2Max = (float) ceil(z2Max, 2); 99 | } 100 | 101 | @Override protected void done() { 102 | if (callback !=null) callback.run(); 103 | } 104 | 105 | 106 | 107 | }; 108 | } 109 | 110 | /** 111 | * creates a lower resolution surfaceVertex array 112 | * 113 | * @param def 114 | * @return 115 | */ 116 | private SurfaceVertex[][] extractResolution(int def) { 117 | SurfaceVertex[][] vertex = allocateMemory(hasFunction1, hasFunction2, def); 118 | int k = segments(def) + 1; 119 | 120 | for (int i = 0; i < k; i++) 121 | for (int j = 0; j < k; j++) 122 | // i, and j are in def coordinate 123 | copy(i, j, def, vertex); 124 | return vertex; 125 | } 126 | 127 | /** 128 | * copy surfaceVertex from the highdefinition in coordinate i,j, in definition def, into the target 129 | * 130 | * @param i 131 | * @param j 132 | * @param def 133 | * @param vertex 134 | */ 135 | private void copy(int i, int j, int def, SurfaceVertex[][] vertex) { 136 | int offset = maxDefinition - def; 137 | int hi = i << offset; 138 | int hj = j << offset; 139 | int k = i * (segments(def) + 1) + j; 140 | int hk = hi * (segments(maxDefinition) + 1) + hj; 141 | 142 | vertex[0][k] = highDefinitionVertex[0][hk]; 143 | vertex[1][k] = highDefinitionVertex[1][hk]; 144 | 145 | } 146 | 147 | /** 148 | * compute the point at i,j in high definition coordinate 149 | * 150 | * @param i 151 | * @param j 152 | */ 153 | private void compute(int i, int j) { 154 | 155 | int steps = segments(maxDefinition); 156 | float xWidth = xMax - xMin; 157 | float yWidth = yMax - yMin; 158 | 159 | float x = xMin + i * xWidth / steps; 160 | float y = yMin + j * yWidth / steps; 161 | // magic number ? no, 20 comes from the SurfaceVertex that requires values to be in [-10,10] 162 | float xfactor = 20 / (xWidth); 163 | float yfactor = 20 / (yWidth); 164 | int k = i * (steps + 1) + j; 165 | 166 | if (hasFunction1) { 167 | float f1 = mapper.f1(x, y); 168 | if (Float.isInfinite(f1)) 169 | f1 = Float.NaN; 170 | if (!Float.isNaN(f1)) { 171 | if (Float.isNaN(z1Max) || (f1 > z1Max)) 172 | z1Max = f1; 173 | else if (Float.isNaN(z1Min) || (f1 < z1Min)) 174 | z1Min = f1; 175 | } 176 | 177 | highDefinitionVertex[0][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, f1); 178 | } 179 | if (hasFunction2) { 180 | float f2 = mapper.f2(x, y); 181 | 182 | if (Float.isInfinite(f2)) 183 | f2 = Float.NaN; 184 | if (!Float.isNaN(f2)) { 185 | if (Float.isNaN(z2Max) || (f2 > z2Max)) 186 | z2Max = f2; 187 | else if (Float.isNaN(z2Min) || (f2 < z2Min)) 188 | z2Min = f2; 189 | } 190 | 191 | highDefinitionVertex[1][k] = new SurfaceVertex((x - xMin) * xfactor - 10, (y - yMin) * yfactor - 10, f2); 192 | } 193 | } 194 | 195 | /** 196 | * Allocates Memory 197 | */ 198 | 199 | private SurfaceVertex[][] allocateMemory(boolean f1, boolean f2, int def) { 200 | SurfaceVertex[][] vertex = null; 201 | int total = vertices(def); // compute total size 202 | 203 | try { 204 | vertex = new SurfaceVertex[2][total]; 205 | if (!f1) 206 | vertex[0] = null; 207 | if (!f2) 208 | vertex[1] = null; 209 | } catch (OutOfMemoryError e) { 210 | setMessage("Not enough memory"); 211 | } catch (Exception e) { 212 | setMessage("Error: " + e.toString()); 213 | } 214 | return vertex; 215 | } 216 | 217 | /** 218 | * return the definition this points belongs too. 219 | * 220 | * @param i 221 | * @param j 222 | * @return 223 | */ 224 | public int definition(int i, int j) { 225 | // odd numbers always belongs to the last definition, 226 | // numberOfTrailingZeros of odd number is 0 227 | // therefore i belongs to the definition maxdef - numberOfTrailingZeros(i) 228 | // cave at, there is an exeception for 0, numberOfTrailingZeros is 64 but we think of it as "0" 229 | int offset = Math.min(Long.numberOfTrailingZeros(i), Long.numberOfTrailingZeros(j)); 230 | return Math.max(0, maxDefinition - offset); 231 | } 232 | 233 | /** 234 | * computes the number of faces in a given definition 235 | * 236 | * @param def 237 | * @return 238 | */ 239 | public static final int faces(int def) { 240 | int segPerDim = segments(def); 241 | return segPerDim * segPerDim; 242 | } 243 | 244 | /** 245 | * computes the number of segment per dimension in a given definition 246 | * 247 | * @param def 248 | * @return 249 | */ 250 | public static final int segments(int def) { 251 | return 1 << def; // 2 ^ def +1 252 | } 253 | 254 | /** 255 | * computes the number of vertices in a given definition 256 | * 257 | * @param def 258 | * @return 259 | */ 260 | public static final int vertices(int def) { 261 | int dotsPerDim = segments(def) + 1; 262 | return dotsPerDim * dotsPerDim; 263 | } 264 | 265 | public SurfaceVertex[][] getSurfaceVertex() { 266 | return surfaceVertex; 267 | } 268 | 269 | protected void setSurfaceVertex(SurfaceVertex[][] surfaceVertex) { 270 | getPropertyChangeSupport().firePropertyChange("surfaceVertex", this.surfaceVertex, this.surfaceVertex = surfaceVertex); 271 | } 272 | 273 | public int getCurrentDefinition() { 274 | return currentDefinition; 275 | } 276 | 277 | /** 278 | * called only when data are available in the given definition, this causes a lot of changes 279 | * 280 | * @param currentDefinition 281 | */ 282 | public void setCurrentDefinition(int currentDefinition) { 283 | assert currentDefinition <= maxDefinition && currentDefinition <= availableDefinition : "cannot change definition higher than " + maxDefinition; 284 | 285 | SurfaceVertex[][] vertex = extractResolution(currentDefinition); 286 | // extract a new surfaceVertex on the given definition, and pass it to the setSurfaceVertex method 287 | getPropertyChangeSupport().firePropertyChange("currentDefinition", this.currentDefinition, this.currentDefinition = currentDefinition); 288 | int step = segments(currentDefinition); 289 | setSurfaceVertex(vertex); 290 | setCalcDivisions(step); 291 | setDispDivisions(step); 292 | if (currentDefinition >= 0) 293 | setDataAvailable(true); 294 | autoScale(); 295 | fireStateChanged(); 296 | } 297 | 298 | public int getMaxDefinition() { 299 | return maxDefinition; 300 | } 301 | 302 | public void setMaxDefinition(int maxDefinition) { 303 | getPropertyChangeSupport().firePropertyChange("maxDefinition", this.maxDefinition, this.maxDefinition = maxDefinition); 304 | } 305 | 306 | 307 | 308 | 309 | }// end of class 310 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/BeanProperty.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.beans; 2 | 3 | import java.beans.BeanInfo; 4 | import java.beans.EventSetDescriptor; 5 | import java.beans.Introspector; 6 | import java.beans.PropertyChangeEvent; 7 | import java.beans.PropertyChangeListener; 8 | import java.beans.PropertyDescriptor; 9 | 10 | /** Observe a standard Bean's property, and provide easy, type safe access to the get and set. 11 | * 12 | * @author Eric 13 | * 14 | */ 15 | public abstract class BeanProperty { 16 | 17 | BEAN bean; 18 | String propertyName; 19 | PropertyChangeListener propertyObserver = new PropertyChangeListener() { 20 | public void propertyChange(PropertyChangeEvent evt) { 21 | if (propertyName!=null && propertyName.equals(evt.getPropertyName() ) ) 22 | onPropertyChanged(evt); 23 | } 24 | }; 25 | 26 | transient BeanInfo beaninfo; 27 | transient EventSetDescriptor eventSetDescriptor; 28 | transient PropertyDescriptor propertyDescriptor; 29 | 30 | 31 | 32 | 33 | /** Sets the actual bean object 34 | * 35 | * @param model 36 | */ 37 | public void setBean(BEAN model) { 38 | Object old = this.bean; 39 | this.bean = model; 40 | bind(old); 41 | 42 | } 43 | 44 | protected abstract void onPropertyChanged(PropertyChangeEvent evt); 45 | 46 | /* (non-Javadoc) 47 | * @see javax.swing.DefaultButtonModel#isSelected() 48 | */ 49 | public PROP getProperty() { 50 | if (propertyDescriptor == null || bean == null) 51 | return null; 52 | try { 53 | return (PROP) propertyDescriptor.getReadMethod().invoke(bean); 54 | } catch (Exception e) { 55 | throw new RuntimeException(e); 56 | } 57 | } 58 | 59 | /* (non-Javadoc) 60 | * @see javax.swing.DefaultButtonModel#setPressed(boolean) 61 | */ 62 | public void setProperty(PROP value) { 63 | if (propertyDescriptor == null) 64 | return; // simple security 65 | try { 66 | propertyDescriptor.getWriteMethod().invoke(bean, value); 67 | } catch (Exception e) { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | 72 | /** 73 | * @return the propertyName 74 | */ 75 | public String getPropertyName() { 76 | return propertyName; 77 | } 78 | 79 | /** attribute to bind to. 80 | * @param propertyName usual lowercased property name 81 | */ 82 | public void setPropertyName(String propertyName) { 83 | this.propertyName = propertyName; 84 | bind(bean); 85 | } 86 | 87 | /** 88 | * @return the bean 89 | */ 90 | public BEAN getBean() { 91 | return bean; 92 | } 93 | 94 | 95 | 96 | private Object unregister(Object bean) { 97 | if (bean != null && propertyObserver !=null) { 98 | try { 99 | eventSetDescriptor.getRemoveListenerMethod().invoke(bean, propertyObserver); 100 | } catch (Exception e) { 101 | throw new RuntimeException(e); 102 | } 103 | } 104 | return getProperty(); // return the old value 105 | } 106 | 107 | private Object register() { 108 | beaninfo = null; 109 | eventSetDescriptor = null; 110 | propertyDescriptor = null; 111 | 112 | if (this.bean != null) { 113 | try { 114 | // introspect the bean 115 | beaninfo = Introspector.getBeanInfo(bean.getClass()); 116 | 117 | // extract the property 118 | for (PropertyDescriptor prop : beaninfo.getPropertyDescriptors()) 119 | if (prop.getName().equals(propertyName)) { 120 | this.propertyDescriptor = prop; 121 | break; 122 | } 123 | // extract the events 124 | for (EventSetDescriptor ev : beaninfo.getEventSetDescriptors()) 125 | if (ev.getListenerType() == PropertyChangeListener.class) { 126 | this.eventSetDescriptor = ev; 127 | break; 128 | } 129 | // now I know the event, and the property, I can use it 130 | if (propertyObserver!=null) 131 | eventSetDescriptor.getAddListenerMethod().invoke(this.bean, propertyObserver); 132 | } catch (Exception e) { 133 | throw new RuntimeException(e); 134 | } 135 | } 136 | return getProperty(); 137 | } 138 | 139 | private void bind(Object oldBean) { 140 | Object oldValue = unregister(oldBean); 141 | Object newValue = register() ; 142 | if (bean!=null && propertyName !=null) onPropertyChanged(new PropertyChangeEvent(bean, propertyName, oldValue, newValue)); 143 | 144 | } 145 | 146 | 147 | 148 | 149 | 150 | 151 | } -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JBindedCheckBox.java: -------------------------------------------------------------------------------- 1 | 2 | package net.ericaro.surfaceplotter.beans; 3 | 4 | import java.awt.event.ActionEvent; 5 | import java.beans.PropertyChangeEvent; 6 | 7 | import javax.swing.Action; 8 | import javax.swing.Icon; 9 | import javax.swing.JCheckBox; 10 | 11 | 12 | /** A {@link JCheckBox} binded to a boolean property of a ModelSource bean 13 | * @author Eric 14 | * 15 | */ 16 | public class JBindedCheckBox extends javax.swing.JCheckBox { 17 | 18 | 19 | ModelBindedBeanProperty property = new ModelBindedBeanProperty("surfaceModel") { 20 | 21 | @Override protected void onPropertyChanged(PropertyChangeEvent evt) { 22 | Object newValue = evt.getNewValue() ; 23 | if (newValue!=null) setSelected((Boolean) newValue); 24 | } 25 | }; 26 | 27 | /** 28 | * 29 | */ 30 | public JBindedCheckBox() { 31 | super(); 32 | } 33 | 34 | /** 35 | * @param a 36 | */ 37 | public JBindedCheckBox(Action a) { 38 | super(a); 39 | } 40 | 41 | /** 42 | * @param icon 43 | * @param selected 44 | */ 45 | public JBindedCheckBox(Icon icon, boolean selected) { 46 | super(icon, selected); 47 | } 48 | 49 | /** 50 | * @param icon 51 | */ 52 | public JBindedCheckBox(Icon icon) { 53 | super(icon); 54 | } 55 | 56 | /** 57 | * @param text 58 | * @param selected 59 | */ 60 | public JBindedCheckBox(String text, boolean selected) { 61 | super(text, selected); 62 | } 63 | 64 | /** 65 | * @param text 66 | * @param icon 67 | * @param selected 68 | */ 69 | public JBindedCheckBox(String text, Icon icon, boolean selected) { 70 | super(text, icon, selected); 71 | } 72 | 73 | /** 74 | * @param text 75 | * @param icon 76 | */ 77 | public JBindedCheckBox(String text, Icon icon) { 78 | super(text, icon); 79 | } 80 | 81 | /** 82 | * @param text 83 | */ 84 | public JBindedCheckBox(String text) { 85 | super(text); 86 | } 87 | 88 | 89 | 90 | 91 | 92 | /* intercept the actionperformed to fire my own 93 | */ 94 | @Override protected void fireActionPerformed(ActionEvent event) { 95 | // toogles the property 96 | Object old= property.getProperty() ; 97 | if (old !=null) property.setProperty(! (Boolean) old); 98 | super.fireActionPerformed(event); 99 | } 100 | 101 | // ########################################################################## 102 | // DELEGATE TO THE MODELBINDEDBEAN BEGIN 103 | // ########################################################################## 104 | 105 | /** 106 | * @return 107 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#getProperty() 108 | */ 109 | public Boolean getProperty() { 110 | return property.getProperty(); 111 | } 112 | 113 | 114 | 115 | 116 | /** 117 | * @param value 118 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#setProperty(java.lang.Object) 119 | */ 120 | public void setProperty(Boolean value) { 121 | property.setProperty(value); 122 | } 123 | 124 | /** 125 | * @return 126 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#getPropertyName() 127 | */ 128 | public String getPropertyName() { 129 | return property.getPropertyName(); 130 | } 131 | 132 | /** 133 | * @param propertyName 134 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#setPropertyName(java.lang.String) 135 | */ 136 | public void setPropertyName(String propertyName) { 137 | property.setPropertyName(propertyName); 138 | } 139 | 140 | /** 141 | * @return 142 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#getSourceBean() 143 | */ 144 | public ModelSource getSourceBean() { 145 | return property.getSourceBean(); 146 | } 147 | 148 | /** 149 | * @param modelSource 150 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#setSourceBean(java.lang.Object) 151 | */ 152 | public void setSourceBean(ModelSource modelSource) { 153 | property.setSourceBean(modelSource); 154 | } 155 | 156 | 157 | 158 | 159 | // ########################################################################## 160 | // DELEGATE TO THE MODELBINDEDBEAN END 161 | // ########################################################################## 162 | 163 | 164 | 165 | 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JBindedRadioButton.java: -------------------------------------------------------------------------------- 1 | 2 | package net.ericaro.surfaceplotter.beans; 3 | 4 | import java.awt.event.ActionEvent; 5 | import java.beans.PropertyChangeEvent; 6 | 7 | import javax.swing.Action; 8 | import javax.swing.Icon; 9 | import javax.swing.JRadioButton; 10 | 11 | /**A {@link JRadioButton} binded to a boolean property of a ModelSource bean 12 | * @author Eric 13 | * 14 | */ 15 | public class JBindedRadioButton extends JRadioButton { 16 | 17 | ModelBindedBeanProperty property = new ModelBindedBeanProperty("surfaceModel") { 18 | @Override protected void onPropertyChanged(PropertyChangeEvent evt) { 19 | Object newValue = evt.getNewValue(); 20 | if (newValue != null) 21 | setSelected((Boolean) newValue); 22 | } 23 | }; 24 | 25 | /** 26 | * 27 | */ 28 | public JBindedRadioButton() {} 29 | 30 | /** 31 | * @param icon 32 | */ 33 | public JBindedRadioButton(Icon icon) { 34 | super(icon); 35 | } 36 | 37 | /** 38 | * @param a 39 | */ 40 | public JBindedRadioButton(Action a) { 41 | super(a); 42 | } 43 | 44 | /** 45 | * @param text 46 | */ 47 | public JBindedRadioButton(String text) { 48 | super(text); 49 | } 50 | 51 | /** 52 | * @param icon 53 | * @param selected 54 | */ 55 | public JBindedRadioButton(Icon icon, boolean selected) { 56 | super(icon, selected); 57 | } 58 | 59 | /** 60 | * @param text 61 | * @param selected 62 | */ 63 | public JBindedRadioButton(String text, boolean selected) { 64 | super(text, selected); 65 | } 66 | 67 | /** 68 | * @param text 69 | * @param icon 70 | */ 71 | public JBindedRadioButton(String text, Icon icon) { 72 | super(text, icon); 73 | } 74 | 75 | /** 76 | * @param text 77 | * @param icon 78 | * @param selected 79 | */ 80 | public JBindedRadioButton(String text, Icon icon, boolean selected) { 81 | super(text, icon, selected); 82 | } 83 | 84 | /* intercept the actionperformed to fire my own 85 | */ 86 | @Override protected void fireActionPerformed(ActionEvent event) { 87 | // toogles the property 88 | Boolean old = property.getProperty(); 89 | if (old != null && !old) 90 | property.setProperty(true); 91 | super.fireActionPerformed(event); 92 | } 93 | 94 | // ########################################################################## 95 | // DELEGATED SECTION BEGIN 96 | // ########################################################################## 97 | 98 | 99 | /** 100 | * @return 101 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#getProperty() 102 | */ 103 | public Boolean getProperty() { 104 | return property.getProperty(); 105 | } 106 | 107 | 108 | 109 | 110 | /** 111 | * @param value 112 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#setProperty(java.lang.Object) 113 | */ 114 | public void setProperty(Boolean value) { 115 | property.setProperty(value); 116 | } 117 | 118 | /** 119 | * @return 120 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#getPropertyName() 121 | */ 122 | public String getPropertyName() { 123 | return property.getPropertyName(); 124 | } 125 | 126 | /** 127 | * @param propertyName 128 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#setPropertyName(java.lang.String) 129 | */ 130 | public void setPropertyName(String propertyName) { 131 | property.setPropertyName(propertyName); 132 | } 133 | 134 | /** 135 | * @return 136 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#getSourceBean() 137 | */ 138 | public ModelSource getSourceBean() { 139 | return property.getSourceBean(); 140 | } 141 | 142 | /** 143 | * @param modelSource 144 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#setSourceBean(java.lang.Object) 145 | */ 146 | public void setSourceBean(ModelSource modelSource) { 147 | property.setSourceBean(modelSource); 148 | } 149 | 150 | 151 | // ########################################################################## 152 | // DELEGATED SECTION END 153 | // ########################################################################## 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JEnumComboBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | ____ _____ ___ ____ __ ____ _____ _ _ ____ ____ 3 | ( _ \( _ )/ __)( ___) /__\ ( _ \( _ )( \/\/ )( ___)( _ \ 4 | )(_) ))(_)(( (__ )__) /(__)\ )___/ )(_)( ) ( )__) ) / 5 | (____/(_____)\___)(____)(__)(__) (__) (_____)(__/\__)(____)(_)\_) 6 | 7 | * Created 20 mai 2011 by : eric@doceapower.com 8 | * Copyright Docea Power 2011 9 | * Any reproduction or distribution prohibited without express written permission from Docea Power 10 | *************************************************************************** 11 | */ 12 | package net.ericaro.surfaceplotter.beans; 13 | 14 | import java.awt.Component; 15 | import java.awt.event.ItemEvent; 16 | import java.beans.PropertyChangeEvent; 17 | 18 | import javax.swing.DefaultListCellRenderer; 19 | import javax.swing.JComboBox; 20 | import javax.swing.JList; 21 | import javax.swing.ListCellRenderer; 22 | 23 | 24 | /** 25 | * @author eric 26 | * 27 | */ 28 | public abstract class JEnumComboBox> extends JComboBox { 29 | 30 | 31 | 32 | 33 | 34 | 35 | ModelBindedBeanProperty property = new ModelBindedBeanProperty("surfaceModel") { 36 | @Override protected void onPropertyChanged(PropertyChangeEvent evt) { 37 | Object newValue = evt.getNewValue(); 38 | if (newValue != null) 39 | setSelectedItem((T) newValue); 40 | } 41 | }; 42 | 43 | 44 | /** 45 | * 46 | */ 47 | public JEnumComboBox(T[] values, String property) { 48 | super(values); 49 | this.property.setPropertyName(property); 50 | setRenderer(new DefaultListCellRenderer() { 51 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 52 | Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 53 | setText( getEnumLabel((T) value) ); 54 | return c; 55 | 56 | } 57 | 58 | }); 59 | } 60 | 61 | protected abstract String getEnumLabel(T value) ; 62 | 63 | /* intercept the state changed to fire my own 64 | */ 65 | @Override protected void fireItemStateChanged(ItemEvent e) { 66 | T old = property.getProperty(); 67 | if (old !=null && !old.equals(e.getItem())) 68 | property.setProperty((T) e.getItem()); 69 | super.fireItemStateChanged(e); 70 | } 71 | 72 | // ########################################################################## 73 | // DELEGATED SECTION BEGIN 74 | // ########################################################################## 75 | 76 | 77 | /** 78 | * @return 79 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#getProperty() 80 | */ 81 | public T getProperty() { 82 | return property.getProperty(); 83 | } 84 | 85 | 86 | 87 | 88 | /** 89 | * @param value 90 | * @see net.ericaro.surfaceplotter.beans.BeanProperty#setProperty(java.lang.Object) 91 | */ 92 | public void setProperty(T value) { 93 | property.setProperty(value); 94 | } 95 | 96 | 97 | /** 98 | * @return 99 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#getSourceBean() 100 | */ 101 | public ModelSource getSourceBean() { 102 | return property.getSourceBean(); 103 | } 104 | 105 | /** 106 | * @param modelSource 107 | * @see net.ericaro.surfaceplotter.beans.ModelBindedBeanProperty#setSourceBean(java.lang.Object) 108 | */ 109 | public void setSourceBean(ModelSource modelSource) { 110 | property.setSourceBean(modelSource); 111 | } 112 | 113 | 114 | // ########################################################################## 115 | // DELEGATED SECTION END 116 | // ########################################################################## 117 | 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JGridBagScrollPane.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.beans; 2 | 3 | import java.awt.Component; 4 | import java.awt.Dimension; 5 | 6 | import javax.swing.JScrollPane; 7 | 8 | 9 | /** A scrollpane suitable for gridbag layout. 10 | *

When a GridBagLayout has not enough room to layout its component, it moves 11 | * from preferredsize to minimum size. Standard scrollpane have a very small minimumsize, and it DOES not depend on the viewport view. 12 | *

Therefore, this scrollpane does not collapse to a very small minimum size. 13 | *

if one direction is set to fixed (either

widthFixed
heightFixed
) then the minimum size for this 14 | * direction = the preffered size. 15 | * 16 | * @author eric 17 | * 18 | */ 19 | public class JGridBagScrollPane extends JScrollPane{ 20 | 21 | private boolean widthFixed =false; 22 | private boolean heightFixed = false; 23 | 24 | 25 | 26 | 27 | public JGridBagScrollPane() { 28 | super(); 29 | } 30 | 31 | 32 | 33 | 34 | public JGridBagScrollPane(Component view, int vsbPolicy, int hsbPolicy) { 35 | super(view, vsbPolicy, hsbPolicy); 36 | } 37 | 38 | 39 | 40 | 41 | public JGridBagScrollPane(Component view) { 42 | super(view); 43 | } 44 | 45 | 46 | 47 | 48 | public JGridBagScrollPane(int vsbPolicy, int hsbPolicy) { 49 | super(vsbPolicy, hsbPolicy); 50 | } 51 | 52 | 53 | 54 | 55 | @Override 56 | public Dimension getMinimumSize() { 57 | Dimension min = super.getMinimumSize(); 58 | int w = min.width; 59 | int h = min.height; 60 | if (widthFixed){ 61 | w = getPreferredSize().width; // the content size 62 | w+= getVerticalScrollBar().getWidth(); 63 | } 64 | if (heightFixed){ 65 | h = getPreferredSize().height; // the content size 66 | h+= getHorizontalScrollBar().getHeight(); 67 | } 68 | 69 | return new Dimension(w, h); 70 | } 71 | 72 | 73 | @Override 74 | public void layout() { 75 | boolean vertical = getVerticalScrollBar().isVisible(); 76 | super.layout(); 77 | if (vertical != getVerticalScrollBar().isVisible() ){ 78 | getParent().invalidate() ; 79 | getParent().validate(); 80 | } 81 | } 82 | 83 | 84 | 85 | 86 | public boolean isWidthFixed() { 87 | return widthFixed; 88 | } 89 | 90 | 91 | 92 | /** 93 | * 94 | * @param widthFixed true to force the minimum width to preferred's width. 95 | */ 96 | public void setWidthFixed(boolean widthFixed) { 97 | firePropertyChange("widthFixed", this.widthFixed , this.widthFixed = widthFixed); 98 | invalidate(); 99 | if (getParent()!=null) 100 | getParent().validate(); 101 | } 102 | 103 | 104 | 105 | 106 | public boolean isHeightFixed() { 107 | return heightFixed; 108 | } 109 | 110 | 111 | 112 | /** 113 | * 114 | * @param heightFixed true to force the minimum height to preferred's height. 115 | */ 116 | public void setHeightFixed(boolean heightFixed) { 117 | firePropertyChange("heightFixed", this.heightFixed , this.heightFixed = heightFixed); 118 | if (getParent()!=null) 119 | getParent().validate(); 120 | } 121 | 122 | 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JPlotColorComboBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | ____ _____ ___ ____ __ ____ _____ _ _ ____ ____ 3 | ( _ \( _ )/ __)( ___) /__\ ( _ \( _ )( \/\/ )( ___)( _ \ 4 | )(_) ))(_)(( (__ )__) /(__)\ )___/ )(_)( ) ( )__) ) / 5 | (____/(_____)\___)(____)(__)(__) (__) (_____)(__/\__)(____)(_)\_) 6 | 7 | * Created 20 mai 2011 by : eric@doceapower.com 8 | * Copyright Docea Power 2011 9 | * Any reproduction or distribution prohibited without express written permission from Docea Power 10 | *************************************************************************** 11 | */ 12 | package net.ericaro.surfaceplotter.beans; 13 | 14 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotColor; 15 | 16 | /** 17 | * @author eric 18 | * 19 | */ 20 | public class JPlotColorComboBox extends JEnumComboBox { 21 | 22 | // String hiddenModeLabel = PlotColor.OPAQUE.getPropertyName(); 23 | // String spectrumModeLabel = PlotColor.SPECTRUM.getPropertyName(); 24 | // String dualShadeModeLabel = PlotColor.DUALSHADE.getPropertyName(); 25 | // String grayScaleModeLabel = PlotColor.GRAYSCALE.getPropertyName(); 26 | // String fogModeLabel = PlotColor.FOG.getPropertyName(); 27 | // 28 | 29 | 30 | String[] labels; 31 | 32 | /** 33 | * 34 | */ 35 | public JPlotColorComboBox() { 36 | super(PlotColor.values(), "plotColor"); 37 | labels = new String[PlotColor.values().length]; 38 | for (int i = 0; i < PlotColor.values().length; i++) 39 | labels[i] = PlotColor.values()[i].getPropertyName() ; 40 | } 41 | 42 | 43 | 44 | 45 | @Override protected String getEnumLabel(PlotColor value) { 46 | return labels[value.ordinal()]; 47 | } 48 | 49 | protected String setEnumLabel(PlotColor value, String newValue) { 50 | labels[value.ordinal()] = newValue; 51 | return newValue; 52 | } 53 | 54 | 55 | 56 | 57 | public String getHiddenModeLabel() { 58 | return getEnumLabel(PlotColor.OPAQUE); 59 | } 60 | 61 | public void setHiddenModeLabel(String hiddenModeLabel) { 62 | firePropertyChange("hiddenModeLabel", getHiddenModeLabel(), setEnumLabel(PlotColor.OPAQUE, hiddenModeLabel)); 63 | } 64 | 65 | 66 | public String getSpectrumModeLabel() { 67 | return getEnumLabel(PlotColor.SPECTRUM); 68 | 69 | } 70 | 71 | public void setSpectrumModeLabel(String spectrumModeLabel) { 72 | firePropertyChange("spectrumModeLabel", getSpectrumModeLabel(), setEnumLabel(PlotColor.SPECTRUM, spectrumModeLabel)); 73 | } 74 | 75 | public String getDualShadeModeLabel() { 76 | return getEnumLabel(PlotColor.DUALSHADE); 77 | 78 | } 79 | 80 | public void setDualShadeModeLabel(String dualShadeModeLabel) { 81 | firePropertyChange("dualShadeModeLabel", getDualShadeModeLabel(), setEnumLabel(PlotColor.DUALSHADE,dualShadeModeLabel)); 82 | } 83 | 84 | public String getGrayScaleModeLabel() { 85 | return getEnumLabel(PlotColor.GRAYSCALE); 86 | } 87 | 88 | public void setGrayScaleModeLabel(String grayScaleModeLabel) { 89 | firePropertyChange("grayScaleModeLabel", getGrayScaleModeLabel(), setEnumLabel(PlotColor.GRAYSCALE,grayScaleModeLabel)); 90 | } 91 | 92 | public String getFogModeLabel() { 93 | return getEnumLabel(PlotColor.FOG); 94 | } 95 | 96 | public void setFogModeLabel(String fogModeLabel) { 97 | firePropertyChange("fogModeLabel", getFogModeLabel(), setEnumLabel(PlotColor.FOG,fogModeLabel)); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JPlotTypeComboBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | ____ _____ ___ ____ __ ____ _____ _ _ ____ ____ 3 | ( _ \( _ )/ __)( ___) /__\ ( _ \( _ )( \/\/ )( ___)( _ \ 4 | )(_) ))(_)(( (__ )__) /(__)\ )___/ )(_)( ) ( )__) ) / 5 | (____/(_____)\___)(____)(__)(__) (__) (_____)(__/\__)(____)(_)\_) 6 | 7 | * Created 20 mai 2011 by : eric@doceapower.com 8 | * Copyright Docea Power 2011 9 | * Any reproduction or distribution prohibited without express written permission from Docea Power 10 | *************************************************************************** 11 | */ 12 | package net.ericaro.surfaceplotter.beans; 13 | 14 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotColor; 15 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotType; 16 | 17 | /** 18 | * @author eric 19 | * 20 | */ 21 | public class JPlotTypeComboBox extends JEnumComboBox { 22 | 23 | 24 | 25 | String[] labels; 26 | 27 | /** 28 | * 29 | */ 30 | public JPlotTypeComboBox() { 31 | super(PlotType.values(), "plotType"); 32 | labels = new String[PlotType.values().length]; 33 | for (int i = 0; i < PlotType.values().length; i++) 34 | labels[i] = PlotType.values()[i].getPropertyName() ; 35 | } 36 | 37 | 38 | 39 | 40 | @Override protected String getEnumLabel(PlotType value) { 41 | return labels[value.ordinal()]; 42 | } 43 | 44 | protected String setEnumLabel(PlotType value, String newValue) { 45 | labels[value.ordinal()] = newValue; 46 | return newValue; 47 | } 48 | 49 | 50 | public String getWireframeLabel() { 51 | return getEnumLabel(PlotType.WIREFRAME); 52 | } 53 | 54 | public void setWireframeLabel(String wireframeLabel) { 55 | firePropertyChange("wireframeLabel", getWireframeLabel(), setEnumLabel(PlotType.WIREFRAME, wireframeLabel)); 56 | } 57 | 58 | public String getSurfaceLabel() { 59 | return getEnumLabel(PlotType.SURFACE); 60 | } 61 | 62 | public void setSurfaceLabel(String surfaceLabel) { 63 | firePropertyChange("surfaceLabel", getSurfaceLabel(), setEnumLabel(PlotType.SURFACE, surfaceLabel)); 64 | } 65 | 66 | public String getDensityLabel() { 67 | return getEnumLabel(PlotType.DENSITY); 68 | } 69 | 70 | public void setDensityLabel(String densityLabel) { 71 | firePropertyChange("densityLabel", getDensityLabel(), setEnumLabel(PlotType.DENSITY, densityLabel)); 72 | } 73 | 74 | 75 | public String getContourLabel() { 76 | return getEnumLabel(PlotType.CONTOUR); 77 | } 78 | 79 | public void setContourLabel(String contourLabel) { 80 | firePropertyChange("contourLabel", getContourLabel(), setEnumLabel(PlotType.CONTOUR, contourLabel)); 81 | } 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/JScrollablePanel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.beans; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.GridBagLayout; 5 | import java.awt.LayoutManager; 6 | import java.awt.Point; 7 | import java.awt.Rectangle; 8 | 9 | import javax.swing.JPanel; 10 | import javax.swing.JViewport; 11 | import javax.swing.Scrollable; 12 | import javax.swing.SwingConstants; 13 | 14 | 15 | /** A panel that rely on its GridBagLayout to provide "smart" increment for scrolling, implementing the {@link Scrollable} interface 16 | * @author eric 17 | * 18 | */ 19 | public class JScrollablePanel extends JPanel implements Scrollable { 20 | 21 | private int blockIncrement = 5; 22 | 23 | /** Block increment is used the scrollpane block increment is blockIncrement* unitIncrement 24 | * 25 | * @return 26 | */ 27 | public int getBlockIncrement() { 28 | return blockIncrement; 29 | } 30 | 31 | public void setBlockIncrement(int blockIncrement) { 32 | this.blockIncrement = blockIncrement; 33 | } 34 | 35 | 36 | /** 37 | * 38 | */ 39 | public JScrollablePanel() { 40 | super(); 41 | } 42 | 43 | /** 44 | * @param isDoubleBuffered 45 | */ 46 | public JScrollablePanel(boolean isDoubleBuffered) { 47 | super(isDoubleBuffered); 48 | } 49 | 50 | /** 51 | * @param layout 52 | * @param isDoubleBuffered 53 | */ 54 | public JScrollablePanel(LayoutManager layout, boolean isDoubleBuffered) { 55 | super(layout, isDoubleBuffered); 56 | } 57 | 58 | /** 59 | * @param layout 60 | */ 61 | public JScrollablePanel(LayoutManager layout) { 62 | super(layout); 63 | } 64 | 65 | public Dimension getPreferredScrollableViewportSize() { 66 | return getPreferredSize(); 67 | } 68 | 69 | public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 70 | return blockIncrement *getScrollableUnitIncrement(visibleRect, orientation, direction); 71 | } 72 | 73 | 74 | public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 75 | 76 | 77 | // TODO improve using other layouts (like gridlayout, or flowlayout, boxlayout etc.) 78 | if (getLayout() instanceof GridBagLayout) 79 | { 80 | // access the grid bag layout and use the rows and cols size to handle increments 81 | GridBagLayout layout = (GridBagLayout) getLayout() ; 82 | Point p = layout.location(visibleRect.x, visibleRect.y); 83 | int[][] dims = layout.getLayoutDimensions(); 84 | Point origin = layout.getLayoutOrigin(); 85 | 86 | if (orientation == SwingConstants.VERTICAL) { // looking for the row height 87 | if (direction<0) // use the previous row, as we are going backward 88 | p.y-=1; 89 | else p.y+=1; // use the next one 90 | if (p.y< dims[1].length && p.y>=0) 91 | {// compute the next position 92 | int pos = origin.y; 93 | for(int i=0;i=0) { 105 | int pos = origin.x; 106 | for(int i=0;i getPreferredSize().height); 119 | } 120 | return false; 121 | } 122 | 123 | public boolean getScrollableTracksViewportWidth() { 124 | if (getParent() instanceof JViewport) { 125 | return (((JViewport)getParent()).getWidth() > getPreferredSize().width); 126 | } 127 | return false; 128 | } 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/ModelBindedBeanProperty.java: -------------------------------------------------------------------------------- 1 | 2 | package net.ericaro.surfaceplotter.beans; 3 | 4 | import java.beans.PropertyChangeEvent; 5 | 6 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 7 | 8 | 9 | 10 | 11 | /** bind the "bean" attribute to a "source" property of a model provider. 12 | * @author eric 13 | * 14 | */ 15 | public abstract class ModelBindedBeanProperty extends BeanProperty{ 16 | 17 | 18 | 19 | 20 | BeanProperty sourceBeanProperty = new BeanProperty() { 21 | 22 | @Override protected void onPropertyChanged(PropertyChangeEvent evt) { 23 | ModelBindedBeanProperty.this.setBean((AbstractSurfaceModel) evt.getNewValue()); 24 | } 25 | }; 26 | 27 | 28 | public ModelBindedBeanProperty(String sourcePropertyName) { 29 | setSourcePropertyName(sourcePropertyName); 30 | } 31 | 32 | /** 33 | * @return the modelSource 34 | */ 35 | public ModelSource getSourceBean() { 36 | return sourceBeanProperty.getBean(); 37 | } 38 | /** 39 | * @param modelSource the modelSource to set 40 | */ 41 | public void setSourceBean(ModelSource modelSource) { 42 | sourceBeanProperty.setBean(modelSource); 43 | } 44 | /** 45 | * @return the modelSourcePropertyName 46 | */ 47 | public String getSourcePropertyName() { 48 | return sourceBeanProperty.getPropertyName(); 49 | } 50 | /** 51 | * @param modelSourcePropertyName the modelSourcePropertyName to set 52 | */ 53 | public void setSourcePropertyName(String modelSourcePropertyName) { 54 | sourceBeanProperty.setPropertyName(modelSourcePropertyName); 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/beans/ModelSource.java: -------------------------------------------------------------------------------- 1 | 2 | package net.ericaro.surfaceplotter.beans; 3 | 4 | import java.beans.PropertyChangeListener; 5 | 6 | import javax.swing.event.SwingPropertyChangeSupport; 7 | 8 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 9 | 10 | 11 | /** A Bean that "handles" an DefaultSurfaceModel, editors get ginded to this source to display an attribute. 12 | * @author eric 13 | * 14 | */ 15 | public class ModelSource { 16 | 17 | SwingPropertyChangeSupport event = new SwingPropertyChangeSupport(this); 18 | AbstractSurfaceModel surfaceModel; 19 | 20 | 21 | /** 22 | * @return the surfaceModel 23 | */ 24 | public AbstractSurfaceModel getSurfaceModel() { 25 | return surfaceModel; 26 | } 27 | 28 | /** 29 | * @param surfaceModel the surfaceModel to set 30 | */ 31 | public void setSurfaceModel(AbstractSurfaceModel surfaceModel) { 32 | Object old = this.surfaceModel ; 33 | this.surfaceModel = surfaceModel; 34 | event.firePropertyChange("surfaceModel", old, surfaceModel); 35 | } 36 | 37 | /** 38 | * @param listener 39 | * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) 40 | */ 41 | public void addPropertyChangeListener(PropertyChangeListener listener) { 42 | event.addPropertyChangeListener(listener); 43 | } 44 | 45 | /** 46 | * @param propertyName 47 | * @param listener 48 | * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 49 | */ 50 | public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { 51 | event.addPropertyChangeListener(propertyName, listener); 52 | } 53 | 54 | /** 55 | * @param listener 56 | * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) 57 | */ 58 | public void removePropertyChangeListener(PropertyChangeListener listener) { 59 | event.removePropertyChangeListener(listener); 60 | } 61 | 62 | /** 63 | * @param propertyName 64 | * @param listener 65 | * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 66 | */ 67 | public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { 68 | event.removePropertyChangeListener(propertyName, listener); 69 | } 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/AbstractSurfaceModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | import java.beans.PropertyChangeSupport; 4 | import java.io.File; 5 | import java.io.IOException; 6 | 7 | import javax.swing.event.ChangeEvent; 8 | import javax.swing.event.ChangeListener; 9 | import javax.swing.event.EventListenerList; 10 | import javax.swing.event.SwingPropertyChangeSupport; 11 | 12 | import net.ericaro.surfaceplotter.Mapper; 13 | 14 | /** Abstract implementation that handles everything but the surfaceVertex array 15 | * 16 | * @author eric 17 | * 18 | */ 19 | public abstract class AbstractSurfaceModel implements SurfaceModel{ 20 | 21 | /** 22 | * Interface returned by this object to write values in this model 23 | * 24 | * @author eric 25 | */ 26 | public interface Plotter { 27 | public int getHeight(); 28 | 29 | public int getWidth(); 30 | 31 | public float getX(int i); 32 | 33 | public float getY(int j); 34 | 35 | public void setValue(int i, int j, float v1, float v2); 36 | 37 | } 38 | /** 39 | * internally used to ceil values 40 | * 41 | * @param d 42 | * @param digits 43 | * @return 44 | */ 45 | public static synchronized double ceil(double d, int digits) { 46 | if (d == 0) 47 | return d; 48 | long og = (long) Math.ceil((Math.log(Math.abs(d)) / Math.log(10))); 49 | double factor = Math.pow(10, digits - og); 50 | double res = Math.ceil((d * factor)) / factor; 51 | return res; 52 | } 53 | 54 | /** 55 | * internally used to floor values 56 | * 57 | * @param d 58 | * @param digits 59 | * @return 60 | */ 61 | public static synchronized double floor(double d, int digits) { 62 | if (d == 0) 63 | return d; 64 | // computes order of magnitude 65 | long og = (long) Math.ceil((Math.log(Math.abs(d)) / Math.log(10))); 66 | 67 | double factor = Math.pow(10, digits - og); 68 | // the matissa 69 | double res = Math.floor((d * factor)) / factor; 70 | // res contains the closed power of ten 71 | return res; 72 | } 73 | 74 | private static final int INIT_CALC_DIV = 20; 75 | private static final int INIT_DISP_DIV = 20; 76 | 77 | 78 | protected boolean autoScaleZ = true; 79 | 80 | 81 | /** 82 | * Determines whether to show bounding box. 83 | * 84 | * @return true if to show bounding box 85 | */ 86 | protected boolean boxed; 87 | protected int calcDivisions = INIT_CALC_DIV; 88 | protected ColorModelSet colorModel; 89 | protected int contourLines; 90 | /** 91 | * Sets data availability flag 92 | */ 93 | protected boolean dataAvailable; 94 | protected int dispDivisions = INIT_DISP_DIV; 95 | /** 96 | * Determines whether to show face grids. 97 | * 98 | * @return true if to show face grids 99 | */ 100 | protected boolean displayGrids; 101 | /** 102 | * Determines whether to show x-y ticks. 103 | * 104 | * @return true if to show x-y ticks 105 | */ 106 | protected boolean displayXY; 107 | 108 | /** 109 | * Determines whether to show z ticks. 110 | * 111 | * @return true if to show z ticks 112 | */ 113 | protected boolean displayZ; 114 | 115 | /** 116 | * Determines whether the delay regeneration checkbox is checked. 117 | * 118 | * @return true if the checkbox is checked, false otherwise 119 | */ 120 | protected boolean expectDelay = false; 121 | 122 | /** 123 | * Determines whether the first function is selected. 124 | * 125 | * @return true if the first function is checked, false otherwise 126 | */ 127 | 128 | protected boolean hasFunction1 = true; 129 | 130 | /** 131 | * Determines whether the first function is selected. 132 | * 133 | * @return true if the first function is checked, false otherwise 134 | */ 135 | protected boolean hasFunction2 = true; 136 | 137 | protected EventListenerList listenerList = new EventListenerList(); 138 | 139 | /** 140 | * Determines whether to show x-y mesh. 141 | * 142 | * @return true if to show x-y mesh 143 | */ 144 | protected boolean mesh; 145 | 146 | protected PlotColor plotColor; 147 | 148 | protected boolean plotFunction1 = hasFunction1; 149 | 150 | protected boolean plotFunction2 = hasFunction2; 151 | 152 | protected PlotType plotType = PlotType.SURFACE; 153 | 154 | private Projector projector; 155 | 156 | protected PropertyChangeSupport property; 157 | 158 | /** 159 | * Determines whether to scale axes and bounding box. 160 | * 161 | * @return true if to scale bounding box 162 | */ 163 | 164 | protected boolean scaleBox; 165 | 166 | protected float xMax = 1f; 167 | 168 | protected float xMin; 169 | protected float yMax = 1f; 170 | 171 | protected float yMin; 172 | protected float z1Max;// the max computed 173 | 174 | protected float z1Min;// the min computed 175 | protected float z2Max;// the max computed 176 | 177 | protected float z2Min;// the min computed 178 | protected float zMax; 179 | 180 | protected float zMin; 181 | 182 | /** 183 | * Empty Surface Model 184 | */ 185 | public AbstractSurfaceModel() { 186 | super(); 187 | property = new SwingPropertyChangeSupport(this); 188 | setColorModel(new ColorModelSet()); 189 | 190 | setCalcDivisions(50); 191 | setDispDivisions(50); 192 | setContourLines(10); 193 | 194 | setXMin(-3); 195 | setXMax(3); 196 | setYMin(-3); 197 | setYMax(3); 198 | 199 | setBoxed(false); 200 | setDisplayXY(false); 201 | setExpectDelay(false); 202 | setAutoScaleZ(true); 203 | setDisplayZ(false); 204 | setMesh(true); 205 | setPlotType(PlotType.SURFACE); 206 | setFirstFunctionOnly(true); 207 | setPlotColor(PlotColor.SPECTRUM); 208 | } 209 | 210 | public void addChangeListener(ChangeListener ol) { 211 | listenerList.add(ChangeListener.class, ol); 212 | } 213 | 214 | public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { 215 | property.addPropertyChangeListener(listener); 216 | } 217 | 218 | public void addPropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener) { 219 | property.addPropertyChangeListener(propertyName, listener); 220 | } 221 | 222 | 223 | 224 | /** 225 | * Autoscale based on actual values 226 | */ 227 | public void autoScale() { 228 | // compute auto scale and repaint 229 | if (!autoScaleZ) 230 | return; 231 | if (plotFunction1 && plotFunction2) { 232 | setZMin(Math.min(z1Min, z2Min)); 233 | setZMax(Math.max(z1Max, z2Max)); 234 | } else { 235 | if (plotFunction1) { 236 | setZMin(z1Min); 237 | setZMax(z1Max); 238 | } 239 | if (plotFunction2) { 240 | setZMin(z2Min); 241 | setZMax(z2Max); 242 | } 243 | } 244 | } 245 | 246 | public void exportCSV(File file) throws IOException { 247 | SurfaceVertex[][] surfaceVertex = getSurfaceVertex(); 248 | if (file == null) 249 | return; 250 | java.io.FileWriter w = new java.io.FileWriter(file); 251 | float stepx, stepy, x, y; 252 | float xi, xx, yi, yx; 253 | int i, j, k; 254 | 255 | 256 | try { 257 | xi = getXMin(); 258 | yi = getYMin(); 259 | xx = getXMax(); 260 | yx = getYMax(); 261 | if ((xi >= xx) || (yi >= yx)) 262 | throw new NumberFormatException(); 263 | } catch (NumberFormatException e) { 264 | setMessage("Error in ranges"); 265 | return; 266 | } 267 | 268 | calcDivisions = getCalcDivisions(); 269 | // func1calc = f1; func2calc = f2; 270 | 271 | stepx = (xx - xi) / calcDivisions; 272 | stepy = (yx - yi) / calcDivisions; 273 | 274 | if (surfaceVertex == null) 275 | return; 276 | i = 0; 277 | j = 0; 278 | k = 0; 279 | x = xi; 280 | y = yi; 281 | 282 | w.write("X\\Y->Z;"); 283 | while (j <= calcDivisions) { 284 | 285 | w.write(Float.toString(y)); 286 | if (j != calcDivisions) 287 | w.write(';'); 288 | j++; 289 | y += stepy; 290 | k++; 291 | } 292 | w.write("\n"); 293 | // first line written 294 | i = 0; 295 | j = 0; 296 | k = 0; 297 | x = xi; 298 | y = yi; 299 | 300 | while (i <= calcDivisions) { 301 | w.write(Float.toString(x)); 302 | w.write(';'); 303 | while (j <= calcDivisions) { 304 | w.write(Float.toString(surfaceVertex[0][k].z)); 305 | if (j != calcDivisions) 306 | w.write(';'); 307 | j++; 308 | y += stepy; 309 | k++; 310 | // setMessage("Calculating : " + k*100/total + "% completed"); 311 | } 312 | w.write('\n'); 313 | // first line written 314 | j = 0; 315 | y = yi; 316 | i++; 317 | x += stepx; 318 | } 319 | w.flush(); 320 | w.close(); 321 | 322 | } 323 | 324 | private void fireAllFunction(boolean oldHas1, boolean oldHas2) { 325 | property.firePropertyChange("firstFunctionOnly", (!oldHas2) && oldHas1, (!plotFunction2) && plotFunction1); 326 | property.firePropertyChange("secondFunctionOnly", (!oldHas1) && oldHas2, (!plotFunction1) && plotFunction2); 327 | property.firePropertyChange("bothFunction", oldHas1 && oldHas2, plotFunction1 && plotFunction2); 328 | autoScale(); 329 | 330 | } 331 | 332 | private void fireAllMode(PlotColor oldValue, PlotColor newValue) { 333 | for (PlotColor c : PlotColor.values()) 334 | property.firePropertyChange(c.getPropertyName(), oldValue == c, newValue == c); 335 | } 336 | 337 | private void fireAllType(PlotType oldValue, PlotType newValue) { 338 | for (PlotType c : PlotType.values()) 339 | property.firePropertyChange(c.getPropertyName(), oldValue == c, newValue == c); 340 | } 341 | 342 | protected void fireStateChanged() { 343 | // Guaranteed to return a non-null array 344 | Object[] listeners = listenerList.getListenerList(); 345 | // Process the listeners last to first, notifying 346 | // those that are interested in this event 347 | ChangeEvent e = null; 348 | for (int i = listeners.length - 2; i >= 0; i -= 2) { 349 | if (listeners[i] == ChangeListener.class) { 350 | // Lazily create the event: 351 | if (e == null) 352 | e = new ChangeEvent(this); 353 | ((ChangeListener) listeners[i + 1]).stateChanged(e); 354 | } 355 | } 356 | } 357 | 358 | public int getCalcDivisions() { 359 | return calcDivisions; 360 | } 361 | 362 | public SurfaceColor getColorModel() { 363 | return colorModel; 364 | } 365 | 366 | public int getContourLines() { 367 | return contourLines; 368 | } 369 | 370 | public int getDispDivisions() { 371 | if (dispDivisions > calcDivisions) 372 | dispDivisions = calcDivisions; 373 | while ((calcDivisions % dispDivisions) != 0) 374 | dispDivisions++; 375 | return dispDivisions; 376 | } 377 | 378 | public PlotColor getPlotColor() { 379 | return plotColor; 380 | } 381 | 382 | public PlotType getPlotType() { 383 | return plotType; 384 | } 385 | 386 | public Projector getProjector() { 387 | if (projector == null) { 388 | projector = new Projector(); 389 | projector.setDistance(70); 390 | projector.set2DScaling(15); 391 | projector.setRotationAngle(125); 392 | projector.setElevationAngle(10); 393 | } 394 | return projector; 395 | } 396 | 397 | public PropertyChangeSupport getPropertyChangeSupport() { 398 | if (property == null) 399 | property = new SwingPropertyChangeSupport(this); 400 | return property; 401 | } 402 | 403 | public float getXMax() { 404 | return xMax; 405 | } 406 | 407 | public float getXMin() { 408 | return xMin; 409 | } 410 | 411 | public float getYMax() { 412 | return yMax; 413 | } 414 | 415 | public float getYMin() { 416 | return yMin; 417 | } 418 | 419 | public float getZMax() { 420 | return zMax; 421 | } 422 | 423 | public float getZMin() { 424 | return zMin; 425 | } 426 | 427 | public boolean isAutoScaleZ() { 428 | return autoScaleZ; 429 | } 430 | 431 | public boolean isBothFunction() { 432 | return plotFunction1 && plotFunction2; 433 | } 434 | 435 | public boolean isBoxed() { 436 | return boxed; 437 | } 438 | 439 | public boolean isContourType() { 440 | return plotType == PlotType.CONTOUR; 441 | } 442 | 443 | public boolean isDataAvailable() { 444 | return dataAvailable; 445 | } 446 | 447 | public boolean isDensityType() { 448 | return plotType == PlotType.DENSITY; 449 | } 450 | 451 | public boolean isDisplayGrids() { 452 | return displayGrids; 453 | } 454 | 455 | public boolean isDisplayXY() { 456 | return displayXY; 457 | } 458 | 459 | public boolean isDisplayZ() { 460 | return displayZ; 461 | } 462 | 463 | public boolean isDualShadeMode() { 464 | return plotColor == PlotColor.DUALSHADE; 465 | } 466 | 467 | public boolean isExpectDelay() { 468 | return expectDelay; 469 | } 470 | 471 | public boolean isFirstFunctionOnly() { 472 | return plotFunction1 && !plotFunction2; 473 | } 474 | 475 | public boolean isFogMode() { 476 | return plotColor == PlotColor.FOG; 477 | } 478 | 479 | public boolean isGrayScaleMode() { 480 | return plotColor == PlotColor.GRAYSCALE; 481 | } 482 | 483 | public boolean isHiddenMode() { 484 | return plotColor == PlotColor.OPAQUE; 485 | } 486 | 487 | public boolean isMesh() { 488 | return mesh; 489 | } 490 | 491 | public boolean isPlotFunction1() { 492 | return plotFunction1; 493 | } 494 | 495 | public boolean isPlotFunction2() { 496 | return plotFunction2; 497 | } 498 | 499 | public boolean isScaleBox() { 500 | return scaleBox; 501 | } 502 | 503 | public boolean isSecondFunctionOnly() { 504 | return (!plotFunction1) && plotFunction2; 505 | } 506 | 507 | public boolean isSpectrumMode() { 508 | return plotColor == PlotColor.SPECTRUM; 509 | } 510 | 511 | public boolean isSurfaceType() { 512 | return plotType == PlotType.SURFACE; 513 | } 514 | 515 | public boolean isWireframeType() { 516 | return plotType == PlotType.WIREFRAME; 517 | } 518 | 519 | public void removeChangeListener(ChangeListener ol) { 520 | listenerList.remove(ChangeListener.class, ol); 521 | } 522 | 523 | public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { 524 | property.removePropertyChangeListener(listener); 525 | } 526 | 527 | public void removePropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener) { 528 | property.removePropertyChangeListener(propertyName, listener); 529 | } 530 | 531 | /** 532 | * Called when automatic rotation stops 533 | */ 534 | 535 | public void rotationStops() { 536 | 537 | // setting_panel.rotationStops(); 538 | } 539 | 540 | public void setAutoScaleZ(boolean autoScaleZ) { 541 | getPropertyChangeSupport().firePropertyChange("this.autoScaleZ", this.autoScaleZ, this.autoScaleZ = autoScaleZ); 542 | autoScale(); 543 | } 544 | 545 | public void setBothFunction(boolean val) { 546 | setPlotFunction12(val, val); 547 | } 548 | 549 | public void setBoxed(boolean boxed) { 550 | getPropertyChangeSupport().firePropertyChange("boxed", this.boxed, this.boxed = boxed); 551 | } 552 | 553 | protected void setColorModel(ColorModelSet colorModel) { 554 | getPropertyChangeSupport().firePropertyChange("colorModel", this.colorModel, this.colorModel = colorModel); 555 | if (colorModel != null) { 556 | colorModel.setPlotColor(plotColor); // this shouls be handled by the model itself, without any 557 | colorModel.setPlotType(plotType); 558 | } 559 | } 560 | 561 | public void setContourLines(int contourLines) { 562 | getPropertyChangeSupport().firePropertyChange("contourLines", this.contourLines, this.contourLines = contourLines); 563 | } 564 | 565 | public void setContourType(boolean val) { 566 | setPlotType(val ? PlotType.CONTOUR : PlotType.SURFACE); 567 | } 568 | 569 | public void setDataAvailable(boolean dataAvailable) { 570 | getPropertyChangeSupport().firePropertyChange("dataAvailable", this.dataAvailable, this.dataAvailable = dataAvailable); 571 | } 572 | 573 | public void setDensityType(boolean val) { 574 | setPlotType(val ? PlotType.DENSITY : PlotType.SURFACE); 575 | } 576 | 577 | public void setDispDivisions(int dispDivisions) { 578 | getPropertyChangeSupport().firePropertyChange("dispDivisions", this.dispDivisions, this.dispDivisions = dispDivisions); 579 | } 580 | 581 | public void setDualShadeMode(boolean val) { 582 | setPlotColor(val ? PlotColor.DUALSHADE : PlotColor.SPECTRUM); 583 | } 584 | 585 | public void setFirstFunctionOnly(boolean val) { 586 | setPlotFunction12(val, !val); 587 | } 588 | 589 | public void setFogMode(boolean val) { 590 | setPlotColor(val ? PlotColor.FOG : PlotColor.SPECTRUM); 591 | } 592 | 593 | public void setGrayScaleMode(boolean val) { 594 | setPlotColor(val ? PlotColor.GRAYSCALE : PlotColor.SPECTRUM); 595 | } 596 | 597 | public void setHiddenMode(boolean val) { 598 | setPlotColor(val ? PlotColor.OPAQUE : PlotColor.SPECTRUM); 599 | } 600 | 601 | 602 | /** 603 | * Sets the text of status line 604 | * 605 | * @param text 606 | * new text to be displayed 607 | */ 608 | 609 | public void setMessage(String text) { 610 | // @todo 611 | // System.out.println("Message"+text); 612 | } 613 | 614 | public void setPlotFunction1(boolean plotFunction1) { 615 | setPlotFunction12(plotFunction1, plotFunction2); 616 | } 617 | 618 | public void setPlotColor(PlotColor plotColor) { 619 | PlotColor old = this.plotColor; 620 | getPropertyChangeSupport().firePropertyChange("plotColor", this.plotColor, this.plotColor = plotColor); 621 | fireAllMode(old, this.plotColor); 622 | if (colorModel != null) 623 | colorModel.setPlotColor(plotColor); // this should be handled by the model itself, without any 624 | } 625 | 626 | public void setPlotFunction12(boolean p1, boolean p2) { 627 | boolean o1 = this.plotFunction1; 628 | boolean o2 = this.plotFunction2; 629 | 630 | this.plotFunction1 = hasFunction1 && p1; 631 | property.firePropertyChange("plotFunction1", o1, p1); 632 | 633 | this.plotFunction2 = hasFunction2 && p2; 634 | property.firePropertyChange("plotFunction1", o2, p2); 635 | fireAllFunction(o1, o2); 636 | } 637 | 638 | public void setPlotFunction2(boolean v) { 639 | setPlotFunction12(plotFunction1, plotFunction2); 640 | } 641 | 642 | public void setPlotType(PlotType plotType) { 643 | PlotType o = this.plotType; 644 | this.plotType = plotType; 645 | if (colorModel != null) 646 | colorModel.setPlotType(plotType); // this should be handled by the model itself, without any 647 | property.firePropertyChange("plotType", o, this.plotType); 648 | fireAllType(o, this.plotType); 649 | } 650 | 651 | public void setSecondFunctionOnly(boolean val) { 652 | setPlotFunction12(!val, val); 653 | } 654 | 655 | public void setSpectrumMode(boolean val) { 656 | setPlotColor(val ? PlotColor.SPECTRUM : PlotColor.GRAYSCALE); 657 | } 658 | 659 | public void setSurfaceType(boolean val) { 660 | setPlotType(val ? PlotType.SURFACE : PlotType.WIREFRAME); 661 | } 662 | 663 | public void setWireframeType(boolean val) { 664 | if (val) 665 | setPlotType(PlotType.WIREFRAME); 666 | else 667 | setPlotType(PlotType.SURFACE); 668 | } 669 | 670 | public void setXMax(float xMax) { 671 | getPropertyChangeSupport().firePropertyChange("xMax", this.xMax, this.xMax = xMax); 672 | } 673 | 674 | public void setXMin(float xMin) { 675 | getPropertyChangeSupport().firePropertyChange("xMin", this.xMin, this.xMin = xMin); 676 | } 677 | 678 | public void setYMax(float yMax) { 679 | getPropertyChangeSupport().firePropertyChange("yMax", this.yMax, this.yMax = yMax); 680 | } 681 | 682 | public void setYMin(float yMin) { 683 | getPropertyChangeSupport().firePropertyChange("yMin", this.yMin, this.yMin = yMin); 684 | } 685 | 686 | public void setZMax(float zMax) { 687 | if (zMax <= zMin) 688 | return; 689 | getPropertyChangeSupport().firePropertyChange("zMax", this.zMax, this.zMax = zMax); 690 | } 691 | 692 | public void setZMin(float zMin) { 693 | if (zMin >= zMax) 694 | return; 695 | getPropertyChangeSupport().firePropertyChange("zMin", this.zMin, this.zMin = zMin); 696 | } 697 | 698 | public void setDisplayGrids(boolean displayGrids) { 699 | getPropertyChangeSupport().firePropertyChange("displayGrids", this.displayGrids, this.displayGrids = displayGrids); 700 | } 701 | 702 | public void setDisplayXY(boolean displayXY) { 703 | getPropertyChangeSupport().firePropertyChange("displayXY", this.displayXY, this.displayXY = displayXY); 704 | } 705 | 706 | public void setDisplayZ(boolean displayZ) { 707 | getPropertyChangeSupport().firePropertyChange("displayZ", this.displayZ, this.displayZ = displayZ); 708 | } 709 | 710 | public void setExpectDelay(boolean expectDelay) { 711 | getPropertyChangeSupport().firePropertyChange("expectDelay", this.expectDelay, this.expectDelay = expectDelay); 712 | } 713 | 714 | public void setMesh(boolean mesh) { 715 | getPropertyChangeSupport().firePropertyChange("mesh", this.mesh, this.mesh = mesh); 716 | } 717 | 718 | public void setScaleBox(boolean scaleBox) { 719 | getPropertyChangeSupport().firePropertyChange("scaleBox", this.scaleBox, this.scaleBox = scaleBox); 720 | } 721 | 722 | public void toggleAutoScaleZ() { 723 | setAutoScaleZ(!isAutoScaleZ()); 724 | } 725 | 726 | public void toggleBoxed() { 727 | setBoxed(!isBoxed()); 728 | } 729 | 730 | 731 | 732 | public void setCalcDivisions(int calcDivisions) { 733 | getPropertyChangeSupport().firePropertyChange("calcDivisions", this.calcDivisions, this.calcDivisions = calcDivisions); 734 | } 735 | 736 | /** 737 | * Processes menu events 738 | * 739 | * @param item 740 | * the selected menu item 741 | */ 742 | 743 | public void toggleDisplayGrids() { 744 | setDisplayGrids(!isDisplayGrids()); 745 | } 746 | 747 | /** 748 | * Sets file name 749 | */ 750 | 751 | public void toggleDisplayXY() { 752 | setDisplayXY(!isDisplayXY()); 753 | } 754 | 755 | public void toggleDisplayZ() { 756 | setDisplayZ(!isDisplayZ()); 757 | } 758 | 759 | public void toggleExpectDelay() { 760 | setExpectDelay(!isExpectDelay()); 761 | } 762 | 763 | public void toggleMesh() { 764 | setMesh(!isMesh()); 765 | } 766 | 767 | public void togglePlotFunction1() { 768 | setPlotFunction1(!isPlotFunction1()); 769 | 770 | } 771 | 772 | public void togglePlotFunction2() { 773 | setPlotFunction2(!isPlotFunction2()); 774 | 775 | } 776 | 777 | public void toggleScaleBox() { 778 | setScaleBox(!isScaleBox()); 779 | } 780 | 781 | } 782 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/ArraySurfaceModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | public class ArraySurfaceModel extends AbstractSurfaceModel { 4 | 5 | SurfaceVertex[][] surfaceVertex; 6 | 7 | /** Creates two surfaces using data from the array. 8 | * 9 | * @param xmin lower bound of x values 10 | * @param xmax upper bound of x values 11 | * @param ymin lower bound of y values 12 | * @param ymax upper bound of y values 13 | * @param size number of items in each dimensions (ie z1 = float[size][size] ) 14 | * @param z1 value matrix (null supported) 15 | * @param z2 secondary function value matrix (null supported) 16 | */ 17 | public void setValues(float xmin, float xmax, float ymin, float ymax, int size, float[][] z1, float[][] z2) { 18 | setDataAvailable(false); // clean space 19 | setXMin(xmin); 20 | setXMax(xmax); 21 | setYMin(ymin); 22 | setYMax(ymax); 23 | setCalcDivisions(size-1); 24 | 25 | final float stepx = (xMax - xMin) / calcDivisions; 26 | final float stepy = (yMax - yMin) / calcDivisions; 27 | final float xfactor = 20 / (xMax - xMin); // 20 aint magic: surface vertex requires a value in [-10 ; 10] 28 | final float yfactor = 20 / (yMax - yMin); 29 | 30 | final int total = (calcDivisions + 1) * (calcDivisions + 1); // compute total size 31 | surfaceVertex = new SurfaceVertex[2][total]; 32 | 33 | 34 | for (int i = 0; i <= calcDivisions; i++) 35 | for (int j = 0; j <= calcDivisions; j++) { 36 | int k = i * (calcDivisions + 1) + j; 37 | 38 | float xv = xMin + i * stepx; 39 | float yv = yMin + j * stepy; 40 | float v1 = z1!=null?z1[i][j]:Float.NaN; 41 | if (Float.isInfinite(v1)) 42 | v1 = Float.NaN; 43 | if (!Float.isNaN(v1)) { 44 | if (Float.isNaN(z1Max) || (v1 > z1Max)) 45 | z1Max = v1; 46 | else if (Float.isNaN(z1Min) || (v1 < z1Min)) 47 | z1Min = v1; 48 | } 49 | 50 | surfaceVertex[0][k] = new SurfaceVertex((xv - xMin) * xfactor - 10, (yv - yMin) * yfactor - 10, v1); 51 | float v2 = z2!=null?z2[i][j]:Float.NaN; 52 | if (Float.isInfinite(v2)) 53 | v2 = Float.NaN; 54 | if (!Float.isNaN(v2)) { 55 | if (Float.isNaN(z2Max) || (v2 > z2Max)) 56 | z2Max = v2; 57 | else if (Float.isNaN(z2Min) || (v2 < z2Min)) 58 | z2Min = v2; 59 | } 60 | 61 | surfaceVertex[1][k] = new SurfaceVertex((xv - xMin) * xfactor - 10, (yv - yMin) * yfactor - 10, v2); 62 | } 63 | 64 | 65 | autoScale(); 66 | setDataAvailable(true); 67 | fireStateChanged(); 68 | } 69 | 70 | public SurfaceVertex[][] getSurfaceVertex() { 71 | return surfaceVertex; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/ColorModel.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | import java.awt.Color; 4 | 5 | 6 | /** Stands for a Color Model 7 | 8 | * @author Eric 9 | * @date 8 avril 2004 15:18:27 10 | */ 11 | public class ColorModel 12 | { 13 | public static final byte DUALSHADE=0; 14 | public static final byte SPECTRUM=1; 15 | public static final byte FOG=2; 16 | public static final byte OPAQUE=3; 17 | 18 | 19 | float hue; 20 | float sat; 21 | float bright; 22 | float min; // hue|sat|bright of z=0 23 | float max; // Hue|sat|bright of z=1 24 | byte mode=0; 25 | 26 | Color ocolor; // fixed color for opaque mode 27 | 28 | 29 | public ColorModel(byte mode,float hue,float sat, float bright,float min,float max) 30 | { 31 | this.mode=mode; 32 | this.hue=hue; 33 | this.sat=sat; 34 | this.bright= bright; 35 | this.min=min; 36 | this.max=max; 37 | } 38 | 39 | 40 | 41 | public Color getPolygonColor(float z) 42 | { 43 | if (z<0 || z>1) return Color.WHITE; 44 | switch(mode) 45 | { 46 | case DUALSHADE: 47 | { 48 | return color(hue,sat, norm(z)); 49 | } 50 | case SPECTRUM: 51 | { 52 | return color(norm(1-z),sat, bright); 53 | //return color(norm(1-z),0.3f+z*(0.7f), bright); 54 | } 55 | case FOG: 56 | { 57 | return color(hue,norm(z), bright); 58 | } 59 | case OPAQUE: 60 | { 61 | if (ocolor==null) ocolor=color(hue,sat, bright); 62 | return ocolor; 63 | } 64 | } 65 | return Color.WHITE;//default 66 | } 67 | 68 | 69 | 70 | /** 71 | * @param hue 72 | * @param sat 73 | * @param bright 74 | * @return 75 | */ 76 | private Color color(float hue, float sat, float bright) { 77 | Color hsb = Color.getHSBColor(hue, sat, bright); 78 | // transparency management: unfortunately we reached power limits of 2010's computers it's laggy 79 | //return new Color(hsb.getRed(), hsb.getGreen(), hsb.getBlue(), 128); 80 | return hsb; 81 | } 82 | 83 | 84 | 85 | private float norm(float z) 86 | { 87 | if (min==max) return min; 88 | return min+z*(max-min); 89 | } 90 | 91 | 92 | 93 | }//end of class 94 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/ColorModelSet.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | import java.awt.Color; 4 | 5 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotColor; 6 | import net.ericaro.surfaceplotter.surface.SurfaceModel.PlotType; 7 | 8 | 9 | /** A simple {@link SurfaceColor} implementations that uses two ColorMode per plot type. 10 | 11 | * @author Eric 12 | * @date jeudi 8 avril 2004 15:45:40 13 | */ 14 | public class ColorModelSet implements SurfaceColor 15 | { 16 | 17 | public static float RED_H=0.941896f; 18 | public static float RED_S=0.7517241f; 19 | public static float RED_B=0.5686275f; 20 | 21 | public static float GOLD_H=0.1f; 22 | public static float GOLD_S=0.9497207f; 23 | public static float GOLD_B=0.7019608f; 24 | 25 | 26 | protected ColorModel dualshade; 27 | protected ColorModel grayscale; 28 | protected ColorModel spectrum; 29 | protected ColorModel fog; 30 | protected ColorModel opaque; 31 | 32 | protected ColorModel alt_dualshade; 33 | protected ColorModel alt_grayscale; 34 | protected ColorModel alt_spectrum; 35 | protected ColorModel alt_fog; 36 | protected ColorModel alt_opaque; 37 | 38 | protected Color lineColor=Color.DARK_GRAY; 39 | protected Color lineboxColor=Color.getHSBColor(0f,0f,0.5f); 40 | protected Color lightColor=Color.WHITE; 41 | // Color(192,220,192); existing 42 | protected Color boxColor=Color.getHSBColor(0f,0f,0.95f);//Color.getHSBColor(226f/240f,145f/240f,1f); 43 | 44 | public ColorModelSet() 45 | { 46 | /* 47 | float[] f = Color.RGBtoHSB(255,255,255, new float[4]); 48 | System.out.print("DP_RED=("); 49 | for (int i=0;i<3;i++) { System.out.println((i==0?"":",")+f[i]);} 50 | */ 51 | 52 | dualshade= new ColorModel( ColorModel.DUALSHADE, RED_H , RED_S , RED_B , 0.4f , 1f ); 53 | grayscale= new ColorModel( ColorModel.DUALSHADE, 0f , 0f , 0f , 0f , 1f ); 54 | spectrum= new ColorModel( ColorModel.SPECTRUM , 0f , 1f , 1f , 0f , .6666f ); 55 | fog= new ColorModel( ColorModel.FOG , RED_H , RED_S , RED_B , 0f , 1f ); 56 | opaque= new ColorModel( ColorModel.OPAQUE , RED_H , 0.1f , 1f , 0f , 0f ); 57 | 58 | 59 | 60 | alt_dualshade= new ColorModel( ColorModel.DUALSHADE, GOLD_H , GOLD_S , GOLD_B , 0.4f , 1f ); 61 | alt_grayscale= new ColorModel( ColorModel.DUALSHADE, 0f , 0f , 0f , 0f , 1f ); 62 | alt_spectrum= new ColorModel( ColorModel.SPECTRUM , 0f , 1f , 0.8f , 0f , .6666f ); 63 | alt_fog= new ColorModel( ColorModel.FOG , GOLD_H , 0f , GOLD_B , 0f , 1f ); 64 | alt_opaque= new ColorModel( ColorModel.OPAQUE , GOLD_H , 0.1f , 1f , 0f , 0f ); 65 | 66 | } 67 | 68 | protected PlotColor color_mode= PlotColor.SPECTRUM; 69 | public void setPlotColor(PlotColor v) 70 | { 71 | this.color_mode=v; 72 | } 73 | protected PlotType plot_mode= PlotType.CONTOUR; 74 | public void setPlotType(PlotType type) 75 | { 76 | this.plot_mode=type; 77 | } 78 | 79 | /* (non-Javadoc) 80 | * @see net.ericaro.surfaceplotter.SurfaceColor#getBackgroundColor() 81 | */ 82 | public Color getBackgroundColor(){return lightColor;} 83 | /* (non-Javadoc) 84 | * @see net.ericaro.surfaceplotter.SurfaceColor#getLineBoxColor() 85 | */ 86 | public Color getLineBoxColor() {return lineboxColor;} 87 | /* (non-Javadoc) 88 | * @see net.ericaro.surfaceplotter.SurfaceColor#getBoxColor() 89 | */ 90 | public Color getBoxColor() {return boxColor;} 91 | /* (non-Javadoc) 92 | * @see net.ericaro.surfaceplotter.SurfaceColor#getLineColor() 93 | */ 94 | public Color getLineColor(){return lineColor;} 95 | /* (non-Javadoc) 96 | * @see net.ericaro.surfaceplotter.SurfaceColor#getTextColor() 97 | */ 98 | public Color getTextColor() {return lineColor;} 99 | 100 | /* (non-Javadoc) 101 | * @see net.ericaro.surfaceplotter.SurfaceColor#getLineColor(int, float) 102 | */ 103 | public Color getLineColor(int curve, float z) 104 | { 105 | return Color.BLACK; 106 | //return Color.BLUE; 107 | /** 108 | if (plot_mode==PlotType.WIREFRAME) 109 | { 110 | return Color.BLACK; 111 | } 112 | return getPolygonColor(curve, 1-z); 113 | /* 114 | if ( 115 | color_mode==PlotColor.GRAYSCALE || 116 | color_mode==PlotColor.SPECTRUM|| 117 | color_mode==PlotColor.DUALSHADE) 118 | return grayscale.getPolygonColor(1-z); 119 | else return Color.DARK_GRAY; 120 | */ 121 | /* 122 | Color c= getPolygonColor(curve, z); 123 | float[] f= c.getComponents(new float[4]); 124 | float ff=f[2]; 125 | if (ff<0.5f) ff=1f; 126 | if (ff<0) ff++; 127 | */ 128 | //return Color.getHSBColor(f[0],f[1],ff); 129 | /**/ 130 | } 131 | 132 | /* (non-Javadoc) 133 | * @see net.ericaro.surfaceplotter.SurfaceColor#getPolygonColor(int, float) 134 | */ 135 | public Color getPolygonColor(int curve, float z) 136 | { 137 | if (curve==1) return getFirstPolygonColor(z); 138 | if (curve==2) return getSecondPolygonColor(z); 139 | return Color.blue; 140 | } 141 | 142 | /* (non-Javadoc) 143 | * @see net.ericaro.surfaceplotter.SurfaceColor#getFirstPolygonColor(float) 144 | */ 145 | public Color getFirstPolygonColor(float z) 146 | { 147 | //contour,density plot does not fit with opaque color 148 | if(plot_mode==PlotType.CONTOUR ||plot_mode==PlotType.DENSITY) 149 | { 150 | if (color_mode==PlotColor.OPAQUE) 151 | return dualshade.getPolygonColor(z); 152 | } 153 | 154 | switch ( color_mode) 155 | { 156 | case OPAQUE :return opaque.getPolygonColor(z); 157 | case GRAYSCALE :return grayscale.getPolygonColor(z); 158 | case SPECTRUM :return spectrum.getPolygonColor(z); 159 | case DUALSHADE :return dualshade.getPolygonColor(z); 160 | case FOG :return fog.getPolygonColor(z); 161 | default: return Color.blue; 162 | } 163 | } 164 | 165 | /* (non-Javadoc) 166 | * @see net.ericaro.surfaceplotter.SurfaceColor#getSecondPolygonColor(float) 167 | */ 168 | public Color getSecondPolygonColor(float z) 169 | { 170 | //contour,density plot does not fit with opaque color 171 | if(plot_mode==PlotType.CONTOUR ||plot_mode==PlotType.DENSITY) 172 | { 173 | if (color_mode==PlotColor.OPAQUE) 174 | return alt_dualshade.getPolygonColor(z); 175 | } 176 | switch ( color_mode) 177 | { 178 | case OPAQUE :return alt_opaque.getPolygonColor(z); 179 | case GRAYSCALE :return alt_grayscale.getPolygonColor(z); 180 | case SPECTRUM :return alt_spectrum.getPolygonColor(z); 181 | case DUALSHADE :return alt_dualshade.getPolygonColor(z); 182 | case FOG :return alt_fog.getPolygonColor(z); 183 | default: return Color.blue; 184 | } 185 | } 186 | 187 | /* 188 | protected float dualshadeColorFirstHue=0.2f;//0.7f;//0.1f;//0.941f; // first curve hue color 189 | protected float dualshadeColorSecondHue=0.7f; 190 | protected float dualshadeSaturation = 0.9125f;//0.604f; // 191 | protected float dualshadeOffset=0.3f; 192 | protected float whiteblack = 0.3f; 193 | 194 | 195 | */ 196 | 197 | }//end of class 198 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/LineAccumulator.java: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------------------* 2 | * LineAccumulator.java * 3 | * * 4 | * Surface Plotter version 1.30b1 17 May 1997 * 5 | * version 1.30b2 18 Oct 2001 * 6 | * * 7 | * Copyright (c) Yanto Suryono * 8 | * * 9 | * This program is free software; you can redistribute it and/or modify it * 10 | * under the terms of the GNU Lesser General Public License as published by the * 11 | * Free Software Foundation; either version 2 of the License, or (at your option) * 12 | * any later version. * 13 | * * 14 | * This program is distributed in the hope that it will be useful, but * 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * 17 | * more details. * 18 | * * 19 | * You should have received a copy of the GNU Lesser General Public License along * 20 | * with this program; if not, write to the Free Software Foundation, Inc., * 21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 22 | * * 23 | *----------------------------------------------------------------------------------------*/ 24 | 25 | /* eric: moved from Vector to List, and LinkedList 26 | * 27 | */ 28 | package net.ericaro.surfaceplotter.surface; 29 | 30 | import java.awt.Graphics; 31 | import java.util.LinkedList; 32 | import java.util.List; 33 | 34 | /** 35 | * The class LineAccumulator accumulates line drawing information and 36 | * then draws all accumulated lines together. It is used as contour lines accumulator 37 | * in Surface Plotter. 38 | * 39 | * @author Yanto Suryono 40 | */ 41 | 42 | public class LineAccumulator { 43 | private List accumulator; 44 | 45 | /** 46 | * The constructor of LineAccumulator 47 | */ 48 | 49 | LineAccumulator() { 50 | accumulator = new LinkedList(); 51 | } 52 | 53 | /** 54 | * Adds a line to the accumulator. 55 | * 56 | * @param x1 the first point's x coordinate 57 | * @param y1 the first point's y coordinate 58 | * @param x2 the second point's x coordinate 59 | * @param y2 the second point's y coordinate 60 | */ 61 | 62 | public void addLine(int x1, int y1, int x2, int y2) { 63 | if (x1<=0 || y1<=0 || x2<=0 || y2<=0 ) return; 64 | //System.out.println("("+x1+","+y1+","+x2+","+y2+")"); 65 | accumulator.add(new LineRecord(x1,y1,x2,y2)); 66 | } 67 | 68 | 69 | 70 | /** 71 | * Clears accumulator. 72 | */ 73 | 74 | public void clearAccumulator() { 75 | accumulator.clear(); 76 | } 77 | 78 | /** 79 | * Draws all accumulated lines. 80 | * 81 | * @param g the graphics context to draw 82 | */ 83 | 84 | public void drawAll(Graphics g) { 85 | for(LineRecord line: accumulator) 86 | g.drawLine(line.x1,line.y1,line.x2,line.y2); 87 | } 88 | } 89 | 90 | /** 91 | * Represents a stright line. 92 | * Used by LineAccumulator class. 93 | * 94 | * @see LineAccumulator 95 | */ 96 | 97 | class LineRecord { 98 | /** 99 | * @param x1 the first point's x coordinate 100 | */ 101 | public final int x1; 102 | 103 | /** 104 | * @param y1 the first point's y coordinate 105 | */ 106 | public final int y1; 107 | 108 | /** 109 | * @param x2 the second point's x coordinate 110 | */ 111 | public final int x2; 112 | 113 | /** 114 | * @param y2 the second point's y coordinate 115 | */ 116 | public final int y2; 117 | 118 | /** 119 | * The constructor of LineRecord 120 | * 121 | * @param x1 the first point's x coordinate 122 | * @param y1 the first point's y coordinate 123 | * @param x2 the second point's x coordinate 124 | * @param y2 the second point's y coordinate 125 | */ 126 | 127 | LineRecord(int x1, int y1, int x2, int y2) { 128 | super(); 129 | this.x1 = x1; this.y1 = y1; 130 | this.x2 = x2; this.y2 = y2; 131 | } 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/Projector.java: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------------------* 2 | * Projector.java version 1.7 Nov 8 1996 * 3 | * Projector.java version 1.71 May 14 1997 * 4 | * * 5 | * Copyright (c) Yanto Suryono * 6 | * * 7 | * This program is free software; you can redistribute it and/or modify it * 8 | * under the terms of the GNU Lesser General Public License as published by the * 9 | * Free Software Foundation; either version 2 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * This program is distributed in the hope that it will be useful, but * 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * 15 | * more details. * 16 | * * 17 | * You should have received a copy of the GNU Lesser General Public License along * 18 | * with this program; if not, write to the Free Software Foundation, Inc., * 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 20 | * * 21 | *----------------------------------------------------------------------------------------*/ 22 | package net.ericaro.surfaceplotter.surface; 23 | 24 | import java.awt.Point; 25 | import java.awt.Rectangle; 26 | 27 | /** 28 | * The class Projector projects points in 3D space to 2D space. 29 | * 30 | * @author Yanto Suryono 31 | */ 32 | 33 | public final class Projector { 34 | private float scale_x, scale_y, scale_z; // 3D scaling factor 35 | private float distance; // distance to object 36 | private float _2D_scale; // 2D scaling factor 37 | private float rotation, elevation; // rotation and elevation angle 38 | private float sin_rotation, cos_rotation; // sin and cos of rotation angle 39 | private float sin_elevation, cos_elevation; // sin and cos of elevation angle 40 | private int _2D_trans_x, _2D_trans_y; // 2D translation 41 | private int x1, x2, y1, y2; // projection area 42 | private int center_x, center_y; // center of projection area 43 | 44 | private int trans_x, trans_y; 45 | private float factor; 46 | private float sx_cos, sy_cos, sz_cos; 47 | private float sx_sin, sy_sin, sz_sin; 48 | 49 | private final float DEGTORAD = (float)Math.PI / 180; 50 | 51 | //was static in SurfaceVertex ! now Dynamic in Projector 52 | float zmin, zmax; 53 | float zfactor; 54 | 55 | 56 | /** 57 | * The constructor of Projector. 58 | */ 59 | 60 | public Projector() { 61 | setScaling(1); 62 | setRotationAngle(0); 63 | setElevationAngle(0); 64 | setDistance(10); 65 | set2DScaling(1); 66 | set2DTranslation(0,0); 67 | } 68 | 69 | /** 70 | * Sets the projection area. 71 | * 72 | * @param r the projection area 73 | */ 74 | 75 | public void setProjectionArea(Rectangle r) { 76 | x1 = r.x; x2 = x1 + r.width; 77 | y1 = r.y; y2 = y1 + r.height; 78 | center_x = (x1 + x2) / 2; 79 | center_y = (y1 + y2) / 2; 80 | 81 | trans_x = center_x + _2D_trans_x; 82 | trans_y = center_y + _2D_trans_y; 83 | } 84 | 85 | /** 86 | * Sets the rotation angle. 87 | * 88 | * @param angle the rotation angle in degrees 89 | */ 90 | 91 | public void setRotationAngle(float angle) { 92 | rotation = angle; 93 | sin_rotation = (float)Math.sin(angle * DEGTORAD); 94 | cos_rotation = (float)Math.cos(angle * DEGTORAD); 95 | 96 | sx_cos = -scale_x * cos_rotation; 97 | sx_sin = -scale_x * sin_rotation; 98 | sy_cos = -scale_y * cos_rotation; 99 | sy_sin = scale_y * sin_rotation; 100 | } 101 | 102 | /** 103 | * Gets current rotation angle. 104 | * 105 | * @return the rotation angle in degrees. 106 | */ 107 | 108 | public float getRotationAngle() { 109 | return rotation; 110 | } 111 | 112 | /** 113 | * Gets the sine of rotation angle. 114 | * 115 | * @return the sine of rotation angle 116 | */ 117 | 118 | public float getSinRotationAngle() { 119 | return sin_rotation; 120 | } 121 | 122 | /** 123 | * Gets the cosine of rotation angle. 124 | * 125 | * @return the cosine of rotation angle 126 | */ 127 | 128 | public float getCosRotationAngle() { 129 | return cos_rotation; 130 | } 131 | 132 | /** 133 | * Sets the elevation angle. 134 | * 135 | * @param angle the elevation angle in degrees 136 | */ 137 | 138 | public void setElevationAngle(float angle) { 139 | elevation = angle; 140 | sin_elevation = (float)Math.sin(angle * DEGTORAD); 141 | cos_elevation = (float)Math.cos(angle * DEGTORAD); 142 | sz_cos = scale_z * cos_elevation; 143 | sz_sin = scale_z * sin_elevation; 144 | } 145 | 146 | /** 147 | * Gets current elevation angle. 148 | * 149 | * @return the elevation angle in degrees. 150 | */ 151 | 152 | public float getElevationAngle() { 153 | return elevation; 154 | } 155 | 156 | /** 157 | * Gets the sine of elevation angle. 158 | * 159 | * @return the sine of elevation angle 160 | */ 161 | 162 | public float getSinElevationAngle() { 163 | return sin_elevation; 164 | } 165 | 166 | /** 167 | * Gets the cosine of elevation angle. 168 | * 169 | * @return the cosine of elevation angle 170 | */ 171 | 172 | public float getCosElevationAngle() { 173 | return cos_elevation; 174 | } 175 | 176 | /** 177 | * Sets the projector distance. 178 | * 179 | * @param new_distance the new distance 180 | */ 181 | 182 | public void setDistance(float new_distance) { 183 | distance = new_distance; 184 | factor = distance * _2D_scale; 185 | } 186 | 187 | /** 188 | * Gets the projector distance. 189 | * 190 | * @return the projector distance 191 | */ 192 | 193 | public float getDistance() { 194 | return distance; 195 | } 196 | 197 | /** 198 | * Sets the scaling factor in x direction. 199 | * 200 | * @param scaling the scaling factor 201 | */ 202 | 203 | public void setXScaling(float scaling) { 204 | scale_x = scaling; 205 | sx_cos = -scale_x * cos_rotation; 206 | sx_sin = -scale_x * sin_rotation; 207 | } 208 | 209 | /** 210 | * Gets the scaling factor in x direction. 211 | * 212 | * @return the scaling factor 213 | */ 214 | 215 | public float getXScaling() { 216 | return scale_x; 217 | } 218 | 219 | /** 220 | * Sets the scaling factor in y direction. 221 | * 222 | * @param scaling the scaling factor 223 | */ 224 | 225 | public void setYScaling(float scaling) { 226 | scale_y = scaling; 227 | sy_cos = -scale_y * cos_rotation; 228 | sy_sin = scale_y * sin_rotation; 229 | } 230 | 231 | /** 232 | * Gets the scaling factor in y direction. 233 | * 234 | * @return the scaling factor 235 | */ 236 | 237 | public float getYScaling() { 238 | return scale_y; 239 | } 240 | 241 | /** 242 | * Sets the scaling factor in z direction. 243 | * 244 | * @param scaling the scaling factor 245 | */ 246 | 247 | public void setZScaling(float scaling) { 248 | scale_z = scaling; 249 | sz_cos = scale_z * cos_elevation; 250 | sz_sin = scale_z * sin_elevation; 251 | } 252 | 253 | /** 254 | * Gets the scaling factor in z direction. 255 | * 256 | * @return the scaling factor 257 | */ 258 | 259 | public float getZScaling() { 260 | return scale_z; 261 | } 262 | 263 | /** 264 | * Sets the scaling factor in all direction. 265 | * 266 | * @param x the scaling factor in x direction 267 | * @param y the scaling factor in y direction 268 | * @param z the scaling factor in z direction 269 | */ 270 | 271 | public void setScaling(float x, float y, float z) { 272 | scale_x = x; scale_y = y; scale_z = z; 273 | 274 | sx_cos = -scale_x * cos_rotation; 275 | sx_sin = -scale_x * sin_rotation; 276 | sy_cos = -scale_y * cos_rotation; 277 | sy_sin = scale_y * sin_rotation; 278 | sz_cos = scale_z * cos_elevation; 279 | sz_sin = scale_z * sin_elevation; 280 | } 281 | 282 | /** 283 | * Sets the same scaling factor for all direction. 284 | * 285 | * @param scaling the scaling factor 286 | */ 287 | 288 | public void setScaling(float scaling) { 289 | scale_x = scale_y = scale_z = scaling; 290 | 291 | sx_cos = -scale_x * cos_rotation; 292 | sx_sin = -scale_x * sin_rotation; 293 | sy_cos = -scale_y * cos_rotation; 294 | sy_sin = scale_y * sin_rotation; 295 | sz_cos = scale_z * cos_elevation; 296 | sz_sin = scale_z * sin_elevation; 297 | } 298 | 299 | /** 300 | * Sets the 2D scaling factor. 301 | * 302 | * @param scaling the scaling factor 303 | */ 304 | 305 | public void set2DScaling(float scaling) { 306 | _2D_scale = scaling; 307 | factor = distance * _2D_scale; 308 | } 309 | 310 | /** 311 | * Gets the 2D scaling factor. 312 | * 313 | * @return the scaling factor 314 | */ 315 | 316 | public float get2DScaling() { 317 | return _2D_scale; 318 | } 319 | 320 | /** 321 | * Sets the 2D translation. 322 | * 323 | * @param x the x translation 324 | * @param y the y translation 325 | */ 326 | 327 | public void set2DTranslation(int x, int y) { 328 | _2D_trans_x = x; _2D_trans_y = y; 329 | 330 | trans_x = center_x + _2D_trans_x; 331 | trans_y = center_y + _2D_trans_y; 332 | } 333 | 334 | /** 335 | * Sets the 2D x translation. 336 | * 337 | * @param x the x translation 338 | */ 339 | 340 | public void set2D_xTranslation(int x) { 341 | _2D_trans_x = x; 342 | trans_x = center_x + _2D_trans_x; 343 | } 344 | 345 | /** 346 | * Gets the 2D x translation. 347 | * 348 | * @return the x translation 349 | */ 350 | 351 | public int get2D_xTranslation() { 352 | return _2D_trans_x; 353 | } 354 | 355 | /** 356 | * Sets the 2D y translation. 357 | * 358 | * @param y the y translation 359 | */ 360 | 361 | public void set2D_yTranslation(int y) { 362 | _2D_trans_y = y; 363 | trans_y = center_y + _2D_trans_y; 364 | } 365 | 366 | /** 367 | * Gets the 2D y translation. 368 | * 369 | * @return the y translation 370 | */ 371 | 372 | public int get2D_yTranslation() { 373 | return _2D_trans_y; 374 | } 375 | 376 | /** 377 | * Projects 3D points. 378 | * 379 | * @param x the x coordinate 380 | * @param y the y coordinate 381 | * @param z the z coordinate 382 | */ 383 | 384 | public final Point project(float x, float y, float z) { 385 | float temp; 386 | 387 | // rotates 388 | 389 | temp = x; 390 | x = x * sx_cos + y * sy_sin; 391 | y = temp * sx_sin + y * sy_cos; 392 | 393 | // elevates and projects 394 | 395 | temp = factor / (y * cos_elevation - z * sz_sin + distance); 396 | return new Point((int)(Math.round(x * temp) + trans_x), 397 | (int)(Math.round((y * sin_elevation + z * sz_cos) * -temp) + trans_y)); 398 | } 399 | 400 | 401 | 402 | public void setZRange(float zmin, float zmax) { 403 | this.zmin = zmin; this.zmax = zmax; 404 | this.zfactor = 20/(zmax-zmin); 405 | } 406 | 407 | } 408 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/SurfaceColor.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | import java.awt.Color; 4 | 5 | /** Interface used by JSurface for every color. Warning, some color are not suitable for some drawing, be careful to sync it with the SurfaceModel 6 | * 7 | * @author eric 8 | * 9 | */ 10 | public interface SurfaceColor { 11 | 12 | public Color getBackgroundColor(); 13 | 14 | public Color getLineBoxColor(); 15 | 16 | public Color getBoxColor(); 17 | 18 | public Color getLineColor(); 19 | 20 | public Color getTextColor(); 21 | 22 | public Color getLineColor(int curve, float z); 23 | 24 | public Color getPolygonColor(int curve, float z); 25 | 26 | public Color getFirstPolygonColor(float z); 27 | 28 | public Color getSecondPolygonColor(float z); 29 | 30 | } -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/SurfaceModel.java: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------------------* 2 | * SurfaceModel.java * 3 | * * 4 | * Surface Plotter version 1.10 14 Oct 1996 * 5 | * version 1.20 8 Nov 1996 * 6 | * version 1.30b1 17 May 1997 * 7 | * bug fixed 21 May 1997 * 8 | * version 1.30b2 18 Oct 2001 * 9 | * * 10 | * Copyright (c) Yanto Suryono * 11 | * * 12 | * This program is free software; you can redistribute it and/or modify it * 13 | * under the terms of the GNU Lesser General Public License as published by the * 14 | * Free Software Foundation; either version 2 of the License, or (at your option) * 15 | * any later version. * 16 | * * 17 | * This program is distributed in the hope that it will be useful, but * 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * 20 | * more details. * 21 | * * 22 | * You should have received a copy of the GNU Lesser General Public License along * 23 | * with this program; if not, write to the Free Software Foundation, Inc., * 24 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 25 | * 26 | Modified : Eric : remove every graphical stuff to get rid of Frame 27 | *----------------------------------------------------------------------------------------*/ 28 | package net.ericaro.surfaceplotter.surface; 29 | 30 | 31 | 32 | 33 | /** 34 | * The model used to display any surface in JSurface 35 | */ 36 | 37 | public interface SurfaceModel 38 | { 39 | 40 | public enum PlotType{ 41 | SURFACE("surfaceType"), 42 | WIREFRAME("wireframeType"), 43 | DENSITY("densityType"), 44 | CONTOUR("contourType"); 45 | 46 | final String att; 47 | PlotType(String att){this.att = att;} 48 | public String getPropertyName() {return att;} 49 | 50 | }; 51 | //TODO replace with enum 52 | //plot type constant 53 | 54 | public enum PlotColor{ 55 | OPAQUE("hiddenMode"), 56 | SPECTRUM("spectrumMode"), 57 | DUALSHADE("dualShadeMode"), 58 | GRAYSCALE("grayScaleMode"), 59 | FOG("fogMode"); 60 | 61 | final String att; 62 | PlotColor(String att){this.att = att;} 63 | public String getPropertyName() {return att;} 64 | 65 | 66 | 67 | }; 68 | //TODO replace with enums 69 | // plot color constant 70 | 71 | //events 72 | public void addPropertyChangeListener(java.beans.PropertyChangeListener listener); 73 | public void addPropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener); 74 | public void removePropertyChangeListener(java.beans.PropertyChangeListener listener); 75 | public void removePropertyChangeListener(String propertyName, java.beans.PropertyChangeListener listener); 76 | public void addChangeListener(javax.swing.event.ChangeListener listener); 77 | public void removeChangeListener(javax.swing.event.ChangeListener listener); 78 | 79 | 80 | 81 | public SurfaceVertex[][] getSurfaceVertex(); //maybe provide a less brutal parameter passing, but 82 | //I have to ber careful, there is performance at stake 83 | 84 | public Projector getProjector(); //project is kind of "point of view" 85 | 86 | 87 | public boolean isAutoScaleZ(); 88 | public PlotType getPlotType(); 89 | public PlotColor getPlotColor(); 90 | public int getCalcDivisions(); 91 | public int getContourLines(); 92 | public int getDispDivisions(); 93 | public float getXMin(); 94 | public float getYMin(); 95 | public float getZMin(); 96 | public float getXMax(); 97 | public float getYMax(); 98 | public float getZMax(); 99 | public SurfaceColor getColorModel(); // not the right place, but JSurface does not work with any colorset, should be removed lately 100 | 101 | /** 102 | * Determines whether the delay regeneration checkbox is checked. 103 | * 104 | * @return true if the checkbox is checked, 105 | * false otherwise 106 | */ 107 | public boolean isExpectDelay(); 108 | 109 | /** 110 | * Determines whether to show bounding box. 111 | * 112 | * @return true if to show bounding box 113 | */ 114 | public boolean isBoxed(); 115 | 116 | /** 117 | * Determines whether to show x-y mesh. 118 | * 119 | * @return true if to show x-y mesh 120 | */ 121 | public boolean isMesh(); 122 | /** 123 | * Determines whether to scale axes and bounding box. 124 | * 125 | * @return true if to scale bounding box 126 | */ 127 | 128 | public boolean isScaleBox(); 129 | 130 | /** 131 | * Determines whether to show x-y ticks. 132 | * 133 | * @return true if to show x-y ticks 134 | */ 135 | public boolean isDisplayXY(); 136 | /** 137 | * Determines whether to show z ticks. 138 | * 139 | * @return true if to show z ticks 140 | */ 141 | public boolean isDisplayZ(); 142 | /** 143 | * Determines whether to show face grids. 144 | * 145 | * @return true if to show face grids 146 | */ 147 | public boolean isDisplayGrids(); 148 | /** 149 | * Determines whether the first function is selected. 150 | * 151 | * @return true if the first function is checked, 152 | * false otherwise 153 | */ 154 | public boolean isPlotFunction1(); 155 | 156 | /** 157 | * Determines whether the first function is selected. 158 | * 159 | * @return true if the first function is checked, 160 | * false otherwise 161 | */ 162 | 163 | public boolean isPlotFunction2(); 164 | 165 | /** 166 | * Sets data availability flag 167 | */ 168 | public boolean isDataAvailable(); 169 | 170 | 171 | } 172 | 173 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/SurfaceUtils.java: -------------------------------------------------------------------------------- 1 | package net.ericaro.surfaceplotter.surface; 2 | 3 | import java.awt.Graphics2D; 4 | import java.io.File; 5 | import java.io.IOException; 6 | 7 | import javax.xml.parsers.ParserConfigurationException; 8 | 9 | public class SurfaceUtils { 10 | 11 | public static void doExportPNG(JSurface surface, File file) throws IOException { 12 | if (file == null) 13 | return; 14 | int h, w; 15 | w = 50; 16 | h = 30; 17 | java.awt.image.BufferedImage bf = new java.awt.image.BufferedImage(surface.getWidth(), surface.getHeight(), java.awt.image.BufferedImage.TYPE_INT_RGB); 18 | Graphics2D g2d = bf.createGraphics(); 19 | 20 | g2d.setColor(java.awt.Color.white); 21 | g2d.fillRect(0,0,surface.getWidth() ,surface.getHeight()); 22 | g2d.setColor(java.awt.Color.black); 23 | surface.export(g2d); 24 | // java.awt.image.BufferedImage bf2=bf.getSubimage(0,0,w,h); 25 | boolean b = javax.imageio.ImageIO.write(bf, "PNG", file); 26 | } 27 | 28 | /** 29 | * needs batik, will reintroduce it later 30 | * @throws ParserConfigurationException 31 | */ 32 | public static void doExportSVG(JSurface surface, File file) throws IOException, ParserConfigurationException{ 33 | if (file == null) 34 | return; 35 | 36 | // Create an instance of org.w3c.dom.Document 37 | org.w3c.dom.Document document = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 38 | 39 | // Create an instance of the SVG Generator 40 | 41 | org.apache.batik.svggen.SVGGraphics2D svgGenerator = new org.apache.batik.svggen.SVGGraphics2D(document); 42 | 43 | // Ask the test to render into the SVG Graphics2D implementation 44 | surface.export(svgGenerator); 45 | 46 | // Finally, stream out SVG to the standard output using UTF-8 // 47 | // character to byte encoding 48 | boolean useCSS = true; // we want to use CSS // style attribute 49 | java.io.Writer out = new java.io.OutputStreamWriter(new java.io.FileOutputStream(file), "UTF-8"); 50 | svgGenerator.stream(out, useCSS); 51 | out.close(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/SurfaceVertex.java: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------------------* 2 | * SurfaceVertex.java * 3 | * * 4 | * Surface Plotter version 1.10 14 Oct 1996 * 5 | * version 1.20 8 Nov 1996 * 6 | * version 1.30b1 17 May 1997 * 7 | * version 1.30b2 18 Oct 2001 * 8 | * * 9 | * Copyright (c) Yanto Suryono * 10 | * * 11 | * This program is free software; you can redistribute it and/or modify it * 12 | * under the terms of the GNU Lesser General Public License as published by the * 13 | * Free Software Foundation; either version 2 of the License, or (at your option) * 14 | * any later version. * 15 | * * 16 | * This program is distributed in the hope that it will be useful, but * 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for * 19 | * more details. * 20 | * * 21 | * You should have received a copy of the GNU Lesser General Public License along * 22 | * with this program; if not, write to the Free Software Foundation, Inc., * 23 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 24 | * * 25 | *----------------------------------------------------------------------------------------*/ 26 | package net.ericaro.surfaceplotter.surface; 27 | 28 | import java.awt.Point; 29 | 30 | /** 31 | * The class SurfaceVertex represents a surfaceVertex in 3D space. 32 | * 33 | * @author Yanto Suryono 34 | */ 35 | 36 | public final class SurfaceVertex { 37 | private Point projection; 38 | private int project_index; 39 | 40 | 41 | private static int master_project_index = 0; // over 4 billion times to reset 42 | 43 | /** 44 | * The x coordinate 45 | */ 46 | public float x; 47 | 48 | /** 49 | * The y coordinate 50 | */ 51 | public float y; 52 | 53 | /** 54 | * The z coordinate 55 | */ 56 | public float z; 57 | 58 | /** 59 | * The constructor of SurfaceVertex. 60 | * The x and y coordinated must be in normalized form, i.e: in the range -10 .. +10. 61 | * 62 | * @param ix the x coordinate 63 | * @param iy the y coordinate 64 | * @param iz the z coordinate 65 | */ 66 | 67 | public SurfaceVertex(float ix, float iy, float iz) 68 | { 69 | x = ix; y = iy; z = iz; 70 | project_index = master_project_index-1; 71 | } 72 | 73 | /** 74 | * Determines whether this surfaceVertex is invalid, i.e has invalid coordinates value. 75 | * 76 | * @return true if this surfaceVertex is invalid 77 | */ 78 | 79 | public final boolean isInvalid() { 80 | return Float.isNaN(z); 81 | } 82 | 83 | /** 84 | * Gets the 2D projection of the surfaceVertex. 85 | * 86 | * @return the 2D projection 87 | */ 88 | 89 | public final Point projection(Projector projector) { 90 | if (project_index != master_project_index) { 91 | projection = projector.project(x,y,(z-projector.zmin)*projector.zfactor-10); 92 | project_index = master_project_index; 93 | } 94 | return projection; 95 | } 96 | 97 | /** 98 | * Transforms coordinate values to fit the scaling factor of the 99 | * projector. This routine is only used for transforming center of projection 100 | * in Surface Plotter. 101 | */ 102 | 103 | public final void transform(Projector projector) { 104 | x = x / projector.getXScaling(); 105 | y = y / projector.getYScaling(); 106 | z = (projector.zmax-projector.zmin)*(z/projector.getZScaling()+10)/20 + projector.zmin; 107 | } 108 | 109 | /** 110 | * Invalidates all vertices. This will force the projector 111 | * to recalculate surfaceVertex projection. 112 | */ 113 | 114 | public static void invalidate() { 115 | master_project_index++; 116 | } 117 | 118 | /** 119 | * Sets the projector to project this surfaceVertex. 120 | * 121 | * @param projector the projector 122 | */ 123 | /* 124 | public void setProjector(Projector projector) { 125 | this.projector = projector; 126 | } 127 | /**/ 128 | /** 129 | * Sets the minimum and maximum value of z range. 130 | * This values is used to compute a factor to normalized 131 | * z values into the range -10 .. +10. 132 | * 133 | * @param zmin the minimum z 134 | * @param zmax the maximum z 135 | */ 136 | 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/main/java/net/ericaro/surfaceplotter/surface/VerticalConfigurationPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Thu Oct 07 17:39:55 CEST 2010 3 | */ 4 | 5 | package net.ericaro.surfaceplotter.surface; 6 | 7 | import java.awt.Color; 8 | import java.awt.Font; 9 | import java.awt.GridBagConstraints; 10 | import java.awt.GridBagLayout; 11 | import java.awt.Insets; 12 | import java.util.ResourceBundle; 13 | import javax.swing.*; 14 | 15 | import javax.swing.ButtonGroup; 16 | import javax.swing.JLabel; 17 | import javax.swing.border.EmptyBorder; 18 | 19 | import net.ericaro.surfaceplotter.DefaultSurfaceModel; 20 | import net.ericaro.surfaceplotter.beans.JBindedCheckBox; 21 | import net.ericaro.surfaceplotter.beans.JBindedRadioButton; 22 | import net.ericaro.surfaceplotter.beans.JScrollablePanel; 23 | import net.ericaro.surfaceplotter.beans.ModelSource; 24 | 25 | 26 | /** A Vertical Configuration panel for the {@link DefaultSurfaceModel}. 27 | * @author eric 28 | */ 29 | public class VerticalConfigurationPanel extends JScrollablePanel { 30 | public VerticalConfigurationPanel() { 31 | initComponents(); 32 | } 33 | 34 | public void setModel(AbstractSurfaceModel model) { 35 | modelSource1.setSurfaceModel(model); 36 | } 37 | 38 | 39 | 40 | private void initComponents() { 41 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 42 | ResourceBundle bundle = ResourceBundle.getBundle("net.ericaro.surfaceplotter.surface.VerticalConfigurationPanel"); 43 | label1 = new JLabel(); 44 | boxed = new JBindedCheckBox(); 45 | scaleBox = new JBindedCheckBox(); 46 | label3 = new JLabel(); 47 | displayXY = new JBindedCheckBox(); 48 | displayZ = new JBindedCheckBox(); 49 | label6 = new JLabel(); 50 | displayGrids = new JBindedCheckBox(); 51 | mesh = new JBindedCheckBox(); 52 | expectDelay = new JBindedCheckBox(); 53 | label4 = new JLabel(); 54 | hiddenMode = new JBindedRadioButton(); 55 | spectrumMode = new JBindedRadioButton(); 56 | grayScaleMode = new JBindedRadioButton(); 57 | dualShadeMode = new JBindedRadioButton(); 58 | fogMode = new JBindedRadioButton(); 59 | label5 = new JLabel(); 60 | wireframeType = new JBindedRadioButton(); 61 | surfaceType = new JBindedRadioButton(); 62 | contourType = new JBindedRadioButton(); 63 | densityType = new JBindedRadioButton(); 64 | label2 = new JLabel(); 65 | firstFunctionOnly = new JBindedRadioButton(); 66 | secondFunctionOnly = new JBindedRadioButton(); 67 | bothFunction = new JBindedRadioButton(); 68 | modelSource1 = new ModelSource(); 69 | abstractSurfaceModel1 = new DefaultSurfaceModel(); 70 | 71 | //======== this ======== 72 | setBorder(new EmptyBorder(6, 6, 6, 6)); 73 | setBackground(Color.white); 74 | setAlignmentY(0.0F); 75 | setLayout(new GridBagLayout()); 76 | ((GridBagLayout)getLayout()).columnWidths = new int[] {6, 0, 0}; 77 | ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 78 | ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 1.0, 1.0E-4}; 79 | ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0E-4}; 80 | 81 | //---- label1 ---- 82 | label1.setText(bundle.getString("label1.text")); 83 | label1.setFont(label1.getFont().deriveFont(label1.getFont().getStyle() | Font.BOLD)); 84 | label1.setBackground(Color.white); 85 | add(label1, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, 86 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 87 | new Insets(6, 0, 0, 0), 0, 0)); 88 | 89 | //---- boxed ---- 90 | boxed.setText(bundle.getString("boxed.text")); 91 | boxed.setBackground(Color.white); 92 | boxed.setSourceBean(modelSource1); 93 | boxed.setPropertyName("boxed"); 94 | boxed.setMargin(new Insets(0, 0, 0, 0)); 95 | add(boxed, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, 96 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 97 | new Insets(0, 0, 0, 0), 0, 0)); 98 | 99 | //---- scaleBox ---- 100 | scaleBox.setText(bundle.getString("scaleBox.text")); 101 | scaleBox.setBackground(Color.white); 102 | scaleBox.setSourceBean(modelSource1); 103 | scaleBox.setPropertyName("scaleBox"); 104 | scaleBox.setMargin(new Insets(0, 0, 0, 0)); 105 | add(scaleBox, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, 106 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 107 | new Insets(0, 0, 0, 0), 0, 0)); 108 | 109 | //---- label3 ---- 110 | label3.setText(bundle.getString("label3.text")); 111 | label3.setFont(label3.getFont().deriveFont(label3.getFont().getStyle() | Font.BOLD)); 112 | label3.setBackground(Color.white); 113 | add(label3, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, 114 | GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 115 | new Insets(6, 0, 0, 0), 0, 0)); 116 | 117 | //---- displayXY ---- 118 | displayXY.setText(bundle.getString("displayXY.text")); 119 | displayXY.setBackground(Color.white); 120 | displayXY.setSourceBean(modelSource1); 121 | displayXY.setPropertyName("displayXY"); 122 | displayXY.setMargin(new Insets(0, 0, 0, 0)); 123 | add(displayXY, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, 124 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 125 | new Insets(0, 0, 0, 0), 0, 0)); 126 | 127 | //---- displayZ ---- 128 | displayZ.setText(bundle.getString("displayZ.text")); 129 | displayZ.setBackground(Color.white); 130 | displayZ.setSourceBean(modelSource1); 131 | displayZ.setPropertyName("displayZ"); 132 | displayZ.setMargin(new Insets(0, 0, 0, 0)); 133 | add(displayZ, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, 134 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 135 | new Insets(0, 0, 0, 0), 0, 0)); 136 | 137 | //---- label6 ---- 138 | label6.setText(bundle.getString("label6.text")); 139 | label6.setFont(label6.getFont().deriveFont(label6.getFont().getStyle() | Font.BOLD)); 140 | label6.setBackground(Color.white); 141 | add(label6, new GridBagConstraints(0, 6, 2, 1, 0.0, 0.0, 142 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 143 | new Insets(6, 0, 0, 0), 0, 0)); 144 | 145 | //---- displayGrids ---- 146 | displayGrids.setText(bundle.getString("displayGrids.text")); 147 | displayGrids.setBackground(Color.white); 148 | displayGrids.setSourceBean(modelSource1); 149 | displayGrids.setPropertyName("displayGrids"); 150 | displayGrids.setMargin(new Insets(0, 0, 0, 0)); 151 | add(displayGrids, new GridBagConstraints(1, 7, 1, 1, 0.0, 0.0, 152 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 153 | new Insets(0, 0, 0, 0), 0, 0)); 154 | 155 | //---- mesh ---- 156 | mesh.setText(bundle.getString("mesh.text")); 157 | mesh.setBackground(Color.white); 158 | mesh.setSourceBean(modelSource1); 159 | mesh.setPropertyName("mesh"); 160 | mesh.setMargin(new Insets(0, 0, 0, 0)); 161 | add(mesh, new GridBagConstraints(1, 8, 1, 1, 0.0, 0.0, 162 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 163 | new Insets(0, 0, 0, 0), 0, 0)); 164 | 165 | //---- expectDelay ---- 166 | expectDelay.setText(bundle.getString("expectDelay.text")); 167 | expectDelay.setBackground(Color.white); 168 | expectDelay.setSourceBean(modelSource1); 169 | expectDelay.setPropertyName("expectDelay"); 170 | expectDelay.setMargin(new Insets(0, 0, 0, 0)); 171 | add(expectDelay, new GridBagConstraints(1, 9, 1, 1, 0.0, 0.0, 172 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 173 | new Insets(0, 0, 0, 0), 0, 0)); 174 | 175 | //---- label4 ---- 176 | label4.setText(bundle.getString("label4.text")); 177 | label4.setFont(label4.getFont().deriveFont(label4.getFont().getStyle() | Font.BOLD)); 178 | label4.setBackground(Color.white); 179 | add(label4, new GridBagConstraints(0, 10, 2, 1, 0.0, 0.0, 180 | GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 181 | new Insets(6, 0, 0, 0), 0, 0)); 182 | 183 | //---- hiddenMode ---- 184 | hiddenMode.setText(bundle.getString("hiddenMode.text")); 185 | hiddenMode.setBackground(Color.white); 186 | hiddenMode.setSourceBean(modelSource1); 187 | hiddenMode.setPropertyName("hiddenMode"); 188 | hiddenMode.setMargin(new Insets(0, 0, 0, 0)); 189 | add(hiddenMode, new GridBagConstraints(1, 11, 1, 1, 0.0, 0.0, 190 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 191 | new Insets(0, 0, 0, 0), 0, 0)); 192 | 193 | //---- spectrumMode ---- 194 | spectrumMode.setText(bundle.getString("spectrumMode.text")); 195 | spectrumMode.setBackground(Color.white); 196 | spectrumMode.setSourceBean(modelSource1); 197 | spectrumMode.setPropertyName("spectrumMode"); 198 | spectrumMode.setMargin(new Insets(0, 0, 0, 0)); 199 | add(spectrumMode, new GridBagConstraints(1, 12, 1, 1, 0.0, 0.0, 200 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 201 | new Insets(0, 0, 0, 0), 0, 0)); 202 | 203 | //---- grayScaleMode ---- 204 | grayScaleMode.setText(bundle.getString("grayScaleMode.text")); 205 | grayScaleMode.setBackground(Color.white); 206 | grayScaleMode.setSourceBean(modelSource1); 207 | grayScaleMode.setPropertyName("grayScaleMode"); 208 | grayScaleMode.setMargin(new Insets(0, 0, 0, 0)); 209 | add(grayScaleMode, new GridBagConstraints(1, 13, 1, 1, 0.0, 0.0, 210 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 211 | new Insets(0, 0, 0, 0), 0, 0)); 212 | 213 | //---- dualShadeMode ---- 214 | dualShadeMode.setText(bundle.getString("dualShadeMode.text")); 215 | dualShadeMode.setBackground(Color.white); 216 | dualShadeMode.setSourceBean(modelSource1); 217 | dualShadeMode.setPropertyName("dualShadeMode"); 218 | dualShadeMode.setMargin(new Insets(0, 0, 0, 0)); 219 | add(dualShadeMode, new GridBagConstraints(1, 14, 1, 1, 0.0, 0.0, 220 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 221 | new Insets(0, 0, 0, 0), 0, 0)); 222 | 223 | //---- fogMode ---- 224 | fogMode.setText(bundle.getString("fogMode.text")); 225 | fogMode.setBackground(Color.white); 226 | fogMode.setSourceBean(modelSource1); 227 | fogMode.setPropertyName("fogMode"); 228 | fogMode.setMargin(new Insets(0, 0, 0, 0)); 229 | add(fogMode, new GridBagConstraints(1, 15, 1, 1, 0.0, 0.0, 230 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 231 | new Insets(0, 0, 0, 0), 0, 0)); 232 | 233 | //---- label5 ---- 234 | label5.setText(bundle.getString("label5.text")); 235 | label5.setFont(label5.getFont().deriveFont(label5.getFont().getStyle() | Font.BOLD)); 236 | label5.setBackground(Color.white); 237 | add(label5, new GridBagConstraints(0, 16, 2, 1, 0.0, 0.0, 238 | GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 239 | new Insets(6, 0, 0, 0), 0, 0)); 240 | 241 | //---- wireframeType ---- 242 | wireframeType.setText(bundle.getString("wireframeType.text")); 243 | wireframeType.setBackground(Color.white); 244 | wireframeType.setSourceBean(modelSource1); 245 | wireframeType.setPropertyName("wireframeType"); 246 | wireframeType.setMargin(new Insets(0, 0, 0, 0)); 247 | add(wireframeType, new GridBagConstraints(1, 17, 1, 1, 0.0, 0.0, 248 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 249 | new Insets(0, 0, 0, 0), 0, 0)); 250 | 251 | //---- surfaceType ---- 252 | surfaceType.setText(bundle.getString("surfaceType.text")); 253 | surfaceType.setBackground(Color.white); 254 | surfaceType.setSourceBean(modelSource1); 255 | surfaceType.setPropertyName("surfaceType"); 256 | surfaceType.setMargin(new Insets(0, 0, 0, 0)); 257 | add(surfaceType, new GridBagConstraints(1, 18, 1, 1, 0.0, 0.0, 258 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 259 | new Insets(0, 0, 0, 0), 0, 0)); 260 | 261 | //---- contourType ---- 262 | contourType.setText(bundle.getString("contourType.text")); 263 | contourType.setBackground(Color.white); 264 | contourType.setSourceBean(modelSource1); 265 | contourType.setPropertyName("contourType"); 266 | contourType.setMargin(new Insets(0, 0, 0, 0)); 267 | add(contourType, new GridBagConstraints(1, 19, 1, 1, 0.0, 0.0, 268 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 269 | new Insets(0, 0, 0, 0), 0, 0)); 270 | 271 | //---- densityType ---- 272 | densityType.setText(bundle.getString("densityType.text")); 273 | densityType.setBackground(Color.white); 274 | densityType.setSourceBean(modelSource1); 275 | densityType.setPropertyName("densityType"); 276 | densityType.setMargin(new Insets(0, 0, 0, 0)); 277 | add(densityType, new GridBagConstraints(1, 20, 1, 1, 0.0, 0.0, 278 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 279 | new Insets(0, 0, 0, 0), 0, 0)); 280 | 281 | //---- label2 ---- 282 | label2.setText(bundle.getString("label2.text")); 283 | label2.setFont(label2.getFont().deriveFont(label2.getFont().getStyle() | Font.BOLD)); 284 | label2.setBackground(Color.white); 285 | add(label2, new GridBagConstraints(0, 21, 2, 1, 0.0, 0.0, 286 | GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, 287 | new Insets(6, 0, 0, 0), 0, 0)); 288 | 289 | //---- firstFunctionOnly ---- 290 | firstFunctionOnly.setText(bundle.getString("firstFunctionOnly.text")); 291 | firstFunctionOnly.setBackground(Color.white); 292 | firstFunctionOnly.setSourceBean(modelSource1); 293 | firstFunctionOnly.setPropertyName("firstFunctionOnly"); 294 | firstFunctionOnly.setProperty(true); 295 | firstFunctionOnly.setMargin(new Insets(0, 0, 0, 0)); 296 | add(firstFunctionOnly, new GridBagConstraints(1, 22, 1, 1, 0.0, 0.0, 297 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 298 | new Insets(0, 0, 0, 0), 0, 0)); 299 | 300 | //---- secondFunctionOnly ---- 301 | secondFunctionOnly.setText(bundle.getString("secondFunctionOnly.text")); 302 | secondFunctionOnly.setBackground(Color.white); 303 | secondFunctionOnly.setSourceBean(modelSource1); 304 | secondFunctionOnly.setPropertyName("secondFunctionOnly"); 305 | secondFunctionOnly.setProperty(true); 306 | secondFunctionOnly.setMargin(new Insets(0, 0, 0, 0)); 307 | add(secondFunctionOnly, new GridBagConstraints(1, 23, 1, 1, 0.0, 0.0, 308 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 309 | new Insets(0, 0, 0, 0), 0, 0)); 310 | 311 | //---- bothFunction ---- 312 | bothFunction.setText(bundle.getString("bothFunction.text")); 313 | bothFunction.setBackground(Color.white); 314 | bothFunction.setSourceBean(modelSource1); 315 | bothFunction.setPropertyName("bothFunction"); 316 | bothFunction.setMargin(new Insets(0, 0, 0, 0)); 317 | add(bothFunction, new GridBagConstraints(1, 24, 1, 1, 0.0, 0.0, 318 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 319 | new Insets(0, 0, 0, 0), 0, 0)); 320 | 321 | //---- modelSource1 ---- 322 | modelSource1.setSurfaceModel(abstractSurfaceModel1); 323 | 324 | //---- abstractSurfaceModel1 ---- 325 | abstractSurfaceModel1.setSecondFunctionOnly(true); 326 | 327 | //---- buttonGroup1 ---- 328 | ButtonGroup buttonGroup1 = new ButtonGroup(); 329 | buttonGroup1.add(hiddenMode); 330 | buttonGroup1.add(spectrumMode); 331 | buttonGroup1.add(grayScaleMode); 332 | buttonGroup1.add(dualShadeMode); 333 | buttonGroup1.add(fogMode); 334 | 335 | //---- buttonGroup2 ---- 336 | ButtonGroup buttonGroup2 = new ButtonGroup(); 337 | buttonGroup2.add(wireframeType); 338 | buttonGroup2.add(surfaceType); 339 | buttonGroup2.add(contourType); 340 | buttonGroup2.add(densityType); 341 | 342 | //---- buttonGroup3 ---- 343 | ButtonGroup buttonGroup3 = new ButtonGroup(); 344 | buttonGroup3.add(firstFunctionOnly); 345 | buttonGroup3.add(secondFunctionOnly); 346 | buttonGroup3.add(bothFunction); 347 | // JFormDesigner - End of component initialization //GEN-END:initComponents 348 | } 349 | 350 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 351 | private JLabel label1; 352 | private JBindedCheckBox boxed; 353 | private JBindedCheckBox scaleBox; 354 | private JLabel label3; 355 | private JBindedCheckBox displayXY; 356 | private JBindedCheckBox displayZ; 357 | private JLabel label6; 358 | private JBindedCheckBox displayGrids; 359 | private JBindedCheckBox mesh; 360 | private JBindedCheckBox expectDelay; 361 | private JLabel label4; 362 | private JBindedRadioButton hiddenMode; 363 | private JBindedRadioButton spectrumMode; 364 | private JBindedRadioButton grayScaleMode; 365 | private JBindedRadioButton dualShadeMode; 366 | private JBindedRadioButton fogMode; 367 | private JLabel label5; 368 | private JBindedRadioButton wireframeType; 369 | private JBindedRadioButton surfaceType; 370 | private JBindedRadioButton contourType; 371 | private JBindedRadioButton densityType; 372 | private JLabel label2; 373 | private JBindedRadioButton firstFunctionOnly; 374 | private JBindedRadioButton secondFunctionOnly; 375 | private JBindedRadioButton bothFunction; 376 | private ModelSource modelSource1; 377 | private DefaultSurfaceModel abstractSurfaceModel1; 378 | // JFormDesigner - End of variables declaration //GEN-END:variables 379 | } 380 | -------------------------------------------------------------------------------- /src/main/resources/net/ericaro/surfaceplotter/JSurfacePanel.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Created by JFormDesigner on Tue May 17 09:54:02 CEST 2011 3 | # 4 | 5 | configurationToggler.Name=configurationToggler 6 | surface.toolTipText=\nShift + Mouse drag\: Pan the curve(s)
\nCtrl   + Mouse drag\: Zoom the curve(s)
\nMouse Wheel\: Zoom the curve(s)
\nF2\: Toggle configuration panel
\n 7 | title.text=title 8 | -------------------------------------------------------------------------------- /src/main/resources/net/ericaro/surfaceplotter/surface/VerticalConfigurationPanel.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Created by JFormDesigner on Thu Oct 07 16:35:01 CEST 2010 3 | # 4 | 5 | secondFunctionOnly.text=Second 6 | firstFunctionOnly.text=First 7 | contourType.text=2D Contour 8 | surfaceType.text=3D Surface 9 | fogMode.text=Fog 10 | dualShadeMode.text=Dual Shade 11 | grayScaleMode.text=Gray Scale 12 | spectrumMode.text=Color Spectrum 13 | hiddenMode.text=Hidden Surface 14 | densityType.text=2D Density 15 | wireframeType.text=3D Wireframe 16 | displayXY.text=Show X-Y Ticks 17 | expectDelay.text=Hide on Drag 18 | scaleBox.text=Scale Box 19 | displayGrids.text=Show Face Grid 20 | mesh.text=Show X-Y Mesh 21 | boxed.text=Draw Box 22 | displayZ.text=Show Z Ticks 23 | label1.text=Bounding Box 24 | label2.text=Curves Selection 25 | label3.text=Ticks 26 | label4.text=Painting Mode 27 | label5.text=Plot Mode 28 | label6.text=Lines 29 | bothFunction.text=Both 30 | -------------------------------------------------------------------------------- /src/test/java/Sample.java: -------------------------------------------------------------------------------- 1 | import java.awt.BorderLayout; 2 | import java.awt.Color; 3 | import java.awt.Font; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import javax.swing.*; 7 | 8 | import javax.swing.JButton; 9 | import javax.swing.JFileChooser; 10 | import javax.swing.JFrame; 11 | import javax.swing.JPanel; 12 | import javax.swing.JToolBar; 13 | import javax.swing.event.*; 14 | 15 | import net.ericaro.surfaceplotter.DefaultSurfaceModel; 16 | import net.ericaro.surfaceplotter.JSurfacePanel; 17 | import net.ericaro.surfaceplotter.Mapper; 18 | import net.ericaro.surfaceplotter.ProgressiveSurfaceModel; 19 | import net.ericaro.surfaceplotter.surface.SurfaceUtils; 20 | 21 | 22 | 23 | 24 | /** 25 | * @author User #1 26 | */ 27 | public class Sample extends JPanel { 28 | private ProgressiveSurfaceModel model; 29 | public Sample() { 30 | initComponents(); 31 | 32 | //DefaultSurfaceModel model = new DefaultSurfaceModel(); 33 | model = new ProgressiveSurfaceModel() ; 34 | surfacePanel1.setModel(model); 35 | 36 | model.setMapper(new Mapper() { 37 | public float f1( float x, float y) 38 | { 39 | float r = x*x+y*y; 40 | 41 | if (r == 0 ) return 1f; 42 | return (float)( Math.sin(r)/(r)); 43 | } 44 | 45 | public float f2( float x, float y) 46 | { 47 | return (float)(Math.sin(x*y)); 48 | } 49 | }); 50 | model.plot().execute(); 51 | } 52 | 53 | private void button1ActionPerformed() { 54 | JFileChooser jfc = new JFileChooser(); 55 | try { 56 | if (jfc.showSaveDialog(surfacePanel1) == JFileChooser.APPROVE_OPTION ) 57 | SurfaceUtils.doExportSVG(surfacePanel1.getSurface(), jfc.getSelectedFile()); 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | public static void main(String[] args) { 64 | Sample sample = new Sample(); 65 | JFrame jf = new JFrame("sample"); 66 | jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 67 | jf.getContentPane().add(sample); 68 | jf.pack(); 69 | jf.setVisible(true); 70 | } 71 | 72 | private void slider1StateChanged(ChangeEvent e) { 73 | if (!slider1.getValueIsAdjusting()) 74 | model.setCurrentDefinition(slider1.getValue()); 75 | } 76 | 77 | private void initComponents() { 78 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 79 | surfacePanel1 = new JSurfacePanel(); 80 | toolBar1 = new JToolBar(); 81 | button1 = new JButton(); 82 | slider1 = new JSlider(); 83 | 84 | //======== this ======== 85 | setLayout(new BorderLayout()); 86 | 87 | //---- surfacePanel1 ---- 88 | surfacePanel1.setTitleText("title"); 89 | surfacePanel1.setBackground(Color.white); 90 | surfacePanel1.setTitleFont(surfacePanel1.getTitleFont().deriveFont(surfacePanel1.getTitleFont().getStyle() | Font.BOLD, surfacePanel1.getTitleFont().getSize() + 6f)); 91 | surfacePanel1.setConfigurationVisible(false); 92 | add(surfacePanel1, BorderLayout.CENTER); 93 | 94 | //======== toolBar1 ======== 95 | { 96 | 97 | //---- button1 ---- 98 | button1.setText("export SVG"); 99 | button1.addActionListener(new ActionListener() { 100 | public void actionPerformed(ActionEvent e) { 101 | button1ActionPerformed(); 102 | } 103 | }); 104 | toolBar1.add(button1); 105 | 106 | //---- slider1 ---- 107 | slider1.setMaximum(6); 108 | slider1.setValue(0); 109 | slider1.setPaintTicks(true); 110 | slider1.setSnapToTicks(true); 111 | slider1.setMinorTickSpacing(1); 112 | slider1.setMajorTickSpacing(1); 113 | slider1.setPaintLabels(true); 114 | slider1.addChangeListener(new ChangeListener() { 115 | public void stateChanged(ChangeEvent e) { 116 | slider1StateChanged(e); 117 | } 118 | }); 119 | toolBar1.add(slider1); 120 | } 121 | add(toolBar1, BorderLayout.NORTH); 122 | // JFormDesigner - End of component initialization //GEN-END:initComponents 123 | } 124 | 125 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 126 | private JSurfacePanel surfacePanel1; 127 | private JToolBar toolBar1; 128 | private JButton button1; 129 | private JSlider slider1; 130 | // JFormDesigner - End of variables declaration //GEN-END:variables 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/Sample.jfd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | form/swing 6 | 7 | 8 | 9 | 10 | 11 | javax.swing.JPanel 12 | 13 | java.awt.BorderLayout 14 | 15 | 16 | this 17 | 18 | 19 | 20 | net.ericaro.surfaceplotter.JSurfacePanel 21 | 22 | titleText 23 | title 24 | 25 | 26 | background 27 | 28 | 255 29 | 255 30 | 255 31 | 255 32 | 33 | 34 | 35 | titleFont 36 | 37 | 38 | 1 39 | 6 40 | false 41 | 42 | 43 | 44 | configurationVisible 45 | false 46 | 47 | 48 | surfacePanel1 49 | 50 | 51 | 52 | java.lang.String 53 | 54 | value 55 | Center 56 | 57 | 58 | 59 | 60 | 61 | javax.swing.JToolBar 62 | 63 | javax.swing.JToolBar 64 | 65 | 66 | toolBar1 67 | 68 | 69 | 70 | javax.swing.JButton 71 | 72 | text 73 | export SVG 74 | 75 | 76 | button1 77 | 78 | 79 | 80 | java.awt.event.ActionListener 81 | actionPerformed 82 | button1ActionPerformed 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | javax.swing.JSlider 91 | 92 | maximum 93 | 6 94 | 95 | 96 | value 97 | 0 98 | 99 | 100 | paintTicks 101 | true 102 | 103 | 104 | snapToTicks 105 | true 106 | 107 | 108 | minorTickSpacing 109 | 1 110 | 111 | 112 | majorTickSpacing 113 | 1 114 | 115 | 116 | paintLabels 117 | true 118 | 119 | 120 | slider1 121 | 122 | 123 | 124 | javax.swing.event.ChangeListener 125 | stateChanged 126 | slider1StateChanged 127 | true 128 | 129 | 130 | 131 | 132 | 133 | 134 | java.lang.String 135 | 136 | value 137 | North 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | location 146 | 147 | 0 148 | 0 149 | 150 | 151 | 152 | size 153 | 154 | 650 155 | 635 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/test/java/SimpleRun.java: -------------------------------------------------------------------------------- 1 | import java.awt.BorderLayout; 2 | import java.util.Random; 3 | 4 | import javax.swing.JFrame; 5 | import javax.swing.SwingConstants; 6 | import javax.swing.SwingUtilities; 7 | import javax.swing.plaf.basic.BasicArrowButton; 8 | 9 | import net.ericaro.surfaceplotter.JSurfacePanel; 10 | import net.ericaro.surfaceplotter.Mapper; 11 | import net.ericaro.surfaceplotter.surface.AbstractSurfaceModel; 12 | import net.ericaro.surfaceplotter.surface.ArraySurfaceModel; 13 | import net.ericaro.surfaceplotter.surface.SurfaceVertex; 14 | 15 | public class SimpleRun { 16 | 17 | public void testSomething() { 18 | JSurfacePanel jsp = new JSurfacePanel(); 19 | jsp.setTitleText("Hello"); 20 | 21 | JFrame jf = new JFrame("test"); 22 | jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 23 | jf.getContentPane().add(jsp, BorderLayout.CENTER); 24 | jf.pack(); 25 | jf.setVisible(true); 26 | 27 | Random rand = new Random(); 28 | int max = 10; 29 | float[][] z1 = new float[max][max]; 30 | float[][] z2 = new float[max][max]; 31 | for (int i = 0; i < max; i++) { 32 | for (int j = 0; j < max; j++) { 33 | z1[i][j] = rand.nextFloat() * 20 - 10f; 34 | z2[i][j] = rand.nextFloat() * 20 - 10f; 35 | } 36 | } 37 | ArraySurfaceModel sm = new ArraySurfaceModel(); 38 | sm.setValues(0f,10f,0f,10f,max, z1, null); 39 | jsp.setModel(sm); 40 | // sm.doRotate(); 41 | 42 | // canvas.doPrint(); 43 | // sm.doCompute(); 44 | } 45 | 46 | public static float f1(float x, float y) { 47 | // System.out.print('.'); 48 | return (float) (Math.sin(x * x + y * y) / (x * x + y * y)); 49 | // return (float)(10*x*x+5*y*y+8*x*y -5*x+3*y); 50 | } 51 | 52 | public static float f2(float x, float y) { 53 | return (float) (Math.sin(x * x - y * y) / (x * x + y * y)); 54 | // return (float)(10*x*x+5*y*y+15*x*y-2*x-y); 55 | } 56 | 57 | public static void main(String[] args) { 58 | SwingUtilities.invokeLater(new Runnable() { 59 | 60 | public void run() { 61 | new SimpleRun().testSomething(); 62 | } 63 | }); 64 | 65 | } 66 | 67 | } 68 | --------------------------------------------------------------------------------