1 | /*
|
---|
2 | * Class Plot
|
---|
3 | *
|
---|
4 | * Superclass for the plotting subclasses:
|
---|
5 | * PlotGraph and PlotPoleZero
|
---|
6 | *
|
---|
7 | * WRITTEN BY: Dr Michael Thomas Flanagan
|
---|
8 | *
|
---|
9 | * DATE: February 2002
|
---|
10 | * REVISED: 20 July 2005, 7 July 2008, 27 July 2008, 11 August 2008
|
---|
11 | *
|
---|
12 | * Copyright (c) 2002 - 2008
|
---|
13 | *
|
---|
14 | * DOCUMENTATION
|
---|
15 | * http://www.ee.ucl.ac.uk/~mflanaga/java/PlotGraph.html
|
---|
16 | * http://www.ee.ucl.ac.uk/~mflanaga/java/
|
---|
17 | *
|
---|
18 | * PERMISSION TO COPY:
|
---|
19 | * Permission to use, copy and modify this software and its documentation for
|
---|
20 | * NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement
|
---|
21 | * to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies.
|
---|
22 | *
|
---|
23 | * Dr Michael Thomas Flanagan makes no representations about the suitability
|
---|
24 | * or fitness of the software for any or for a particular purpose.
|
---|
25 | * Michael Thomas Flanagan shall not be liable for any damages suffered
|
---|
26 | * as a result of using, modifying or distributing this software or its derivatives.
|
---|
27 | *
|
---|
28 | ***************************************************************************************/
|
---|
29 |
|
---|
30 |
|
---|
31 | package agents.anac.y2015.agentBuyogV2.flanagan.plot;
|
---|
32 |
|
---|
33 | import java.awt.*;
|
---|
34 | import java.io.Serializable;
|
---|
35 |
|
---|
36 | import agents.anac.y2015.agentBuyogV2.flanagan.interpolation.CubicSpline;
|
---|
37 | import agents.anac.y2015.agentBuyogV2.flanagan.math.ArrayMaths;
|
---|
38 | import agents.anac.y2015.agentBuyogV2.flanagan.math.Fmath;
|
---|
39 |
|
---|
40 | public class Plot extends Canvas implements Serializable{
|
---|
41 |
|
---|
42 | protected static final long serialVersionUID = 1L; // serial version unique identifier
|
---|
43 |
|
---|
44 | protected double[][] data = null; // data to be plotted
|
---|
45 | // data[i][] i = 0, 2, 4 . . . x values
|
---|
46 | // data[i][] i = 1, 3, 5 . . . y values for x[i-1][]
|
---|
47 | protected double[][] copy = null; // copy of original data to be plotted
|
---|
48 | protected int nCurves = 0; // number of curves
|
---|
49 | protected int[] nPoints = null; // number of points points on curve each curve
|
---|
50 | protected int nmPoints = 0; // number of points points on curve with most points
|
---|
51 | protected int niPoints = 200; // number of cubic spline interpolation points
|
---|
52 | protected int[] pointOpt = null; // point plotting option for each curve
|
---|
53 | // pointOpt = 0: no points plotted
|
---|
54 | // pointOpt = i where i = 1,2,3,4,5,6,7,8: points plotted
|
---|
55 | // default options
|
---|
56 | // curve 1 - open circles
|
---|
57 | // curve 2 - open squares
|
---|
58 | // curve 3 - open diamonds
|
---|
59 | // curve 4 - filled circles
|
---|
60 | // curve 5 - filled squares
|
---|
61 | // curve 6 - filled diamonds
|
---|
62 | // curve 7 - x crosses
|
---|
63 | // curve 8 - + crosses
|
---|
64 | // further curves - above sequence repeated
|
---|
65 | protected int[] pointSize = null; // point size in pixels for each curve
|
---|
66 | protected int npTypes = 8; // number of point types
|
---|
67 | protected boolean[] errorBar = null; // true - error bar plotted, flase no error bar plotted - default = false
|
---|
68 | protected double[][] errors = null; // error bar values - should be an estimate of the sd of the variable
|
---|
69 | protected double[][] errorsCopy = null; // copy of error bar values
|
---|
70 | protected int[] lineOpt = null; // line drawing option for each curve
|
---|
71 | // lineOpt = 0: no line plotted
|
---|
72 | // lineOpt = 1: cubic spline interpolation line plotted as a continuous line
|
---|
73 | // lineOpt = 2: cubic spline interpolation line plotted as a dashed line
|
---|
74 | // lineOpt = 3: line plotted by joining points
|
---|
75 | // lineOpt = 4: dashed line plotted by joining points
|
---|
76 | // default - lineOpt = 1
|
---|
77 | protected int[] dashLength = null; // dash length in lineOpt = 2
|
---|
78 | protected boolean[] minMaxOpt = null;// true - curve included in maximum and minimum axes value calculation
|
---|
79 | protected boolean[] trimOpt = null; // true - curve trimmed to fit axes rectangle
|
---|
80 |
|
---|
81 | protected int fontSize = 14; // text font size
|
---|
82 | protected int xLen = 625; // length of the x axis in pixels
|
---|
83 | protected int yLen = 375; // length of the y axis in pixels
|
---|
84 | protected int xBot = 100; // x coordinate of the bottom of the x axis in pixels
|
---|
85 | protected int xTop = xBot+xLen; // x coordinate of the top of the x axis in pixels
|
---|
86 | protected int yTop = 110; // y coordinate of the top of the y axis in pixels
|
---|
87 | protected int yBot = yTop+yLen; // y coordinate of the bottom of the y axis in pixels
|
---|
88 |
|
---|
89 | protected double xLow = 0; // scaled lower limit data value of the x axis
|
---|
90 | protected double xHigh = 0; // scaled upper limit data value of the x axis
|
---|
91 | protected double yLow = 0; // scaled lower limit data value of the y axis
|
---|
92 | protected double yHigh = 0; // scaled upper limit data value of the y axis
|
---|
93 | protected int xFac = 0; // decadic exponent of x axis scaling factor
|
---|
94 | protected int yFac = 0; // decadic exponent of y axis scaling factor
|
---|
95 | protected int xTicks = 0; // number of x axis ticks
|
---|
96 | protected int yTicks = 0; // number of y axis ticks
|
---|
97 |
|
---|
98 | protected double xMin = 0.0D; // minimum x data value
|
---|
99 | protected double xMax = 0.0D; // maximum x data value
|
---|
100 | protected double yMin = 0.0D; // minimum y data value
|
---|
101 | protected double yMax = 0.0D; // maximum y data value
|
---|
102 |
|
---|
103 | protected double xOffset = 0.0D; // xaxis data value offset
|
---|
104 | protected double yOffset = 0.0D; // y axis data value offset
|
---|
105 | protected boolean noXoffset = false; // no x axis offset allowed if true
|
---|
106 | protected boolean noYoffset = false; // no y axis offset allowed if true
|
---|
107 | protected double xLowFac = 0.75D; // x axis data setting low factor
|
---|
108 | protected double yLowFac = 0.75D; // y axis data setting low factor
|
---|
109 |
|
---|
110 | protected String graphTitle = " "; // graph title
|
---|
111 | protected String graphTitle2 = " "; // graph title (secondline)
|
---|
112 | protected String xAxisLegend = " "; // x axis legend title
|
---|
113 | protected String xAxisUnits = " "; // x axis unit name, e.g. V, ohm
|
---|
114 | protected String yAxisLegend = " "; // y axis legend title
|
---|
115 | protected String yAxisUnits = " "; // x axis unit name
|
---|
116 |
|
---|
117 | protected boolean xZero = false; // if true - a (x=0) zero line is required
|
---|
118 | protected boolean yZero = false; // if true - a (y=0) zero line required
|
---|
119 | protected boolean noXunits = true; // if true - no x axis units
|
---|
120 | protected boolean noYunits = true; // if true - no y axis units
|
---|
121 |
|
---|
122 | protected double[] xAxisNo = new double[50]; // x axis legend numbers as double
|
---|
123 | protected double[] yAxisNo = new double[50]; // y axis legend numbers as double
|
---|
124 | protected String[] xAxisChar = new String[50]; // x axis legend numbers as char
|
---|
125 | protected String[] yAxisChar = new String[50]; // y axis legend numbers as char
|
---|
126 | protected int[] axisTicks = new int[50]; // no of ticks for scaled lengths
|
---|
127 |
|
---|
128 | protected static double dataFill = 3.0e200; // value used to initialise data array by Plot.data()
|
---|
129 |
|
---|
130 |
|
---|
131 | // Constructor
|
---|
132 | //One 2-dimensional data arrays
|
---|
133 | public Plot(double[][] data){
|
---|
134 | this.initialise(data);
|
---|
135 | }
|
---|
136 |
|
---|
137 | // Constructor
|
---|
138 | //Two 1-dimensional data arrays
|
---|
139 | public Plot(double[] xdata, double[] ydata){
|
---|
140 | int xl = xdata.length;
|
---|
141 | int yl = ydata.length;
|
---|
142 | if(xl!=yl)throw new IllegalArgumentException("x-data length is not equal to the y-data length");
|
---|
143 | double[][] data = new double[2][xl];
|
---|
144 | for(int i=0; i<xl; i++){
|
---|
145 | data[0][i] = xdata[i];
|
---|
146 | data[1][i] = ydata[i];
|
---|
147 | }
|
---|
148 | this.initialise(data);
|
---|
149 | }
|
---|
150 |
|
---|
151 | // Initialisation
|
---|
152 | private void initialise(double[][] cdata){
|
---|
153 |
|
---|
154 | // Calculate number of curves
|
---|
155 | this.nCurves = cdata.length/2;
|
---|
156 |
|
---|
157 | // Initialize 1D class arrays
|
---|
158 | this.nPoints = new int[nCurves];
|
---|
159 | this.lineOpt = new int[nCurves];
|
---|
160 | this.dashLength = new int[nCurves];
|
---|
161 | this.trimOpt = new boolean[nCurves];
|
---|
162 | this.minMaxOpt = new boolean[nCurves];
|
---|
163 | this.pointOpt = new int[nCurves];
|
---|
164 | this.pointSize = new int[nCurves];
|
---|
165 | this.errorBar = new boolean[nCurves];
|
---|
166 |
|
---|
167 | // Calculate maximum number of points on a single curve
|
---|
168 | this.nmPoints = 0;
|
---|
169 | int ll = 0;
|
---|
170 | for(int i=0; i<2*nCurves; i++){
|
---|
171 | if((ll=cdata[i].length)>nmPoints)nmPoints=ll;
|
---|
172 | }
|
---|
173 |
|
---|
174 | // Initialize class 2D arrays
|
---|
175 | this.data = new double[2*nCurves][nmPoints];
|
---|
176 | this.copy = new double[2*nCurves][nmPoints];
|
---|
177 | this.errors = new double[nCurves][nmPoints];
|
---|
178 | this.errorsCopy = new double[nCurves][nmPoints];
|
---|
179 |
|
---|
180 |
|
---|
181 | // Calculate curve lengths
|
---|
182 | // and check all individual curves have an equal number of abscissae and ordinates
|
---|
183 | int k = 0, l1 = 0, l2 = 0;
|
---|
184 | boolean testlen=true;
|
---|
185 | for(int i=0; i<nCurves; i++){
|
---|
186 | k=2*i;
|
---|
187 | testlen=true;
|
---|
188 | l1=cdata[k].length;
|
---|
189 | l2=cdata[k+1].length;
|
---|
190 | if(l1!=l2)throw new IllegalArgumentException("an x and y array length differ");
|
---|
191 | nPoints[i]=l1;
|
---|
192 |
|
---|
193 | }
|
---|
194 |
|
---|
195 | // Remove both abscissae and ordinates for points equal to dataFill
|
---|
196 | k=0;
|
---|
197 | boolean testopt=true;
|
---|
198 | for(int i=0; i<nCurves; i++){
|
---|
199 | testlen=true;
|
---|
200 | l1=nPoints[i];
|
---|
201 | while(testlen){
|
---|
202 | if(l1<0)throw new IllegalArgumentException("curve array index "+k+ ": blank array");
|
---|
203 | if(cdata[k][l1-1]==dataFill){
|
---|
204 | if(cdata[k+1][l1-1]==dataFill){
|
---|
205 | l1--;
|
---|
206 | testopt=false;
|
---|
207 | }
|
---|
208 | else{
|
---|
209 | testlen=false;
|
---|
210 | }
|
---|
211 | }
|
---|
212 | else{
|
---|
213 | testlen=false;
|
---|
214 | }
|
---|
215 | }
|
---|
216 | nPoints[i]=l1;
|
---|
217 | k+=2;
|
---|
218 | }
|
---|
219 |
|
---|
220 | // Sort arrays into ascending order
|
---|
221 | k = 0;
|
---|
222 | for(int i=0; i<nCurves; i++){
|
---|
223 | double[][] xxx = new double[2][nPoints[i]];
|
---|
224 | for(int j=0; j<nPoints[i]; j++){
|
---|
225 | xxx[0][j] = cdata[k][j];
|
---|
226 | xxx[1][j] = cdata[k+1][j];
|
---|
227 | }
|
---|
228 | xxx = doubleSelectionSort(xxx);
|
---|
229 | for(int j=0; j<nPoints[i]; j++){
|
---|
230 | cdata[k][j] = xxx[0][j];
|
---|
231 | cdata[k+1][j] = xxx[1][j];
|
---|
232 | }
|
---|
233 | k += 2;
|
---|
234 | }
|
---|
235 |
|
---|
236 | // initialize class data variables
|
---|
237 | k=0;
|
---|
238 | int kk=1;
|
---|
239 | for(int i=0; i<nCurves; i++){
|
---|
240 |
|
---|
241 | // reverse order if all abscissae are in descending order
|
---|
242 | int rev = 1;
|
---|
243 | for(int j=1; j<nPoints[i]; j++){
|
---|
244 | if(cdata[k][j]<cdata[k][j-1])rev++;
|
---|
245 | }
|
---|
246 | if(rev==nPoints[i]){
|
---|
247 | double[] hold = new double[nPoints[i]];
|
---|
248 | for(int j=0; j<nPoints[i]; j++)hold[j] = cdata[k][j];
|
---|
249 | for(int j=0; j<nPoints[i]; j++)cdata[k][j] = hold[nPoints[i]-j-1];
|
---|
250 | for(int j=0; j<nPoints[i]; j++)hold[j] = cdata[k+1][j];
|
---|
251 | for(int j=0; j<nPoints[i]; j++)cdata[k+1][j] = hold[nPoints[i]-j-1];
|
---|
252 | }
|
---|
253 |
|
---|
254 | // copy arrays
|
---|
255 | for(int j=0; j<nPoints[i]; j++){
|
---|
256 | this.data[k][j]=cdata[k][j];
|
---|
257 | this.data[k+1][j]=cdata[k+1][j];
|
---|
258 | this.copy[k][j]=cdata[k][j];
|
---|
259 | this.copy[k+1][j]=cdata[k+1][j];
|
---|
260 | }
|
---|
261 |
|
---|
262 | this.lineOpt[i] = 1;
|
---|
263 | this.dashLength[i] = 5;
|
---|
264 | this.trimOpt[i] = false;
|
---|
265 | if(this.lineOpt[i]==1)trimOpt[i] = true;
|
---|
266 | this.minMaxOpt[i]=true;
|
---|
267 | this.pointSize[i]= 6;
|
---|
268 | this.errorBar[i]= false;
|
---|
269 | this.pointOpt[i] = kk;
|
---|
270 | k+=2;
|
---|
271 | kk++;
|
---|
272 | if(kk>npTypes)kk = 1;
|
---|
273 | }
|
---|
274 | }
|
---|
275 |
|
---|
276 | // sort x elements into ascending order with matching switches of y elements
|
---|
277 | // using selection sort method
|
---|
278 | public static double[][] doubleSelectionSort(double[][] aa){
|
---|
279 | int index = 0;
|
---|
280 | int lastIndex = -1;
|
---|
281 | int n = aa[0].length;
|
---|
282 | double holdx = 0.0D;
|
---|
283 | double holdy = 0.0D;
|
---|
284 | double[][] bb = new double[2][n];
|
---|
285 | for(int i=0; i<n; i++){
|
---|
286 | bb[0][i]=aa[0][i];
|
---|
287 | bb[1][i]=aa[1][i];
|
---|
288 | }
|
---|
289 |
|
---|
290 |
|
---|
291 | while(lastIndex != n-1){
|
---|
292 | index = lastIndex+1;
|
---|
293 | for(int i=lastIndex+2; i<n; i++){
|
---|
294 | if(bb[0][i]<bb[0][index]){
|
---|
295 | index=i;
|
---|
296 | }
|
---|
297 | }
|
---|
298 | lastIndex++;
|
---|
299 | holdx=bb[0][index];
|
---|
300 | bb[0][index]=bb[0][lastIndex];
|
---|
301 | bb[0][lastIndex]=holdx;
|
---|
302 | holdy=bb[1][index];
|
---|
303 | bb[1][index]=bb[1][lastIndex];
|
---|
304 | bb[1][lastIndex]=holdy;
|
---|
305 |
|
---|
306 | }
|
---|
307 | return bb;
|
---|
308 | }
|
---|
309 |
|
---|
310 |
|
---|
311 | //Create a data array initialised to dataFill;
|
---|
312 | public static double[][] data(int n, int m){
|
---|
313 | double[][] d = new double[2*n][m];
|
---|
314 | for(int i=0; i<2*n; i++){
|
---|
315 | for(int j=0; j<m; j++){
|
---|
316 | d[i][j]=dataFill;
|
---|
317 | }
|
---|
318 | }
|
---|
319 | return d;
|
---|
320 | }
|
---|
321 |
|
---|
322 | //Change the value used to initialise the datarray
|
---|
323 | public static void setDataFillValue(double dataFill){
|
---|
324 | Plot.dataFill=dataFill;
|
---|
325 | }
|
---|
326 |
|
---|
327 | //Get the value used to initialise the datarray
|
---|
328 | public static double getDataFillValue(){
|
---|
329 | return Plot.dataFill;
|
---|
330 | }
|
---|
331 |
|
---|
332 | // Enter primary graph title
|
---|
333 | public void setGraphTitle(String graphTitle){
|
---|
334 | this.graphTitle=graphTitle;
|
---|
335 | }
|
---|
336 |
|
---|
337 | // Enter second line to graph title
|
---|
338 | public void setGraphTitle2(String graphTitle2){
|
---|
339 | this.graphTitle2=graphTitle2;
|
---|
340 | }
|
---|
341 |
|
---|
342 | // Enter x axis legend
|
---|
343 | public void setXaxisLegend(String xAxisLegend){
|
---|
344 | this.xAxisLegend=xAxisLegend;
|
---|
345 | }
|
---|
346 |
|
---|
347 | // Enter y axis legend
|
---|
348 | public void setYaxisLegend(String yAxisLegend){
|
---|
349 | this.yAxisLegend=yAxisLegend;
|
---|
350 | }
|
---|
351 |
|
---|
352 | // Enter x axis unit name
|
---|
353 | public void setXaxisUnitsName(String xAxisUnits){
|
---|
354 | this.xAxisUnits=xAxisUnits;
|
---|
355 | this.noXunits=false;
|
---|
356 | }
|
---|
357 |
|
---|
358 | // Enter y axis unit name
|
---|
359 | public void setYaxisUnitsName(String yAxisUnits){
|
---|
360 | this.yAxisUnits=yAxisUnits;
|
---|
361 | this.noYunits=false;
|
---|
362 | }
|
---|
363 |
|
---|
364 | // Get pixel length of the x axis
|
---|
365 | public int getXaxisLen(){
|
---|
366 | return this.xLen;
|
---|
367 | }
|
---|
368 |
|
---|
369 | // Get pixel length of the y axis
|
---|
370 | public int getYaxisLen(){
|
---|
371 | return this.yLen;
|
---|
372 | }
|
---|
373 |
|
---|
374 | // Get pixel start of the x axis
|
---|
375 | public int getXlow(){
|
---|
376 | return this.xBot;
|
---|
377 | }
|
---|
378 |
|
---|
379 | // Get pixel end of the y axis
|
---|
380 | public int getYhigh(){
|
---|
381 | return this.yTop;
|
---|
382 | }
|
---|
383 |
|
---|
384 | // Get point size in pixels
|
---|
385 | public int[] getPointsize(){
|
---|
386 | return this.pointSize;
|
---|
387 | }
|
---|
388 |
|
---|
389 | // Get dash length in pixels
|
---|
390 | public int[] getDashlength(){
|
---|
391 | return this.dashLength;
|
---|
392 | }
|
---|
393 |
|
---|
394 | // Get the x axis low factor
|
---|
395 | public double getXlowFac(){
|
---|
396 | return 1.0D-this.xLowFac;
|
---|
397 | }
|
---|
398 |
|
---|
399 | // Get the y axis low factor
|
---|
400 | public double getYlowFac(){
|
---|
401 | return 1.0D-this.yLowFac;
|
---|
402 | }
|
---|
403 |
|
---|
404 | // Get the x axis minimum value
|
---|
405 | public double getXmin(){
|
---|
406 | return this.xMin;
|
---|
407 | }
|
---|
408 |
|
---|
409 | // Get the x axis maximum value
|
---|
410 | public double getXmax(){
|
---|
411 | return this.xMax;
|
---|
412 | }
|
---|
413 |
|
---|
414 | // Get the y axis minimum value
|
---|
415 | public double getYmin(){
|
---|
416 | return this.yMin;
|
---|
417 | }
|
---|
418 |
|
---|
419 | // Get the y axis maximum value
|
---|
420 | public double getYmax(){
|
---|
421 | return this.yMax;
|
---|
422 | }
|
---|
423 |
|
---|
424 | // get line plotting option
|
---|
425 | public int[] getLine(){
|
---|
426 | return this.lineOpt;
|
---|
427 | }
|
---|
428 |
|
---|
429 | // Get point plotting options
|
---|
430 | public int[] getPoint(){
|
---|
431 | return this.pointOpt;
|
---|
432 | }
|
---|
433 |
|
---|
434 | // Get the number of points to be used in the cubic spline interpolation
|
---|
435 | public int getNiPoints(){
|
---|
436 | return this.niPoints;
|
---|
437 | }
|
---|
438 |
|
---|
439 | // Get font size
|
---|
440 | public int getFontSize(){
|
---|
441 | return this.fontSize;
|
---|
442 | }
|
---|
443 |
|
---|
444 | // Reset pixel length of the x axis
|
---|
445 | public void setXaxisLen(int xLen){
|
---|
446 | this.xLen=xLen;
|
---|
447 | this.update();
|
---|
448 | }
|
---|
449 |
|
---|
450 | // Reset pixel length of the y axis
|
---|
451 | public void setYaxisLen(int yLen){
|
---|
452 | this.yLen=yLen;
|
---|
453 | this.update();
|
---|
454 | }
|
---|
455 |
|
---|
456 | // Reset pixel start of the x axis
|
---|
457 | public void setXlow(int xBot){
|
---|
458 | this.xBot=xBot;
|
---|
459 | this.update();
|
---|
460 | }
|
---|
461 |
|
---|
462 | // Reset pixel end of the y axis
|
---|
463 | public void setYhigh(int yTop){
|
---|
464 | this.yTop=yTop;
|
---|
465 | this.update();
|
---|
466 | }
|
---|
467 |
|
---|
468 | // Reset the x axis low factor
|
---|
469 | public void setXlowFac(double xLowFac){
|
---|
470 | this.xLowFac=1.0D-xLowFac;
|
---|
471 | }
|
---|
472 |
|
---|
473 | // Reset the y axis low factor
|
---|
474 | public void setYlowFac(double yLowFac){
|
---|
475 | this.yLowFac=1.0D-yLowFac;
|
---|
476 | }
|
---|
477 |
|
---|
478 | // Reset the x axis offset option
|
---|
479 | public void setNoXoffset(boolean noXoffset){
|
---|
480 | this.noXoffset=noXoffset;
|
---|
481 | }
|
---|
482 |
|
---|
483 | // Reset the y axis offset option
|
---|
484 | public void setNoYoffset(boolean noYoffset){
|
---|
485 | this.noYoffset=noYoffset;
|
---|
486 | }
|
---|
487 |
|
---|
488 | // Reset both the x and y axis offset options to the same optio
|
---|
489 | public void setNoOffset(boolean nooffset){
|
---|
490 | this.noXoffset=nooffset;
|
---|
491 | this.noYoffset=nooffset;
|
---|
492 | }
|
---|
493 |
|
---|
494 | // Get the x axis offset option
|
---|
495 | public boolean getNoXoffset(){
|
---|
496 | return this.noXoffset;
|
---|
497 | }
|
---|
498 |
|
---|
499 | // RGet the y axis offset option
|
---|
500 | public boolean getNoYoffset(){
|
---|
501 | return this.noYoffset;
|
---|
502 | }
|
---|
503 |
|
---|
504 | // Update axis pixel position parameters
|
---|
505 | protected void update(){
|
---|
506 | this.xTop = this.xBot + this.xLen;
|
---|
507 | this.yBot = this.yTop + this.yLen;
|
---|
508 | }
|
---|
509 |
|
---|
510 | // Overwrite line plotting option with different options for individual curves
|
---|
511 | public void setLine(int[] lineOpt){
|
---|
512 | int n=lineOpt.length;
|
---|
513 | if(n!=nCurves)throw new IllegalArgumentException("input array of wrong length");
|
---|
514 | for(int i=0; i<n; i++)if(lineOpt[i]<0 || lineOpt[i]>4)throw new IllegalArgumentException("lineOpt must be 0, 1, 2, 3 or 4");
|
---|
515 | this.lineOpt=lineOpt;
|
---|
516 |
|
---|
517 | // check if data supports cubic spline interpolation if lineOpt = 1 or 2
|
---|
518 | for(int i=0; i<this.lineOpt.length; i++){
|
---|
519 | if(this.lineOpt[i]==1 || this.lineOpt[i]==2){
|
---|
520 | // check if some points reverse direction
|
---|
521 | boolean test0 = false;
|
---|
522 | for(int j=1; j<this.nPoints[i]; j++){
|
---|
523 | if(data[i][j]<data[i][j-1])test0=true;
|
---|
524 | }
|
---|
525 | if(test0){
|
---|
526 | // check if y all in ascending order
|
---|
527 | int rev = 1;
|
---|
528 | for(int j=1; j<nPoints[i]; j++){
|
---|
529 | if(data[2*i][j]>data[2*i][j-1])rev++;
|
---|
530 | }
|
---|
531 | if(rev==nPoints[i]){
|
---|
532 | lineOpt[i]=-lineOpt[i];
|
---|
533 | }
|
---|
534 | else{
|
---|
535 | // check if y all in descending order
|
---|
536 | rev = 1;
|
---|
537 | for(int j=1; j<nPoints[i]; j++){
|
---|
538 | if(data[2*i][j]<data[2*i][j-1])rev++;
|
---|
539 | }
|
---|
540 | if(rev==nPoints[i]){
|
---|
541 | // reverse order of y
|
---|
542 | double[] hold = new double[nPoints[i]];
|
---|
543 | for(int j=0; j<nPoints[i]; j++)hold[j] = data[i][j];
|
---|
544 | for(int j=0; j<nPoints[i]; j++)data[i][j] = hold[nPoints[i]-j-1];
|
---|
545 | for(int j=0; j<nPoints[i]; j++)hold[j] = data[2*i][j];
|
---|
546 | for(int j=0; j<nPoints[i]; j++)data[2*i][j] = hold[nPoints[i]-j-1];
|
---|
547 | this.lineOpt[i] = - lineOpt[i];
|
---|
548 | }
|
---|
549 | else{
|
---|
550 | System.out.println("Curve "+i+" will not support interpolation");
|
---|
551 | System.out.println("Straight connecting line option used");
|
---|
552 | if(this.lineOpt[i]==1) this.lineOpt[i] = 3;
|
---|
553 | if(this.lineOpt[i]==2) this.lineOpt[i] = 4;
|
---|
554 | }
|
---|
555 | }
|
---|
556 | }
|
---|
557 | }
|
---|
558 | }
|
---|
559 | }
|
---|
560 |
|
---|
561 | // Overwrite line plotting option with a single option for all curves
|
---|
562 | public void setLine(int slineOpt){
|
---|
563 | if(slineOpt<0 || slineOpt>3)throw new IllegalArgumentException("lineOpt must be 0, 1, 2 or 3");
|
---|
564 | for(int i=0; i<this.nCurves; i++)this.lineOpt[i]=slineOpt;
|
---|
565 | }
|
---|
566 |
|
---|
567 | // Overwrite dash length with different options for individual curves
|
---|
568 | public void setDashLength(int[] dashLength){
|
---|
569 | if(dashLength.length!=nCurves)throw new IllegalArgumentException("input array of wrong length");
|
---|
570 | this.dashLength=dashLength;
|
---|
571 | }
|
---|
572 |
|
---|
573 | // Overwrite dashLength with a single option for all curves
|
---|
574 | public void setDashLength(int sdashLength){
|
---|
575 | for(int i=0; i<this.nCurves; i++)this.dashLength[i]=sdashLength;
|
---|
576 | }
|
---|
577 |
|
---|
578 | // Overwrite point plotting option with different options for individual curves
|
---|
579 | public void setPoint(int[] pointOpt){
|
---|
580 | int n=pointOpt.length;
|
---|
581 | if(n!=nCurves)throw new IllegalArgumentException("input array of wrong length");
|
---|
582 | for(int i=0; i<n; i++)if(pointOpt[i]<0 || pointOpt[i]>8)throw new IllegalArgumentException("pointOpt must be 0, 1, 2, 3, 4, 5, 6, 7, or 8");
|
---|
583 | this.pointOpt=pointOpt;
|
---|
584 | }
|
---|
585 |
|
---|
586 | // Overwrite point plotting option with a single option for all curves
|
---|
587 | public void setPoint(int spointOpt){
|
---|
588 | if(spointOpt<0 || spointOpt>8)throw new IllegalArgumentException("pointOpt must be 0, 1, 2, 3, 4, 5, 6, 7, or 8");
|
---|
589 | for(int i=0; i<this.nCurves; i++)this.pointOpt[i]=spointOpt;
|
---|
590 | }
|
---|
591 |
|
---|
592 | // Overwrite point size with different options for individual curves
|
---|
593 | public void setPointSize(int[] mpointSize){
|
---|
594 | if(mpointSize.length!=nCurves)throw new IllegalArgumentException("input array of wrong length");
|
---|
595 | for(int i=0; i<this.nCurves; i++){
|
---|
596 | if(mpointSize[i]!=(mpointSize[i]/2)*2)mpointSize[i]++;
|
---|
597 | this.pointSize[i]=mpointSize[i];
|
---|
598 | }
|
---|
599 | }
|
---|
600 |
|
---|
601 | // Overwrite point size with a single option for all curves
|
---|
602 | public void setPointSize(int spointSize){
|
---|
603 | if(spointSize%2!=0)spointSize++;
|
---|
604 | for(int i=0; i<this.nCurves; i++)this.pointSize[i]=spointSize;
|
---|
605 | }
|
---|
606 |
|
---|
607 | // Set errorBar values
|
---|
608 | // Must set each curve individually
|
---|
609 | // nc is the curve identifier (remember curves start at 0)
|
---|
610 | // err are the error bar values which should be an estimate of the standard devition of the experimental point
|
---|
611 | public void setErrorBars(int nc, double[] err){
|
---|
612 | if(err.length!=this.nPoints[nc])throw new IllegalArgumentException("input array of wrong length");
|
---|
613 | this.errorBar[nc] = true;
|
---|
614 | for(int i=0; i<this.nPoints[nc]; i++){
|
---|
615 | this.errors[nc][i] = err[i];
|
---|
616 | this.errorsCopy[nc][i] = err[i];
|
---|
617 | }
|
---|
618 | }
|
---|
619 |
|
---|
620 | // overwrite the number of points to be used in the cubic spline interpolation
|
---|
621 | public void setNiPoints(int niPoints){
|
---|
622 | this.niPoints=niPoints;
|
---|
623 | }
|
---|
624 |
|
---|
625 | // overwrite the font size
|
---|
626 | public void setFontSize(int fontSize){
|
---|
627 | this.fontSize=fontSize;
|
---|
628 | }
|
---|
629 |
|
---|
630 | // overwrite the trim option
|
---|
631 | public void setTrimOpt(boolean[] trim){
|
---|
632 | this.trimOpt=trim;
|
---|
633 | }
|
---|
634 |
|
---|
635 | // overwrite the minMaxOpt option
|
---|
636 | public void setMinMaxOpt(boolean[] minmax){
|
---|
637 | this.minMaxOpt=minmax;
|
---|
638 | }
|
---|
639 |
|
---|
640 | // Calculate scaling factors
|
---|
641 | public static int scale(double mmin, double mmax){
|
---|
642 | int fac=0;
|
---|
643 | double big=0.0D;
|
---|
644 | boolean test=false;
|
---|
645 |
|
---|
646 | if(mmin>=0.0 && mmax>0.0){
|
---|
647 | big=mmax;
|
---|
648 | test=true;
|
---|
649 | }
|
---|
650 | else{
|
---|
651 | if(mmin<0.0 && mmax<=0.0){
|
---|
652 | big=-mmin;
|
---|
653 | test=true;
|
---|
654 | }
|
---|
655 | else{
|
---|
656 | if(mmax>0.0 && mmin<0.0){
|
---|
657 | big=Math.max(mmax, -mmin);
|
---|
658 | test=true;
|
---|
659 | }
|
---|
660 | }
|
---|
661 | }
|
---|
662 |
|
---|
663 | if(test){
|
---|
664 | if(big>100.0){
|
---|
665 | while(big>1.0){
|
---|
666 | big/=10.0;
|
---|
667 | fac--;
|
---|
668 | }
|
---|
669 | }
|
---|
670 | if(big<=0.01){
|
---|
671 | while(big<=0.10){
|
---|
672 | big*=10.0;
|
---|
673 | fac++;
|
---|
674 | }
|
---|
675 | }
|
---|
676 | }
|
---|
677 | return fac;
|
---|
678 | }
|
---|
679 |
|
---|
680 | // Set low value on axis
|
---|
681 | public static void limits(double low, double high, double lowfac, double[]limits){
|
---|
682 |
|
---|
683 | double facl = 1.0D;
|
---|
684 | double fach = 1.0D;
|
---|
685 | if(Math.abs(low)<1.0D)facl=10.0D;
|
---|
686 | if(Math.abs(low)<0.1D)facl=100.0D;
|
---|
687 | if(Math.abs(high)<1.0D)fach=10.0D;
|
---|
688 | if(Math.abs(high)<0.1D)fach=100.0D;
|
---|
689 |
|
---|
690 | double ld=Math.floor(10.0*low*facl)/facl;
|
---|
691 | double hd=Math.ceil(10.0*high*fach)/fach;
|
---|
692 |
|
---|
693 | if(ld>=0.0D && hd>0.0D){
|
---|
694 | if(ld<lowfac*hd){
|
---|
695 | ld=0.0;
|
---|
696 | }
|
---|
697 | }
|
---|
698 | if(ld<0.0D && hd<=0.0D){
|
---|
699 | if(-hd <= -lowfac*ld){
|
---|
700 | hd=0.0;
|
---|
701 | }
|
---|
702 | }
|
---|
703 | limits[0] = ld/10.0;
|
---|
704 | limits[1] = hd/10.0;
|
---|
705 | }
|
---|
706 |
|
---|
707 | // Calculate axis offset value
|
---|
708 | public static double offset(double low, double high){
|
---|
709 |
|
---|
710 | double diff = high - low;
|
---|
711 | double sh = Fmath.sign(high);
|
---|
712 | double sl = Fmath.sign(low);
|
---|
713 | double offset=0.0D;
|
---|
714 | int eh=0, ed=0;
|
---|
715 |
|
---|
716 | if(sh == sl){
|
---|
717 | ed=(int)Math.floor(Fmath.log10(diff));
|
---|
718 | if(sh==1){
|
---|
719 | eh=(int)Math.floor(Fmath.log10(high));
|
---|
720 | if(eh-ed>1)offset = Math.floor(low*Math.pow(10, -ed))*Math.pow(10,ed);
|
---|
721 | }
|
---|
722 | else{
|
---|
723 | eh=(int)Math.floor(Fmath.log10(Math.abs(low)));
|
---|
724 | if(eh-ed>1)offset = Math.floor(high*Math.pow(10, -ed))*Math.pow(10,ed);
|
---|
725 | }
|
---|
726 | }
|
---|
727 | return offset;
|
---|
728 | }
|
---|
729 |
|
---|
730 |
|
---|
731 | // Calculate scaling and offset values for both axes
|
---|
732 | public void axesScaleOffset(){
|
---|
733 |
|
---|
734 | double[] limit = new double[2];
|
---|
735 |
|
---|
736 | // tranfer data from copy to enable redrawing
|
---|
737 | int k=0;
|
---|
738 | for(int i=0; i<nCurves; i++){
|
---|
739 | for(int j=0; j<nPoints[i]; j++){
|
---|
740 | this.data[k][j]=this.copy[k][j];
|
---|
741 | this.data[k+1][j]=this.copy[k+1][j];
|
---|
742 | this.errors[i][j]=this.errorsCopy[i][j];
|
---|
743 | if(this.errorBar[i])this.errors[i][j]+=this.data[k+1][j];
|
---|
744 | }
|
---|
745 | k+=2;
|
---|
746 | }
|
---|
747 |
|
---|
748 | // Find mimium and maximum data values
|
---|
749 | minMax();
|
---|
750 |
|
---|
751 | // Calculate x axis offset values and subtract it from the data
|
---|
752 | if(!noXoffset)this.xOffset=offset(this.xMin, this.xMax);
|
---|
753 | if(this.xOffset!=0.0){
|
---|
754 | k=0;
|
---|
755 | for(int i=0; i<this.nCurves; i++){
|
---|
756 | for(int j=0; j<this.nPoints[i]; j++){
|
---|
757 | this.data[k][j] -= this.xOffset;
|
---|
758 | }
|
---|
759 | k+=2;
|
---|
760 | }
|
---|
761 | this.xMin -= this.xOffset;
|
---|
762 | this.xMax -= this.xOffset;
|
---|
763 | }
|
---|
764 |
|
---|
765 | // Calculate y axis offset values and subtract it from the data
|
---|
766 | if(!noYoffset)this.yOffset=offset(this.yMin, this.yMax);
|
---|
767 | if(this.yOffset!=0.0){
|
---|
768 | k=1;
|
---|
769 | for(int i=0; i<this.nCurves; i++){
|
---|
770 | for(int j=0; j<this.nPoints[i]; j++){
|
---|
771 | this.data[k][j] -= this.yOffset;
|
---|
772 | if(this.errorBar[i])this.errors[i][j] -= this.yOffset;
|
---|
773 | }
|
---|
774 | k+=2;
|
---|
775 | }
|
---|
776 | this.yMin -= this.yOffset;
|
---|
777 | this.yMax -= this.yOffset;
|
---|
778 | }
|
---|
779 |
|
---|
780 | // Calculate x axes scale values and scale data
|
---|
781 | this.xFac = scale(this.xMin, this.xMax);
|
---|
782 | if(this.xFac!=0){
|
---|
783 | k=0;
|
---|
784 | for(int i=0; i<this.nCurves; i++){
|
---|
785 | for(int j=0; j<this.nPoints[i]; j++){
|
---|
786 | this.data[k][j] *= Math.pow(10, this.xFac+1);
|
---|
787 | }
|
---|
788 | k+=2;
|
---|
789 | }
|
---|
790 | this.xMin *= Math.pow(10, this.xFac+1);
|
---|
791 | this.xMax *= Math.pow(10, this.xFac+1);
|
---|
792 | }
|
---|
793 |
|
---|
794 | // Calculate y axes scale values and scale data
|
---|
795 | this.yFac = scale(this.yMin, this.yMax);
|
---|
796 | if(this.yFac!=0){
|
---|
797 | k=1;
|
---|
798 | for(int i=0; i<this.nCurves; i++){
|
---|
799 | for(int j=0; j<this.nPoints[i]; j++){
|
---|
800 | this.data[k][j] *= Math.pow(10, yFac+1);
|
---|
801 | if(this.errorBar[i])this.errors[i][j] *= Math.pow(10, this.yFac+1);
|
---|
802 | }
|
---|
803 | k+=2;
|
---|
804 | }
|
---|
805 | this.yMin *= Math.pow(10, this.yFac+1);
|
---|
806 | this.yMax *= Math.pow(10, this.yFac+1);
|
---|
807 | }
|
---|
808 |
|
---|
809 | // Calculate scaled low and high values
|
---|
810 | // x axis
|
---|
811 | limits(this.xMin, this.xMax, this.xLowFac, limit);
|
---|
812 | this.xLow = limit[0];
|
---|
813 | this.xHigh = limit[1];
|
---|
814 | if(xLow<0 && xHigh>0)xZero=true;
|
---|
815 | // y axis
|
---|
816 | limits(this.yMin, this.yMax, this.yLowFac, limit);
|
---|
817 | this.yLow = limit[0];
|
---|
818 | this.yHigh = limit[1];
|
---|
819 | if(yLow<0 && yHigh>0)yZero=true;
|
---|
820 |
|
---|
821 | // Calculate tick parameters
|
---|
822 | // x axis
|
---|
823 | this.xTicks = ticks(this.xLow, this.xHigh, this.xAxisNo, this.xAxisChar);
|
---|
824 | this.xHigh = this.xAxisNo[this.xTicks-1];
|
---|
825 | if(this.xLow!=this.xAxisNo[0]){
|
---|
826 | if(this.xOffset!=0.0D){
|
---|
827 | this.xOffset = this.xOffset - this.xLow + this.xAxisNo[0];
|
---|
828 | }
|
---|
829 | this.xLow = this.xAxisNo[0];
|
---|
830 | }
|
---|
831 | // y axis
|
---|
832 | this.yTicks = ticks(this.yLow, this.yHigh, this.yAxisNo, this.yAxisChar);
|
---|
833 | this.yHigh = this.yAxisNo[this.yTicks-1];
|
---|
834 | if(this.yLow!=this.yAxisNo[0]){
|
---|
835 | if(this.yOffset!=0.0D){
|
---|
836 | this.yOffset = this.yOffset - this.yLow + this.yAxisNo[0];
|
---|
837 | }
|
---|
838 | this.yLow = this.yAxisNo[0];
|
---|
839 | }
|
---|
840 |
|
---|
841 | }
|
---|
842 |
|
---|
843 | // Calculate axis ticks and tick values
|
---|
844 | public static int ticks(double low, double high, double[] tickval, String[] tickchar){
|
---|
845 |
|
---|
846 |
|
---|
847 | // Find range
|
---|
848 | int[] trunc = {1, 1, 1, 2, 3};
|
---|
849 | double[] scfac1 = {1.0, 10.0, 1.0, 0.1, 0.01};
|
---|
850 | double[] scfac2 = {1.0, 1.0, 0.1, 0.01, 0.001};
|
---|
851 |
|
---|
852 | double rmax = Math.abs(high);
|
---|
853 | double temp = Math.abs(low);
|
---|
854 | if(temp>rmax)rmax = temp;
|
---|
855 | int range = 0;
|
---|
856 | if(rmax<=100.0D){
|
---|
857 | range = 1;
|
---|
858 | }
|
---|
859 | if(rmax<=10.0D){
|
---|
860 | range = 2;
|
---|
861 | }
|
---|
862 | if(rmax<=1.0D){
|
---|
863 | range = 3;
|
---|
864 | }
|
---|
865 | if(rmax<=0.1D){
|
---|
866 | range = 4;
|
---|
867 | }
|
---|
868 | if(rmax>100.0D || rmax<0.01)range = 0;
|
---|
869 |
|
---|
870 | // Calculate number of ticks
|
---|
871 | double inc = 0.0D;
|
---|
872 | double bot = 0.0D;
|
---|
873 | double top = 0.0D;
|
---|
874 | int sgn = 0;
|
---|
875 | int dirn = 0;
|
---|
876 | if(high>0.0D && low>=0.0D){
|
---|
877 | inc = Math.ceil((high-low)/scfac1[range])*scfac2[range];
|
---|
878 | dirn = 1;
|
---|
879 | bot = low;
|
---|
880 | top = high;
|
---|
881 | sgn = 1;
|
---|
882 | }
|
---|
883 | else{
|
---|
884 | if(high<=0 && low<0.0D){
|
---|
885 | inc = Math.ceil((high-low)/scfac1[range])*scfac2[range];
|
---|
886 | dirn = -1;
|
---|
887 | bot = high;
|
---|
888 | top = low;
|
---|
889 | sgn = -1;
|
---|
890 | }
|
---|
891 | else{
|
---|
892 | double up = Math.abs(Math.ceil(high));
|
---|
893 | double down = Math.abs(Math.floor(low));
|
---|
894 | int np = 0;
|
---|
895 | if(up>=down){
|
---|
896 | dirn = 2;
|
---|
897 | np = (int)Math.rint(10.0*up/(up+down));
|
---|
898 | inc = Math.ceil((high*10/np)/scfac1[range])*scfac2[range];
|
---|
899 | bot = 0.0D;
|
---|
900 | top = high;
|
---|
901 | sgn = 1;
|
---|
902 | }
|
---|
903 | else{
|
---|
904 | dirn = -2;
|
---|
905 | np = (int)Math.rint(10.0D*down/(up+down));
|
---|
906 | inc = Math.ceil((Math.abs(low*10/np))/scfac1[range])*scfac2[range];
|
---|
907 | bot = 0.0D;
|
---|
908 | top = low;
|
---|
909 | sgn = -1;
|
---|
910 | }
|
---|
911 | }
|
---|
912 | }
|
---|
913 |
|
---|
914 | int nticks = 1;
|
---|
915 | double sum = bot;
|
---|
916 | boolean test = true;
|
---|
917 | while(test){
|
---|
918 | sum = sum + sgn*inc;
|
---|
919 | nticks++;
|
---|
920 | if(Math.abs(sum)>=Math.abs(top))test=false;
|
---|
921 | }
|
---|
922 |
|
---|
923 | // Calculate tick values
|
---|
924 | int npExtra = 0;
|
---|
925 | double[] ttickval = null;;
|
---|
926 | switch(dirn){
|
---|
927 | case 1: ttickval = new double[nticks];
|
---|
928 | tickval[0]=Fmath.truncate(low, trunc[range]);
|
---|
929 | for(int i=1; i<nticks; i++){
|
---|
930 | tickval[i] = Fmath.truncate(tickval[i-1]+inc, trunc[range]);
|
---|
931 | }
|
---|
932 | break;
|
---|
933 | case -1: ttickval = new double[nticks];
|
---|
934 | ttickval[0]=Fmath.truncate(high, trunc[range]);
|
---|
935 | for(int i=1; i<nticks; i++){
|
---|
936 | ttickval[i] = Fmath.truncate(ttickval[i-1]-inc, trunc[range]);
|
---|
937 | }
|
---|
938 | ttickval = Fmath.reverseArray(ttickval);
|
---|
939 | for(int i=0; i<nticks; i++)tickval[i] = ttickval[i];
|
---|
940 | break;
|
---|
941 | case 2: npExtra = (int)Math.ceil(-low/inc);
|
---|
942 | nticks += npExtra;
|
---|
943 | ttickval = new double[nticks];
|
---|
944 | tickval[0]=Fmath.truncate(-npExtra*inc, trunc[range]);
|
---|
945 | for(int i=1; i<nticks; i++){
|
---|
946 | tickval[i] = Fmath.truncate(tickval[i-1]+inc, trunc[range]);
|
---|
947 | }
|
---|
948 | break;
|
---|
949 | case -2: npExtra = (int)Math.ceil(high/inc);
|
---|
950 | nticks += npExtra;
|
---|
951 | ttickval = new double[nticks];
|
---|
952 | ttickval[0]=Fmath.truncate(npExtra*inc, trunc[range]);
|
---|
953 | for(int i=1; i<nticks; i++){
|
---|
954 | ttickval[i] = Fmath.truncate(ttickval[i-1]-inc, trunc[range]);
|
---|
955 | }
|
---|
956 | ttickval = Fmath.reverseArray(ttickval);
|
---|
957 | for(int i=0; i<nticks; i++)tickval[i] = ttickval[i];
|
---|
958 | break;
|
---|
959 | }
|
---|
960 |
|
---|
961 | // ensure a zero value is truly zero and not a zero with rounding errors, e.g. 1e-17
|
---|
962 | ArrayMaths am = new ArrayMaths(tickval);
|
---|
963 | double max = am.maximum();
|
---|
964 | double min = Math.abs(am.minimum());
|
---|
965 | boolean testZero = true;
|
---|
966 | int counter = 0;
|
---|
967 | while(testZero){
|
---|
968 | if(Math.abs(tickval[counter])<max*1e-4 || Math.abs(tickval[counter])<min*1e-4){
|
---|
969 | tickval[counter] = 0.0;
|
---|
970 | testZero = false;
|
---|
971 | }
|
---|
972 | else{
|
---|
973 | counter++;
|
---|
974 | if(counter>=nticks)testZero = false;
|
---|
975 | }
|
---|
976 | }
|
---|
977 |
|
---|
978 | // set String form of tick values
|
---|
979 | for(int i=0; i<nticks; i++){
|
---|
980 | tickchar[i] = String.valueOf(tickval[i]);
|
---|
981 | tickchar[i] = tickchar[i].trim();
|
---|
982 | }
|
---|
983 |
|
---|
984 | return nticks;
|
---|
985 | }
|
---|
986 |
|
---|
987 | // Find minimum and maximum x and y values
|
---|
988 | public void minMax(){
|
---|
989 | boolean test = true;
|
---|
990 |
|
---|
991 | int ii=0;
|
---|
992 | while(test){
|
---|
993 | if(this.minMaxOpt[ii]){
|
---|
994 | test=false;
|
---|
995 | this.xMin=this.data[2*ii][0];
|
---|
996 | this.xMax=this.data[2*ii][0];
|
---|
997 | this.yMin=this.data[2*ii+1][0];
|
---|
998 | if(this.errorBar[ii])this.yMin=2.0D*this.yMin-this.errors[ii][0];
|
---|
999 | this.yMax=this.data[2*ii+1][0];
|
---|
1000 | if(this.errorBar[ii])this.yMax=errors[ii][0];
|
---|
1001 | }
|
---|
1002 | else{
|
---|
1003 | ii++;
|
---|
1004 | if(ii>nCurves)throw new IllegalArgumentException("At least one curve must be included in the maximum/minimum calculation");
|
---|
1005 | }
|
---|
1006 | }
|
---|
1007 |
|
---|
1008 | int k=0;
|
---|
1009 | double yMint=0.0D, yMaxt=0.0D;
|
---|
1010 | for(int i=0; i<this.nCurves; i++){
|
---|
1011 | if(minMaxOpt[i]){
|
---|
1012 | for(int j=0; j<this.nPoints[i]; j++){
|
---|
1013 | if(this.xMin>this.data[k][j])this.xMin=this.data[k][j];
|
---|
1014 | if(this.xMax<this.data[k][j])this.xMax=this.data[k][j];
|
---|
1015 | yMint=this.data[k+1][j];
|
---|
1016 | if(errorBar[i])yMint=2.0D*yMint-errors[i][j];
|
---|
1017 | if(this.yMin>yMint)this.yMin=yMint;
|
---|
1018 | yMaxt=this.data[k+1][j];
|
---|
1019 | if(errorBar[i])yMaxt=errors[i][j];
|
---|
1020 | if(this.yMax<yMaxt)this.yMax=yMaxt;
|
---|
1021 | }
|
---|
1022 | }
|
---|
1023 | k+=2;
|
---|
1024 | }
|
---|
1025 |
|
---|
1026 | if(this.xMin==this.xMax){
|
---|
1027 | if(this.xMin==0.0D){
|
---|
1028 | this.xMin=0.1D;
|
---|
1029 | this.xMax=0.1D;
|
---|
1030 | }
|
---|
1031 | else{
|
---|
1032 | if(this.xMin<0.0D){
|
---|
1033 | this.xMin=this.xMin*1.1D;
|
---|
1034 | }
|
---|
1035 | else{
|
---|
1036 | this.xMax=this.xMax*1.1D;
|
---|
1037 | }
|
---|
1038 | }
|
---|
1039 | }
|
---|
1040 |
|
---|
1041 | if(this.yMin==this.yMax){
|
---|
1042 | if(this.yMin==0.0D){
|
---|
1043 | this.yMin=0.1D;
|
---|
1044 | this.yMax=0.1D;
|
---|
1045 | }
|
---|
1046 | else{
|
---|
1047 | if(this.yMin<0.0D){
|
---|
1048 | this.yMin=this.yMin*1.1D;
|
---|
1049 | }
|
---|
1050 | else{
|
---|
1051 | this.yMax=this.yMax*1.1D;
|
---|
1052 | }
|
---|
1053 | }
|
---|
1054 | }
|
---|
1055 | }
|
---|
1056 |
|
---|
1057 | // Convert offset value to a string and reformat if in E format
|
---|
1058 | protected static String offsetString(double offset){
|
---|
1059 | String stroffset = String.valueOf(offset);
|
---|
1060 | String substr1="", substr2="", substr3="";
|
---|
1061 | String zero ="0";
|
---|
1062 | int posdot = stroffset.indexOf('.');
|
---|
1063 | int posexp = stroffset.indexOf('E');
|
---|
1064 |
|
---|
1065 | if(posexp==-1){
|
---|
1066 | return stroffset;
|
---|
1067 | }
|
---|
1068 | else{
|
---|
1069 | substr1 = stroffset.substring(posexp+1);
|
---|
1070 | int n = Integer.parseInt(substr1);
|
---|
1071 | substr1 = stroffset.substring(0,posexp);
|
---|
1072 | if(n>=0){
|
---|
1073 | for(int i=0; i<n; i++){
|
---|
1074 | substr1 = substr1 + zero;
|
---|
1075 | }
|
---|
1076 | return substr1;
|
---|
1077 | }
|
---|
1078 | else{
|
---|
1079 | substr2 = substr1.substring(0, posdot+1);
|
---|
1080 | substr3 = substr1.substring(posdot+1);
|
---|
1081 | for(int i=0; i<-n; i++){
|
---|
1082 | substr2 = substr1 + zero;
|
---|
1083 | }
|
---|
1084 | substr2 = substr2 + substr3;
|
---|
1085 | return substr2;
|
---|
1086 | }
|
---|
1087 | }
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | // check whether point in line segment is to be drawn
|
---|
1091 | public boolean printCheck(boolean trim, int xoldpoint, int xnewpoint, int yoldpoint, int ynewpoint){
|
---|
1092 |
|
---|
1093 | boolean btest2=true;
|
---|
1094 |
|
---|
1095 | if(trim){
|
---|
1096 | if(xoldpoint<xBot)btest2=false;
|
---|
1097 | if(xoldpoint>xTop)btest2=false;
|
---|
1098 | if(xnewpoint<xBot)btest2=false;
|
---|
1099 | if(xnewpoint>xTop)btest2=false;
|
---|
1100 | if(yoldpoint>yBot)btest2=false;
|
---|
1101 | if(yoldpoint<yTop)btest2=false;
|
---|
1102 | if(ynewpoint>yBot)btest2=false;
|
---|
1103 | if(ynewpoint<yTop)btest2=false;
|
---|
1104 | }
|
---|
1105 |
|
---|
1106 | return btest2;
|
---|
1107 | }
|
---|
1108 |
|
---|
1109 | // Draw graph
|
---|
1110 | public void graph(Graphics g){
|
---|
1111 |
|
---|
1112 | // Set font type and size
|
---|
1113 | g.setFont(new Font("serif", Font.PLAIN, this.fontSize));
|
---|
1114 | FontMetrics fm = g.getFontMetrics();
|
---|
1115 |
|
---|
1116 | // calculation of all graphing parameters and data scaling
|
---|
1117 | axesScaleOffset();
|
---|
1118 |
|
---|
1119 | // Draw title, legends and axes
|
---|
1120 | String xoffstr = offsetString(xOffset);
|
---|
1121 | String yoffstr = offsetString(yOffset);
|
---|
1122 | String bunit1 = " /( ";
|
---|
1123 | String bunit2 = " )";
|
---|
1124 | String bunit3 = " / ";
|
---|
1125 | String bunit4 = " ";
|
---|
1126 | String bunit5 = " x 10";
|
---|
1127 | String bunit6 = "10";
|
---|
1128 | String nounit = " ";
|
---|
1129 | String xbrack1 = bunit1;
|
---|
1130 | String xbrack2 = bunit2;
|
---|
1131 | String xbrack3 = bunit5;
|
---|
1132 | if(this.xFac==0){
|
---|
1133 | xbrack1 = bunit3;
|
---|
1134 | xbrack2 = "";
|
---|
1135 | xbrack3 = "";
|
---|
1136 | }
|
---|
1137 | String ybrack1 = bunit1;
|
---|
1138 | String ybrack2 = bunit2;
|
---|
1139 | String ybrack3 = bunit5;
|
---|
1140 | if(this.yFac==0){
|
---|
1141 | ybrack1 = bunit3;
|
---|
1142 | ybrack2 = "";
|
---|
1143 | ybrack3 = "";
|
---|
1144 | }
|
---|
1145 | if(noXunits){
|
---|
1146 | if(xFac==0){
|
---|
1147 | xbrack1=nounit;
|
---|
1148 | xbrack2=nounit;
|
---|
1149 | xbrack3=nounit;
|
---|
1150 | }
|
---|
1151 | else{
|
---|
1152 | xbrack1=bunit3;
|
---|
1153 | xbrack2=bunit4;
|
---|
1154 | xbrack3=bunit6;
|
---|
1155 | }
|
---|
1156 | }
|
---|
1157 | if(noYunits){
|
---|
1158 | if(yFac==0){
|
---|
1159 | ybrack1=nounit;
|
---|
1160 | ybrack2=nounit;
|
---|
1161 | ybrack3=nounit;
|
---|
1162 | }
|
---|
1163 | else{
|
---|
1164 | ybrack1=bunit3;
|
---|
1165 | ybrack2=bunit4;
|
---|
1166 | ybrack3=bunit6;
|
---|
1167 | }
|
---|
1168 | }
|
---|
1169 |
|
---|
1170 | double xLen=xTop-xBot;
|
---|
1171 | double yLen=yBot-yTop;
|
---|
1172 |
|
---|
1173 | // Print title
|
---|
1174 | String sp = " + ", sn = " - ";
|
---|
1175 | String ss=sn;
|
---|
1176 | g.drawString(this.graphTitle+" ", 15,15);
|
---|
1177 | g.drawString(this.graphTitle2+" ", 15,35);
|
---|
1178 | if(this.xOffset<0){
|
---|
1179 | ss=sp;
|
---|
1180 | xOffset=-xOffset;
|
---|
1181 | }
|
---|
1182 |
|
---|
1183 | // Print legends
|
---|
1184 | int sw=0;
|
---|
1185 | String ssx="", ssy="", sws1="", sws2="";
|
---|
1186 | if(this.xFac==0 && this.xOffset==0){
|
---|
1187 | g.drawString(this.xAxisLegend+xbrack1+this.xAxisUnits+xbrack2, xBot-4,yBot+32);
|
---|
1188 | }
|
---|
1189 | else{
|
---|
1190 | if(this.xOffset==0){
|
---|
1191 | ssx = this.xAxisLegend + xbrack1 + this.xAxisUnits + xbrack3;
|
---|
1192 | sw = fm.stringWidth(ssx);
|
---|
1193 | g.drawString(ssx, xBot-4,yBot+42);
|
---|
1194 | sws1=String.valueOf(-this.xFac-1);
|
---|
1195 | g.drawString(sws1, xBot-4+sw+1,yBot+32);
|
---|
1196 | sw += fm.stringWidth(sws1);
|
---|
1197 | g.drawString(xbrack2, xBot-4+sw+1,yBot+42);
|
---|
1198 | }
|
---|
1199 | else{
|
---|
1200 | if(this.xFac==0){
|
---|
1201 | g.drawString(this.xAxisLegend + ss + xoffstr + xbrack1+this.xAxisUnits+xbrack2, xBot-4,yBot+30);
|
---|
1202 | }
|
---|
1203 | else{
|
---|
1204 | ssx = this.xAxisLegend + ss + xoffstr + xbrack1+this.xAxisUnits+xbrack3;
|
---|
1205 | sw = fm.stringWidth(ssx);
|
---|
1206 | g.drawString(ssx, xBot-4,yBot+37);
|
---|
1207 | sws1 = String.valueOf(-this.xFac-1);
|
---|
1208 | g.drawString(sws1, xBot-4+sw+1,yBot+32);
|
---|
1209 | sw += fm.stringWidth(sws1);
|
---|
1210 | g.drawString(xbrack2, xBot-4+sw+1,yBot+37);
|
---|
1211 | }
|
---|
1212 | }
|
---|
1213 | }
|
---|
1214 |
|
---|
1215 | ss=sn;
|
---|
1216 | if(yOffset<0){
|
---|
1217 | ss=sp;
|
---|
1218 | yOffset=-yOffset;
|
---|
1219 | }
|
---|
1220 |
|
---|
1221 | if(yFac==0 && yOffset==0){
|
---|
1222 | g.drawString(this.yAxisLegend+" ", 15,yTop-25);
|
---|
1223 | g.drawString(ybrack1+this.yAxisUnits+ybrack2, 15,yTop-10);
|
---|
1224 | }
|
---|
1225 | else{
|
---|
1226 | if(yOffset==0){
|
---|
1227 | g.drawString(this.yAxisLegend, 15,yTop-35);
|
---|
1228 | sws1 = ybrack1+this.yAxisUnits + ybrack3;
|
---|
1229 | g.drawString(sws1, 15,yTop-15);
|
---|
1230 | sw = fm.stringWidth(sws1);
|
---|
1231 | sws2=String.valueOf(-this.yFac-1);
|
---|
1232 | g.drawString(sws2, 15+sw+1,yTop-20);
|
---|
1233 | sw += fm.stringWidth(sws2);
|
---|
1234 | g.drawString(ybrack2, 15+sw+1,yTop-15);
|
---|
1235 | }
|
---|
1236 | else{
|
---|
1237 | if(yFac==0){
|
---|
1238 | g.drawString(this.yAxisLegend + ss + yoffstr, 15,yTop-25);
|
---|
1239 | g.drawString(ybrack1+this.yAxisUnits+ybrack2, 15,yTop-10);
|
---|
1240 | }
|
---|
1241 | else{
|
---|
1242 | ssy = this.yAxisLegend + ss + yoffstr;
|
---|
1243 | g.drawString(ssy, 15,yTop-35);
|
---|
1244 | sws1 = ybrack1+this.yAxisUnits + ybrack3;
|
---|
1245 | g.drawString(sws1, 15,yTop-15);
|
---|
1246 | sw = fm.stringWidth(sws1);
|
---|
1247 | sws2=String.valueOf(-this.yFac-1);
|
---|
1248 | g.drawString(sws2, 15+sw+1,yTop-20);
|
---|
1249 | sw += fm.stringWidth(sws2);
|
---|
1250 | g.drawString(ybrack2, 15+sw+1,yTop-15);
|
---|
1251 | }
|
---|
1252 | }
|
---|
1253 | }
|
---|
1254 |
|
---|
1255 | // Draw axes
|
---|
1256 | int zdif=0, zold=0, znew=0, zzer=0;
|
---|
1257 | double csstep=0.0D;
|
---|
1258 | double xdenom=(xHigh-xLow);
|
---|
1259 | double ydenom=(yHigh-yLow);
|
---|
1260 |
|
---|
1261 | g.drawLine(xBot, yBot, xTop, yBot);
|
---|
1262 | g.drawLine(xBot, yTop, xTop, yTop);
|
---|
1263 | g.drawLine(xBot, yBot, xBot, yTop);
|
---|
1264 | g.drawLine(xTop, yBot, xTop, yTop);
|
---|
1265 |
|
---|
1266 |
|
---|
1267 | // Draw zero lines if drawn axes are not at zero and a zero value lies on an axis
|
---|
1268 | if(xZero){
|
---|
1269 | zdif=8;
|
---|
1270 | zzer=xBot+(int)(((0.0-xLow)/xdenom)*xLen);
|
---|
1271 | g.drawLine(zzer,yTop,zzer,yTop+8);
|
---|
1272 | g.drawLine(zzer,yBot,zzer,yBot-8);
|
---|
1273 | zold=yTop;
|
---|
1274 | while(zold+zdif<yBot){
|
---|
1275 | znew=zold+zdif;
|
---|
1276 | g.drawLine(zzer, zold, zzer, znew);
|
---|
1277 | zold=znew+zdif;
|
---|
1278 | }
|
---|
1279 | }
|
---|
1280 |
|
---|
1281 | if(yZero){
|
---|
1282 | zdif=8;
|
---|
1283 | zzer=yBot-(int)(((0.0-yLow)/ydenom)*yLen);
|
---|
1284 | g.drawLine(xBot,zzer,xBot+8,zzer);
|
---|
1285 | g.drawLine(xTop,zzer,xTop-8,zzer);
|
---|
1286 | zold=xBot;
|
---|
1287 | while(zold+zdif<xTop){
|
---|
1288 | znew=zold+zdif;
|
---|
1289 | g.drawLine(zold, zzer, znew, zzer);
|
---|
1290 | zold=znew+zdif;
|
---|
1291 | }
|
---|
1292 | }
|
---|
1293 |
|
---|
1294 | // Draw tick marks and axis numbers
|
---|
1295 | int xt=0;
|
---|
1296 | //double xtep=(double)(xTop-xBot)/((double)(this.xTicks-1));
|
---|
1297 | for(int ii=0; ii<this.xTicks; ii++)
|
---|
1298 | {
|
---|
1299 | xt=xBot+(int)(((this.xAxisNo[ii]-xLow)/xdenom)*xLen);
|
---|
1300 | g.drawLine(xt,yBot,xt,yBot-8);
|
---|
1301 | g.drawLine(xt,yTop,xt,yTop+8);
|
---|
1302 | g.drawString(xAxisChar[ii]+" ",xt-4,yBot+18);
|
---|
1303 | }
|
---|
1304 |
|
---|
1305 | int yt=0;
|
---|
1306 | int yCharLenMax=yAxisChar[0].length();
|
---|
1307 | for(int ii=1; ii<this.yTicks; ii++)if(yAxisChar[ii].length()>yCharLenMax)yCharLenMax=yAxisChar[ii].length();
|
---|
1308 | int shift = (yCharLenMax-3)*5;
|
---|
1309 | double ytep=(double)(-yTop+yBot)/((double)(this.yTicks-1));
|
---|
1310 | for(int ii=0; ii<this.yTicks; ii++)
|
---|
1311 | {
|
---|
1312 | yt=yBot-(int)Math.round(ii*ytep);
|
---|
1313 | yt=yBot-(int)(((this.yAxisNo[ii]-yLow)/ydenom)*yLen);
|
---|
1314 | g.drawLine(xBot,yt,xBot+8,yt);
|
---|
1315 | g.drawLine(xTop,yt,xTop-8,yt);
|
---|
1316 | g.drawString(yAxisChar[ii]+" ",xBot-30-shift,yt+4);
|
---|
1317 | }
|
---|
1318 |
|
---|
1319 | int dsum=0; // dashed line counter
|
---|
1320 | boolean dcheck=true; // dashed line check
|
---|
1321 |
|
---|
1322 | // Draw curves
|
---|
1323 | int kk=0;
|
---|
1324 | int xxp=0, yyp=0, yype=0;
|
---|
1325 | int xoldpoint=0, xnewpoint=0, yoldpoint=0, ynewpoint=0;
|
---|
1326 | int ps=0, psh=0, nxpoints=0;
|
---|
1327 | double ics[]= new double[niPoints];
|
---|
1328 | boolean btest2=true;
|
---|
1329 |
|
---|
1330 | for(int i=0; i<this.nCurves; i++){
|
---|
1331 | // cubic spline interpolation option
|
---|
1332 | nxpoints=this.nPoints[i];
|
---|
1333 | double xcs[]= new double[nxpoints];
|
---|
1334 | double ycs[]= new double[nxpoints];
|
---|
1335 |
|
---|
1336 | if(lineOpt[i]==1 || lineOpt[i]==2){
|
---|
1337 | CubicSpline cs = new CubicSpline(this.nPoints[i]);
|
---|
1338 | for(int ii=0; ii<nxpoints; ii++){
|
---|
1339 | xcs[ii]=this.data[kk][ii];
|
---|
1340 | }
|
---|
1341 | csstep=(xcs[nxpoints-1]-xcs[0])/(niPoints-1);
|
---|
1342 | ics[0]=xcs[0];
|
---|
1343 | for(int ii=1; ii<niPoints; ii++){
|
---|
1344 | ics[ii]=ics[ii-1]+csstep;
|
---|
1345 | }
|
---|
1346 | ics[niPoints-1] = xcs[nxpoints-1];
|
---|
1347 | for(int ii=0; ii<nxpoints; ii++){
|
---|
1348 | ycs[ii]=this.data[kk+1][ii];
|
---|
1349 | }
|
---|
1350 |
|
---|
1351 | cs.resetData(xcs, ycs);
|
---|
1352 | cs.calcDeriv();
|
---|
1353 | xoldpoint=xBot+(int)(((xcs[0]-xLow)/xdenom)*xLen);
|
---|
1354 | yoldpoint=yBot-(int)(((ycs[0]-yLow)/ydenom)*yLen);
|
---|
1355 | for(int ii=1; ii<niPoints; ii++){
|
---|
1356 | xnewpoint=xBot+(int)(((ics[ii]-xLow)/xdenom)*xLen);
|
---|
1357 | ynewpoint=yBot-(int)(((cs.interpolate(ics[ii])-yLow)/ydenom)*yLen);
|
---|
1358 | btest2=printCheck(trimOpt[i], xoldpoint, xnewpoint, yoldpoint, ynewpoint);
|
---|
1359 | if(btest2){
|
---|
1360 | if(this.lineOpt[i]==2){
|
---|
1361 | dsum++;
|
---|
1362 | if(dsum>dashLength[i]){
|
---|
1363 | dsum=0;
|
---|
1364 | if(dcheck){
|
---|
1365 | dcheck=false;
|
---|
1366 | }
|
---|
1367 | else{
|
---|
1368 | dcheck=true;
|
---|
1369 | }
|
---|
1370 | }
|
---|
1371 | }
|
---|
1372 | if(dcheck)g.drawLine(xoldpoint,yoldpoint,xnewpoint,ynewpoint);
|
---|
1373 | }
|
---|
1374 | xoldpoint=xnewpoint;
|
---|
1375 | yoldpoint=ynewpoint;
|
---|
1376 | }
|
---|
1377 | }
|
---|
1378 |
|
---|
1379 | if(lineOpt[i]==-1 || lineOpt[i]==-2){
|
---|
1380 | CubicSpline cs = new CubicSpline(this.nPoints[i]);
|
---|
1381 | for(int ii=0; ii<nxpoints; ii++){
|
---|
1382 | xcs[ii]=this.data[kk][ii];
|
---|
1383 | }
|
---|
1384 | for(int ii=0; ii<nxpoints; ii++){
|
---|
1385 | ycs[ii]=this.data[kk+1][ii];
|
---|
1386 | }
|
---|
1387 | csstep=(ycs[nxpoints-1]-ycs[0])/(niPoints-1);
|
---|
1388 | ics[0]=ycs[0];
|
---|
1389 | for(int ii=1; ii<niPoints; ii++){
|
---|
1390 | ics[ii]=ics[ii-1]+csstep;
|
---|
1391 | }
|
---|
1392 | ics[niPoints-1] = ycs[nxpoints-1];
|
---|
1393 |
|
---|
1394 | cs.resetData(ycs, xcs);
|
---|
1395 | cs.calcDeriv();
|
---|
1396 | xoldpoint=xBot+(int)(((xcs[0]-xLow)/xdenom)*xLen);
|
---|
1397 | yoldpoint=yBot-(int)(((ycs[0]-yLow)/ydenom)*yLen);
|
---|
1398 | for(int ii=1; ii<niPoints; ii++){
|
---|
1399 | ynewpoint=yBot+(int)(((ics[ii]-yLow)/ydenom)*yLen);
|
---|
1400 | xnewpoint=xBot-(int)(((cs.interpolate(ics[ii])-xLow)/xdenom)*xLen);
|
---|
1401 | btest2=printCheck(trimOpt[i], xoldpoint, xnewpoint, yoldpoint, ynewpoint);
|
---|
1402 | if(btest2){
|
---|
1403 | if(this.lineOpt[i]==2){
|
---|
1404 | dsum++;
|
---|
1405 | if(dsum>dashLength[i]){
|
---|
1406 | dsum=0;
|
---|
1407 | if(dcheck){
|
---|
1408 | dcheck=false;
|
---|
1409 | }
|
---|
1410 | else{
|
---|
1411 | dcheck=true;
|
---|
1412 | }
|
---|
1413 | }
|
---|
1414 | }
|
---|
1415 | if(dcheck)g.drawLine(xoldpoint,yoldpoint,xnewpoint,ynewpoint);
|
---|
1416 | }
|
---|
1417 | xoldpoint=xnewpoint;
|
---|
1418 | yoldpoint=ynewpoint;
|
---|
1419 | }
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 | if(lineOpt[i]==3){
|
---|
1423 | // Join points option
|
---|
1424 | dsum=0;
|
---|
1425 | dcheck=true;
|
---|
1426 | xoldpoint=xBot+(int)((((this.data[kk][0])-xLow)/xdenom)*xLen);
|
---|
1427 | yoldpoint=yBot-(int)((((this.data[kk+1][0])-yLow)/ydenom)*yLen);
|
---|
1428 | for(int ii=1; ii<nxpoints; ii++){
|
---|
1429 | xnewpoint=xBot+(int)((((this.data[kk][ii])-xLow)/xdenom)*xLen);
|
---|
1430 | ynewpoint=yBot-(int)((((this.data[kk+1][ii])-yLow)/ydenom)*yLen);
|
---|
1431 | btest2=printCheck(trimOpt[i], xoldpoint, xnewpoint, yoldpoint, ynewpoint);
|
---|
1432 | if(btest2)g.drawLine(xoldpoint,yoldpoint,xnewpoint,ynewpoint);
|
---|
1433 | xoldpoint=xnewpoint;
|
---|
1434 | yoldpoint=ynewpoint;
|
---|
1435 | }
|
---|
1436 | }
|
---|
1437 |
|
---|
1438 | if(lineOpt[i]==4){
|
---|
1439 | // Join points with dotted line option
|
---|
1440 |
|
---|
1441 | // lines between points
|
---|
1442 | int[] lengths = new int[nxpoints-1];
|
---|
1443 | double[] gradients = new double[nxpoints-1];
|
---|
1444 | double[] intercepts = new double[nxpoints-1];
|
---|
1445 | int totalLength = 0;
|
---|
1446 | xoldpoint=xBot+(int)((((this.data[kk][0])-xLow)/xdenom)*xLen);
|
---|
1447 | yoldpoint=yBot-(int)((((this.data[kk+1][0])-yLow)/ydenom)*yLen);
|
---|
1448 | for(int ii=1; ii<nxpoints; ii++){
|
---|
1449 | xnewpoint=xBot+(int)((((this.data[kk][ii])-xLow)/xdenom)*xLen);
|
---|
1450 | ynewpoint=yBot-(int)((((this.data[kk+1][ii])-yLow)/ydenom)*yLen);
|
---|
1451 | lengths[ii-1] = (int)Fmath.hypot((double)(xnewpoint-xoldpoint), (double)(ynewpoint-yoldpoint));
|
---|
1452 | totalLength += lengths[ii-1];
|
---|
1453 | gradients[ii-1] = (double)(ynewpoint-yoldpoint)/(double)(xnewpoint-xoldpoint);
|
---|
1454 | intercepts[ii-1] = (double)yoldpoint - gradients[ii-1]*xoldpoint;
|
---|
1455 | xoldpoint=xnewpoint;
|
---|
1456 | yoldpoint=ynewpoint;
|
---|
1457 | }
|
---|
1458 |
|
---|
1459 | // number of points
|
---|
1460 | int incrmt = totalLength/(4*niPoints-1);
|
---|
1461 | int nlpointsold = 0;
|
---|
1462 | int nlpointsnew = 0;
|
---|
1463 | int totalLpoints = 1;
|
---|
1464 | for(int ii=1; ii<nxpoints; ii++){
|
---|
1465 | totalLpoints++;
|
---|
1466 | nlpointsnew = lengths[ii-1]/incrmt;
|
---|
1467 | for(int jj = nlpointsold+1; jj<(nlpointsnew + nlpointsold); jj++)totalLpoints ++;
|
---|
1468 | nlpointsold = nlpointsold + nlpointsnew;
|
---|
1469 | }
|
---|
1470 |
|
---|
1471 | // fill arrays
|
---|
1472 | int[] xdashed = new int[totalLpoints];
|
---|
1473 | int[] ydashed = new int[totalLpoints];
|
---|
1474 | nlpointsold = 0;
|
---|
1475 | nlpointsnew = 0;
|
---|
1476 | xdashed[0] = xBot+(int)((((this.data[kk][0])-xLow)/xdenom)*xLen);
|
---|
1477 | ydashed[0] = yBot-(int)((((this.data[kk+1][0])-yLow)/ydenom)*yLen);
|
---|
1478 | for(int ii=1; ii<nxpoints; ii++){
|
---|
1479 | nlpointsnew = lengths[ii-1]/incrmt;
|
---|
1480 | xdashed[nlpointsnew + nlpointsold] = xBot+(int)((((this.data[kk][ii])-xLow)/xdenom)*xLen);
|
---|
1481 | ydashed[nlpointsnew + nlpointsold] = yBot-(int)((((this.data[kk+1][ii])-yLow)/ydenom)*yLen);
|
---|
1482 | if(Math.abs(gradients[ii-1])>0.5){
|
---|
1483 | int diff = (ydashed[nlpointsnew + nlpointsold] - ydashed[nlpointsold])/nlpointsnew;
|
---|
1484 | for(int jj = nlpointsold+1; jj<(nlpointsnew + nlpointsold); jj++){
|
---|
1485 | ydashed[jj] = ydashed[jj-1]+diff;
|
---|
1486 | if(Fmath.isInfinity(Math.abs(gradients[ii-1]))){
|
---|
1487 | xdashed[jj] = xdashed[nlpointsnew + nlpointsold];
|
---|
1488 | }
|
---|
1489 | else{
|
---|
1490 | xdashed[jj] = (int)(((double)ydashed[jj] - intercepts[ii-1])/gradients[ii-1]);
|
---|
1491 | }
|
---|
1492 | }
|
---|
1493 | }
|
---|
1494 | else{
|
---|
1495 | int diff = (xdashed[nlpointsnew + nlpointsold] - xdashed[nlpointsold])/nlpointsnew;
|
---|
1496 | for(int jj = nlpointsold+1; jj<(nlpointsnew + nlpointsold); jj++){
|
---|
1497 | xdashed[jj] = xdashed[jj-1]+diff;
|
---|
1498 | ydashed[jj] = (int)(gradients[ii-1]*ydashed[jj] + intercepts[ii-1]);
|
---|
1499 | }
|
---|
1500 | }
|
---|
1501 | nlpointsold = nlpointsold + nlpointsnew;
|
---|
1502 | }
|
---|
1503 |
|
---|
1504 | dsum=0;
|
---|
1505 | dcheck=true;
|
---|
1506 | for(int ii=1; ii<totalLpoints; ii++){
|
---|
1507 | dsum++;
|
---|
1508 | if(dsum>dashLength[i]){
|
---|
1509 | dsum=0;
|
---|
1510 | if(dcheck){
|
---|
1511 | dcheck=false;
|
---|
1512 | }
|
---|
1513 | else{
|
---|
1514 | dcheck=true;
|
---|
1515 | }
|
---|
1516 | }
|
---|
1517 | if(dcheck)g.drawLine(xdashed[ii-1],ydashed[ii-1],xdashed[ii],ydashed[ii]);
|
---|
1518 | }
|
---|
1519 | }
|
---|
1520 |
|
---|
1521 |
|
---|
1522 |
|
---|
1523 | // Plot points
|
---|
1524 | if(pointOpt[i]>0){
|
---|
1525 | for(int ii=0; ii<nxpoints; ii++){
|
---|
1526 | ps=this.pointSize[i];
|
---|
1527 | psh=ps/2;
|
---|
1528 | xxp=xBot+(int)(((this.data[kk][ii]-xLow)/xdenom)*xLen);
|
---|
1529 | yyp=yBot-(int)(((this.data[kk+1][ii]-yLow)/ydenom)*yLen);
|
---|
1530 | switch(pointOpt[i]){
|
---|
1531 | case 1: g.drawOval(xxp-psh, yyp-psh, ps, ps);
|
---|
1532 | break;
|
---|
1533 | case 2: g.drawRect(xxp-psh, yyp-psh, ps, ps);
|
---|
1534 | break;
|
---|
1535 | case 3: g.drawLine(xxp-psh, yyp, xxp, yyp+psh);
|
---|
1536 | g.drawLine(xxp, yyp+psh, xxp+psh, yyp);
|
---|
1537 | g.drawLine(xxp+psh, yyp, xxp, yyp-psh);
|
---|
1538 | g.drawLine(xxp, yyp-psh, xxp-psh, yyp);
|
---|
1539 | break;
|
---|
1540 | case 4: g.fillOval(xxp-psh, yyp-psh, ps, ps);
|
---|
1541 | break;
|
---|
1542 | case 5: g.fillRect(xxp-psh, yyp-psh, ps, ps);
|
---|
1543 | break;
|
---|
1544 | case 6: for(int jj=0; jj<psh; jj++)g.drawLine(xxp-jj, yyp-psh+jj, xxp+jj, yyp-psh+jj);
|
---|
1545 | for(int jj=0; jj<=psh; jj++)g.drawLine(xxp-psh+jj, yyp+jj, xxp+psh-jj, yyp+jj);
|
---|
1546 | break;
|
---|
1547 | case 7: g.drawLine(xxp-psh, yyp-psh, xxp+psh, yyp+psh);
|
---|
1548 | g.drawLine(xxp-psh, yyp+psh, xxp+psh, yyp-psh);
|
---|
1549 | break;
|
---|
1550 | case 8: g.drawLine(xxp-psh, yyp, xxp+psh, yyp);
|
---|
1551 | g.drawLine(xxp, yyp+psh, xxp, yyp-psh);
|
---|
1552 | break;
|
---|
1553 | default:g.drawLine(xxp-psh, yyp-psh, xxp+psh, yyp+psh);
|
---|
1554 | g.drawLine(xxp-psh, yyp+psh, xxp+psh, yyp-psh);
|
---|
1555 | break;
|
---|
1556 | }
|
---|
1557 |
|
---|
1558 | if(this.errorBar[i]){
|
---|
1559 | yype=yBot-(int)(((errors[i][ii]-yLow)/ydenom)*yLen);
|
---|
1560 | g.drawLine(xxp, yyp, xxp, yype);
|
---|
1561 | g.drawLine(xxp-4, yype, xxp+4, yype);
|
---|
1562 | yype=2*yyp-yype;
|
---|
1563 | g.drawLine(xxp, yyp, xxp, yype);
|
---|
1564 | g.drawLine(xxp-4, yype, xxp+4, yype);
|
---|
1565 | }
|
---|
1566 | }
|
---|
1567 | }
|
---|
1568 | kk+=2;
|
---|
1569 | }
|
---|
1570 | }
|
---|
1571 |
|
---|
1572 | // Return the serial version unique identifier
|
---|
1573 | public static long getSerialVersionUID(){
|
---|
1574 | return Plot.serialVersionUID;
|
---|
1575 | }
|
---|
1576 | }
|
---|