package diagapplet.plotter; import java.util.Vector; import java.util.Hashtable; import java.util.Enumeration; import java.awt.*; import java.awt.event.*; import java.text.DecimalFormat; /* * * PlotGraph * */ public class PlotGraph extends Panel implements MouseListener, MouseMotionListener { static public boolean use_buffer = false; static public int max_points_per_plot = -1; // -1 = no limit public int dplotter_num = -1; private int max_scroll_x = 0; private int max_scroll_y = 0; public int repaint_count = 0; public int paint_count = 0; boolean repaint_just_issued = false; String line_style = "11011"; int line_width = 1; public boolean show_lines = true; public boolean show_key = false; public boolean repaint_needed = true; public boolean rescale_to_selected_rectangle_needed = false; int m_width = 0; int m_height = 0; double x_max = 1.0; double y_max = 1.0; double x_min = -1.0; double y_min = -1.0; int scroll_height = 0; int scroll_width = 0; public boolean show_grid = true; public boolean show_axis = true; public boolean label_grid = true; public boolean mark_points = true; public boolean label_points = false; public static Color axis_color = null; public static Color grid_color = null; public static Color back_color = null; double grid_x = 1.0; double grid_y = 1.0; int grid_y_spacing = 10; int grid_x_spacing = 10; int x_offset = 0; int y_offset = 0; public static Hashtable plots = null; public static boolean m_color = true; int m_scroll_x = 0; int m_scroll_y = 0; Dimension m_prefDim; public double x_scale; public double y_scale; int last_scroll_x = 0; int last_scroll_y = 0; public boolean show_rect = false; Rectangle selected_rectangle = null; static public boolean debug_on = false; public static final int CARTESIAN_COORD_TYPE = 1; public static final int POLAR_COORD_TYPE = 2; public int coordinate_type = CARTESIAN_COORD_TYPE; public static final int ANGLE_DEGREE_UNITS = 1; public static final int ANGLE_RAD_UNITS = 2; public static final int ANGLE_RADPI_UNITS = 3; public int angle_unit_type = ANGLE_DEGREE_UNITS; public int radius_lines = 8; public int angle_lines = 8; public static Color zero_rad_color = null; public static DecimalFormat df_noexponent = null; public static DecimalFormat df_exponent = null; static { try { df_noexponent = new DecimalFormat("###.##"); try { df_exponent = new DecimalFormat("0.##E0"); } catch(Exception e) { df_exponent = df_noexponent; } } catch(Exception e) { e.printStackTrace(); } } public static String format_double(double d) { try { if(Math.abs(d) <= 0.01 || Math.abs(d) >= 1000.0) { if(null == df_exponent) { return Double.toString(d); } return df_exponent.format(d); } else { if(null == df_noexponent) { return Double.toString(d); } return df_noexponent.format(d); } } catch(Exception e) { e.printStackTrace(); } return Double.toString(d); } public PlotGraph(int start_width,int start_height) { repaint_needed = true; image_needs_to_be_updated =true; repaint_just_issued = false; m_width = start_width; scroll_width = start_width; m_height = start_height; scroll_height = start_height; m_prefDim = new Dimension(m_width,m_height); selected_rectangle = new Rectangle(); show_rect = false; changeScale(x_min, x_max, scroll_width, y_min, y_max, scroll_height); if(null == plots) { plots = new Hashtable(); } if(use_buffer) { bufferImage = createImage(m_width, m_height); } addMouseListener(this); addMouseMotionListener(this); } int plot_clicking_on = -1; long time_of_last_click = 0; public void mouseClicked(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); if(show_key) { if(x > 30 && x < 70 && y > 15 && y < keyVector.size()*15+20) { int new_plot_clicking_on = (y-15)/15; if(new_plot_clicking_on == plot_clicking_on && new_plot_clicking_on >= 0 && new_plot_clicking_on < keyVector.size()) { PlotData pd = (PlotData) keyVector.elementAt(plot_clicking_on); if(null == pd.show) { pd.show = new boolean[dplotter_num+1]; } if(pd.show.length <= dplotter_num) { boolean new_show[] = new boolean[dplotter_num+1]; for(int i = 0; i < pd.show.length; i++) { new_show[i] = pd.show[i]; } for(int i = pd.show.length; i < dplotter_num+1; i++) { new_show[i] = true; } pd.show = new_show; } pd.show[dplotter_num] = ! pd.show[dplotter_num]; } } } plot_clicking_on = -1; } public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } public void mousePressed(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); repaint_needed = true; selected_rectangle.x = x; selected_rectangle.y = y; selected_rectangle.width = 0; selected_rectangle.height = 0; show_rect = true; if(show_key) { if(x > 30 && x < 70 && y > 15 && y < keyVector.size()*15+20) { if(Math.abs(System.currentTimeMillis() - time_of_last_click) > 1000) { plot_clicking_on = -1; } int new_plot_clicking_on = (y-15)/15; if(new_plot_clicking_on == plot_clicking_on && new_plot_clicking_on >= 0 && new_plot_clicking_on < keyVector.size()) { PlotData pd = (PlotData) keyVector.elementAt(plot_clicking_on); if(null == pd.show) { pd.show = new boolean[dplotter_num+1]; } if(pd.show.length <= dplotter_num) { boolean new_show[] = new boolean[dplotter_num+1]; for(int i = 0; i < pd.show.length; i++) { new_show[i] = pd.show[i]; } for(int i = pd.show.length; i < dplotter_num+1; i++) { new_show[i] = true; } pd.show = new_show; } pd.show[dplotter_num] = ! pd.show[dplotter_num]; plot_clicking_on = -1; } else { plot_clicking_on = new_plot_clicking_on; time_of_last_click = System.currentTimeMillis(); } } else { plot_clicking_on = -1; } } else { plot_clicking_on = -1; } } public void mouseMoved(MouseEvent evt) { } public void mouseDragged(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); int temp; if(debug_on) { System.out.println("PlotGraph.mouseDragged("+evt+") x="+x+", y="+y); } repaint_needed = true; if(x > selected_rectangle.x) { selected_rectangle.width = x - selected_rectangle.x; } else { temp = selected_rectangle.x; selected_rectangle.x = x; selected_rectangle.width += temp - selected_rectangle.x ; } if(y > selected_rectangle.y) { selected_rectangle.height = y - selected_rectangle.y; } else { temp = selected_rectangle.y; selected_rectangle.y = y; selected_rectangle.height += temp - selected_rectangle.y ; } show_rect = true; } public void mouseReleased(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); if(debug_on) { System.out.println("PlotGraph.mouseReleased("+evt+") x="+x+", y="+y); } if(show_rect && selected_rectangle.width > 5 && selected_rectangle.height > 5) { rescale_to_selected_rectangle_needed = true; show_rect = false; repaint_just_issued = false; //System.out.println("mouseUp setting repaint_needed = true"); repaint_needed = true; return; } show_rect = false; image_needs_to_be_updated =true; } public static void AddPlot(PlotData pd, String name) { for(int i = 0; i < dplotter.dplotter_vector.size(); i++) { dplotter dp = (dplotter) dplotter.dplotter_vector.elementAt(i); if(null != dp) { if(null != dp.plot_graph) { dp.plot_graph.repaint_needed = true; dp.plot_graph.repaint_just_issued = false; } } } pd.name = name; plots.put(name,pd); if(null == keyVector) { keyVector = new Vector(); } keyVector.addElement(pd); } public PlotData GetPlot( String name) { return (PlotData) plots.get(name); } public static void RemoveAllPlots() { plots = new Hashtable(); if(null != keyVector) { keyVector.removeAllElements(); } } public void RemovePlot( String name) { plots.remove(name); if(null != keyVector) { keyVector.removeAllElements(); Enumeration plots_enum = plots.elements(); while(plots_enum.hasMoreElements()) { PlotData pd = (PlotData) plots_enum.nextElement(); keyVector.addElement(pd); } } image_needs_to_be_updated =true; } public static void AddPointToPlot(PlotData pd,double x, double y,boolean connected) { for(int i = 0; i < dplotter.dplotter_vector.size(); i++) { dplotter dp = (dplotter) dplotter.dplotter_vector.elementAt(i); if(null != dp) { if(null != dp.plot_graph) { dp.plot_graph.repaint_needed = true; dp.plot_graph.repaint_just_issued = false; } } } //int converted_x = (int) ((x - x_min)*x_scale); //int converted_y = (int) ((y_max - y)*y_scale); pd.v.addElement(new PlotPoint((int) x, (int) y,x,y,connected)); if(max_points_per_plot > 0) { while(pd.v.size() > max_points_per_plot) { pd.v.removeElementAt(0); } } } public void equalizeAxis() { image_needs_to_be_updated =true; try { if(debug_on) { System.out.println("equalizeAxis called."); System.out.println("m_width = "+m_width); System.out.println("m_height = "+m_height); System.out.println("scroll_width = "+scroll_width); System.out.println("scroll_height = "+scroll_height); System.out.println("x_scale = "+x_scale); System.out.println("y_scale = "+y_scale); } if(Math.abs((x_scale-y_scale)/(x_scale+y_scale)) < 1E-6) { return; } changeScale(x_min, x_max, scroll_width, y_min, y_max, scroll_height); if(debug_on) { System.out.println("After first changeScale."); System.out.println("m_width = "+m_width); System.out.println("m_height = "+m_height); System.out.println("scroll_width = "+scroll_width); System.out.println("scroll_height = "+scroll_height); System.out.println("x_scale = "+x_scale); System.out.println("y_scale = "+y_scale); } if(x_scale > y_scale) { double x_range = (x_max - x_min); if(debug_on) { System.out.println("x_range="+x_range); } int new_scroll_width = (int) (y_scale*x_range); if(debug_on) { System.out.println("new_scroll_width="+new_scroll_width); } if(new_scroll_width <= m_width) { double x_mid = x_min + x_range/2; double new_x_range = scroll_width/y_scale; if(debug_on) { System.out.println("x_mid="+x_mid); System.out.println("new_x_range="+new_x_range); } x_min = x_mid - new_x_range/2; x_max = x_mid + new_x_range/2; new_scroll_width = scroll_width; } changeScale(x_min, x_max, new_scroll_width, y_min, y_max, scroll_height); } else { double y_range = (y_max - y_min); if(debug_on) { System.out.println("y_range="+y_range); } int new_scroll_height = (int) (x_scale*y_range); if(debug_on) { System.out.println("new_scroll_height="+new_scroll_height); } if(new_scroll_height <= m_height) { double y_mid = y_min + y_range/2; double new_y_range = scroll_height/x_scale; if(debug_on) { System.out.println("y_mid="+y_mid); System.out.println("new_y_range="+new_y_range); } y_min = y_mid - new_y_range/2; y_max = y_mid + new_y_range/2; new_scroll_height = scroll_height; } changeScale(x_min, x_max, scroll_width, y_min, y_max, new_scroll_height); } /* if(x_scale > y_scale) { System.out.println("scroll_width="+scroll_width); double x_range = scroll_width/y_scale; System.out.println("x_range="+x_range); System.out.println("x_max="+x_max); System.out.println("x_min="+x_min); double x_range_inc = x_range - (x_max - x_min); System.out.println("x_range_inc="+x_range_inc); double new_x_max = x_max + x_range_inc/2.0; double new_x_min = x_min - x_range_inc/2.0; changeScale(new_x_min, new_x_max, scroll_width, y_min, y_max, scroll_height); } else { System.out.println("scroll_height="+scroll_height); double y_range = scroll_height/x_scale; System.out.println("y_range="+y_range); System.out.println("y_max="+y_max); System.out.println("y_min="+y_min); double y_range_inc = y_range - (y_max - y_min); System.out.println("y_range_inc="+y_range_inc); double new_y_max = y_max + y_range_inc/2.0; double new_y_min = y_min - y_range_inc/2.0; changeScale(x_min, x_max, scroll_width, new_y_min, new_y_max, scroll_height); } */ if(debug_on) { System.out.println("x_scale = "+x_scale); System.out.println("y_scale = "+y_scale); } } catch(Exception e) { e.printStackTrace(); } } int x_scale_change_factor = 2; int y_scale_change_factor = 2; public void changeScale(double new_x_min, double new_x_max, int new_scroll_width, double new_y_min, double new_y_max, int new_scroll_height) { repaint_needed = true; image_needs_to_be_updated =true; repaint_just_issued = false; rescale_to_selected_rectangle_needed = false; if(debug_on) { System.out.println("changeScale("+new_x_min+", "+new_x_max+", "+new_scroll_width+", "+new_y_min+", "+new_y_max+", "+new_scroll_height+")"); } if(new_scroll_width < m_width) { new_scroll_width = m_width; } if(new_scroll_height < m_height) { new_scroll_height = m_height; } if(new_x_max <= new_x_min) { new_x_max = new_x_min + 1.0; } if(new_y_max <= new_y_min) { new_y_max = new_y_min + 1.0; } double new_x_scale = (new_scroll_width)/(new_x_max - new_x_min); double new_y_scale = (new_scroll_height)/(new_y_max - new_y_min); int new_x_offset = (int) (-new_x_min*new_x_scale); int new_y_offset = (int) (new_y_max*new_y_scale); if(debug_on) { System.out.println("new_x_scale ="+new_x_scale); System.out.println("new_y_scale ="+new_y_scale); System.out.println("new_x_offset ="+new_x_offset); System.out.println("new_y_offset ="+new_y_offset); } /* if(plots != null) { Enumeration plots_enumeration = plots.elements(); while(plots_enumeration.hasMoreElements()) { PlotData plot_data = (PlotData) plots_enumeration.nextElement(); int j = 0; for( j = 0; j < plot_data.v.size(); j++) { PlotPoint current_point = (PlotPoint) plot_data.v.elementAt(j); current_point.x = (int) ((current_point.orig_x - new_x_min)*new_x_scale); current_point.y = (int) ((new_y_max - current_point.orig_y)*new_y_scale); } } } */ x_offset = new_x_offset; y_offset = new_y_offset; x_scale = new_x_scale; y_scale = new_y_scale; scroll_width = new_scroll_width; scroll_height = new_scroll_height; x_min = new_x_min; x_max = new_x_max; y_min = new_y_min; y_max = new_y_max; max_scroll_x = (int) ((new_x_max - new_x_min)*new_x_scale - m_width); if(max_scroll_x < 0) { max_scroll_x = -max_scroll_x; } max_scroll_y = (int) ((new_y_max - new_y_min)*new_y_scale - m_height); if(max_scroll_y < 0) { max_scroll_y = -max_scroll_y; } if(debug_on) { System.out.println("max_scroll_x ="+max_scroll_x); System.out.println("max_scroll_y ="+max_scroll_y); } grid_x_spacing = (int) (grid_x*x_scale); while(grid_x_spacing < 25) { grid_x = x_scale_change_factor*grid_x; grid_x_spacing = (int) (grid_x*x_scale); if(x_scale_change_factor == 2) { x_scale_change_factor = 5; } else { x_scale_change_factor = 2; } } while(grid_x_spacing > m_width/2) { grid_x = grid_x/y_scale_change_factor; grid_x_spacing = (int) (grid_x*x_scale); if(y_scale_change_factor == 2) { y_scale_change_factor = 5; } else { y_scale_change_factor = 2; } } grid_y_spacing = (int) (grid_y*y_scale); while(grid_y_spacing < 25) { grid_y = y_scale_change_factor*grid_y; grid_y_spacing = (int) (grid_y*y_scale); if(y_scale_change_factor == 2) { y_scale_change_factor = 5; } else { y_scale_change_factor = 2; } } while(grid_y_spacing > m_height/2) { grid_y = grid_y/y_scale_change_factor; grid_y_spacing = (int) (grid_y*y_scale); if(y_scale_change_factor == 2) { y_scale_change_factor = 5; } else { y_scale_change_factor = 2; } } } public Dimension getPreferredSize() { return m_prefDim; } public Dimension getMinimumSize() { return m_prefDim; } public void UpdateDisplay(boolean force_repaint) { if(dplotter.loading_url) { return; } if(force_repaint) { image_needs_to_be_updated =true; repaint_needed = true; } if(last_scroll_x != m_scroll_x) { image_needs_to_be_updated =true; last_scroll_x = m_scroll_x; repaint_needed = true; } if(last_scroll_y != m_scroll_y) { image_needs_to_be_updated =true; last_scroll_y = m_scroll_y; repaint_needed = true; } if(show_rect && use_buffer) { repaint_just_issued = false; repaint_count++; repaint(500); return; } if(repaint_needed && !repaint_just_issued) { if(!show_rect) { image_needs_to_be_updated =true; repaint_just_issued = true; } repaint_count++; repaint(600); } } public static Vector keyVector = null; private void paintKey(Graphics g) { try { if(null == keyVector) { return; } if(m_color) { g.setColor(Color.white); } else { g.setColor(Color.black); } if(plots != null) { int y_pos = 20; int x_pos = 30; for(int i = 0; i < keyVector.size(); i++) { String shStr = " (hidden)"; PlotData pd = (PlotData) keyVector.elementAt(i); if(pd.show == null) { shStr = " (visible)"; } else { if(pd.show.length <= dplotter_num) { shStr = " (visible)"; } else { if(pd.show[dplotter_num]) { shStr = " (visible)"; } } } if(pd.v.size() < 1 || pd.name.length() < 1) { continue; } if(m_color) { g.setColor(pd.line_color); } EnhancedDrawLine(g,x_pos,y_pos,x_pos+40,y_pos); if(m_color) { g.setColor(pd.point_color); } g.fillRect(x_pos+20,y_pos-2,4,4); if(m_color && axis_color != null) { g.setColor(axis_color); } g.drawString(pd.name + shStr,x_pos+50,y_pos+5); y_pos += 15; } } } catch(Exception e) { e.printStackTrace(); } } private void EnhancedDrawLine(Graphics g,int x1, int y1, int x2, int y2) { int temp; int x_low; int x_high; int x_pos; int y_low; int y_high; int y_pos; int x_diff; int y_diff; int i; double m; double inverse_m; int starting_i = 0; try { if(x2 > x1) { x_low = x1; x_high = x2; } else { x_low = x2; x_high = x1; } if(y2 > y1) { y_low = y1; y_high = y2; } else { y_low = y2; y_high = y1; } x_diff = x_high - x_low; y_diff = y_high - y_low; // Handle vertical line and sindgle point case separately. if(x_diff < 1) { // Handle sindgle point case separately. if(y_diff < 1) { g.fillRect(x_low,y_low,1,1); return; } g.fillRect(x_low,y_low,line_width,y_diff); return; } // Handle horizontal line case separately. if(y_diff < 1) { g.fillRect(x_low,y_low,x_diff,line_width); return; } if(y_diff > x_diff) { // Swap the points to make the higher point (x1,y1) if(y1 > y2) { temp = x2; x2 = x1; x1 = temp; temp = y2; y2 = y1; y1 = temp; } if(y1 > 0) { starting_i = 0; } else { starting_i = -y1; } for(i = starting_i; i < y_diff; i++) { if(line_style != null) { if(line_style.charAt(i%line_style.length()) == '0') { continue; } } inverse_m = ((double)(x2 - x1))/((double)(y2 -y1)); y_pos = y1 + i; if(y_pos > m_height) { break; } x_pos = (int) (x1 + inverse_m*i); if(x_pos > m_width+line_width/2 && inverse_m > 0) { break; } if(x_pos < -line_width/2 && inverse_m < 0) { break; } g.fillRect(x_pos-line_width/2,y_pos,line_width,1); } } else { // Swap the points to make the one to the left (x1,y1) if(x1 > x2) { temp = x2; x2 = x1; x1 = temp; temp = y2; y2 = y1; y1 = temp; } if(x1 > 0) { starting_i = 0; } else { starting_i = -x1; } for(i = starting_i; i < x_diff; i++) { if(line_style != null) { if(line_style.charAt(i%line_style.length()) == '0') { continue; } } m = ((double)(y2 -y1))/ ((double)(x2 - x1)); x_pos = x1 + i; if(x_pos > m_width) { break; } y_pos = (int) (y1 + m*i); if(y_pos > m_height+line_width/2 && m > 0) { break; } if(x_pos < -line_width/2 && m < 0) { break; } g.fillRect(x_pos,y_pos-line_width/2,1,line_width); } } } catch(Exception e) { e.printStackTrace(); } } Font font = null; FontMetrics fm = null; String label_string = null; public void paintGrid(Graphics g) { try { switch(coordinate_type) { case POLAR_COORD_TYPE: paintPolarGrid(g); break; case CARTESIAN_COORD_TYPE: paintCartesianGrid(g); break; } } catch(Exception e) { e.printStackTrace(); } } double x1_last = 0.0; double x2_last = 0.0; double y1_last = 0.0; double y2_last = 0.0; double theta_min_last=0.0; double theta_max_last=0.0; double r_min_last=0.0; double r_max_last=0.0; // java.math.atan2 seems to be broken static double atan2(double x, double y) { if(x == 0 || y == 0) { return 0; } if(x > 0) { return Math.atan(y/x); } else { return Math.atan(y/x)+Math.PI; } } public static String FormatDouble(double d, int length) { //System.out.println("FormatDouble("+d+", "+length+")"); String str = Double.toString(d); //System.out.println("FormatDouble str = "+str); if(str.length() < length) { return str; } int eindex = str.indexOf('E'); String exponent = ""; //System.out.println("FormatDouble eindex = "+eindex); if(eindex > 0) { exponent = str.substring(eindex); str = str.substring(0,eindex); } else { int pindex = str.indexOf('.'); //System.out.println("FormatDouble pindex = "+pindex); if(pindex > 2) { if(pindex > length -1) { exponent = "E" + (pindex-1); str = str.charAt(0)+"."+str.substring(1,pindex) + str.substring(pindex+1); } } else { int exponent_int =0; int i = 0; for( i = 0; i < str.length(); i++) { if(str.charAt(i) != '0' && str.charAt(i) != '.') { break; } if(i > pindex) { exponent_int--; } } //System.out.println("FormatDouble exponent_int = "+exponent_int); if(exponent_int < -3) { exponent = "E"+exponent_int; //System.out.println("FormatDouble i = "+i); //System.out.println("FormatDouble str.charAt(i) = "+str.charAt(i)); //System.out.println("FormatDouble str.substring(i+1) = "+str.substring(i+1)); //System.out.println( str.charAt(i)+'.'+str.substring(i+1)); str = str.charAt(i)+"."+str.substring(i+1); } } } //System.out.println("FormatDouble str = "+str); //System.out.println("FormatDouble exponent = "+exponent); str = str.substring(0,(length - exponent.length()))+exponent; while(true) { char last_char = str.charAt(str.length() -1); int pindex = str.indexOf('.'); if(last_char != ' ' && last_char != '.' && (last_char != '0' || pindex == -1)) { break; } str = str.substring(0, str.length()-1); } return str; } double r_spacing = 1.0; int scale_change = 2; public void paintPolarGrid(Graphics g) { if(m_color && grid_color != null) { g.setColor(grid_color); } double x1,y1,x2,y2; int orig_scroll_x = m_scroll_x; int orig_scroll_y = m_scroll_y; int x_offset_orig = x_offset; int y_offset_orig = y_offset; double x_scale_orig = x_scale; double y_scale_orig = y_scale; double orig_grid_x = grid_x; double orig_grid_y = grid_y; int orig_grid_x_spacing = grid_x_spacing; int orig_grid_y_spacing = grid_y_spacing; int x_pos = 0; int y_pos = 0; x1 = (orig_scroll_x-x_offset_orig)/x_scale; if(x1 != x1_last) { if(debug_on) { System.out.println("x1="+x1); } x1_last = x1; } x2 = (orig_scroll_x-x_offset_orig+m_width)/x_scale; if(x2 != x2_last) { if(debug_on) { System.out.println("x2="+x2); } x2_last = x2; } y1 = (y_offset_orig-orig_scroll_y)/y_scale; if(y1 != y1_last) { if(debug_on) { System.out.println("y1="+y1); } y1_last = y1; } y2 = (y_offset_orig-orig_scroll_y-m_height)/y_scale; if(y2 != y2_last) { if(debug_on) { System.out.println("y2="+y2); } y2_last = y2; } double theta_min = +2.0 *Math.PI; double theta_max = -2.0 * Math.PI; double r_min = 1E9; double r_max = 0; double r; r = Math.sqrt(x1*x1 + y1*y1); if(debug_on) { System.out.println("r11="+r); } if(r_min > r) { r_min = r; } if(r_max < r) { r_max = r; } r = Math.sqrt(x1*x1 + y2*y2); if(debug_on) { System.out.println("r12="+r); } if(r_min > r) { r_min = r; } if(r_max < r) { r_max = r; } r = Math.sqrt(x2*x2 + y1*y1); if(debug_on) { System.out.println("r21="+r); } if(r_min > r) { r_min = r; } if(r_max < r) { r_max = r; } r = Math.sqrt(x2*x2 + y2*y2); if(debug_on) { System.out.println("r22="+r); } if(r_min > r) { r_min = r; } if(r_max < r) { r_max = r; } double theta = atan2(x1,y1); if(debug_on) { System.out.println("theta = "+theta+"("+theta/Math.PI+"*PI)"); } if(theta_min > theta) { theta_min = theta; } if(theta_max < theta) { theta_max = theta; } theta = atan2(x1,y2); if(debug_on) { System.out.println("theta = "+theta+"("+theta/Math.PI+"*PI)"); } if(theta_min > theta) { theta_min = theta; } if(theta_max < theta) { theta_max = theta; } theta = atan2(x2,y1); if(debug_on) { System.out.println("theta = "+theta+"("+theta/Math.PI+"*PI)"); } if(theta_min > theta) { theta_min = theta; } if(theta_max < theta) { theta_max = theta; } theta = atan2(x2,y2); if(debug_on) { System.out.println("theta = "+theta+"("+theta/Math.PI+"*PI)"); } if(theta_min > theta) { theta_min = theta; } if(theta_max < theta) { theta_max = theta; } if( x1*x2 <= 0 && y1*y2 <= 0) { theta_min = 0; theta_max = Math.PI *2; r_min = 0; } else if(x1*x2 <= 0) { if(r_min > Math.abs(y1)) { r_min = Math.abs(y1); } if(r_min > Math.abs(y2)) { r_min = Math.abs(y2); } } else if(y1*y2 <= 0) { if(r_min > Math.abs(x1)) { r_min = Math.abs(x1); } if(r_min > Math.abs(x2)) { r_min = Math.abs(x2); } } if(theta_min >= 2.0*Math.PI) { theta_min -= 2.0*Math.PI; } if(theta_max >= 2.0*Math.PI) { theta_max -= 2.0*Math.PI; } if(theta_min < 0) { theta_min += 2.0*Math.PI; } if(theta_max < 0) { theta_max += 2.0*Math.PI; } if(theta_min > theta_max) { double temp = theta_min; theta_min = theta_max; theta_max = temp; } if(theta_min == theta_max) { theta_min = 0.0; theta_max = Math.PI*2.0; } if(theta_min != theta_min_last) { if(debug_on) { System.out.println("theta_min = "+theta_min+"("+theta_min/Math.PI+"*PI)"); } theta_min_last = theta_min; } if(theta_max != theta_max_last) { if(debug_on) { System.out.println("theta_max = "+theta_max+"("+theta_max/Math.PI+"*PI)"); } theta_max_last = theta_max; } boolean r_new = false; if(r_min != r_min_last) { r_new = true; if(debug_on) { System.out.println("r_min = "+r_min); } r_min_last = r_min; } if(r_max != r_max_last) { r_new = true; if(debug_on) { System.out.println("r_max = "+r_max); } r_max_last = r_max; } double r_mid = (r_max + r_min) / 2.0; double theta_spacing = (theta_max -theta_min)/angle_lines; if(Math.abs(theta_max - theta_min) > Math.PI &&( x1*x2 > 0 || y1*y2 > 0) ) { if(debug_on) { System.out.println("Switching theta_min and theta_max"); System.out.println("x1*x2="+x1*x2+", y1*y2="+y1*y2); System.out.println("theta_min = "+theta_min); System.out.println("theta_max = "+theta_max); } double temp = theta_min; theta_min = theta_max; theta_max = temp; if(theta_min > Math.PI) { theta_min -= Math.PI*2; } if(debug_on) { System.out.println("theta_min = "+theta_min); System.out.println("theta_max = "+theta_max); } theta_spacing = (theta_max -theta_min)/angle_lines; } if(debug_on) { System.out.println("theta_spacing="+theta_spacing); } for(int i = 0; i < (angle_lines+1); i++) { theta = theta_min + i*theta_spacing; if(debug_on) { System.out.println("i="+i+", theta ="+theta); } double xa, xb, ya, yb, xm, ym; xa = r_min * Math.cos(theta); ya = r_min * Math.sin(theta); xb = r_max * Math.cos(theta); yb = r_max * Math.sin(theta); xm = r_mid * Math.cos(theta); ym = r_mid * Math.sin(theta); int xai = (int) ((xa - x_min)*x_scale); int yai = (int) ((y_max - ya)*y_scale); int xbi = (int) ((xb - x_min)*x_scale); int ybi = (int) ((y_max - yb)*y_scale); int xmi = (int) ((xm - x_min)*x_scale); int ymi = (int) ((y_max - ym)*y_scale); EnhancedDrawLine(g,xai- orig_scroll_x,yai- orig_scroll_y,xbi- orig_scroll_x,ybi- orig_scroll_y); if(i != (angle_lines/2) && i != angle_lines) { switch(angle_unit_type) { case ANGLE_DEGREE_UNITS: double theta_degrees = theta*180/Math.PI; g.drawString(FormatDouble(theta_degrees,4)+" deg.", xmi-orig_scroll_x, ymi-orig_scroll_y); break; case ANGLE_RADPI_UNITS: double theta_radpi = theta/Math.PI; g.drawString(FormatDouble(theta_radpi,4)+"PI", xmi-orig_scroll_x, ymi-orig_scroll_y); break; default: g.drawString(FormatDouble(theta,4)+" rad.", xmi-orig_scroll_x, ymi-orig_scroll_y); break; } } } double theta_mid = (theta_max + theta_min)/2.0; int radius_lines_this_time = radius_lines; if(r_new) { r_spacing = (r_max - r_min)/radius_lines; if(debug_on) { System.out.println("r_spacing = "+r_spacing); System.out.println("grid_x = "+grid_x); System.out.println("grid_y = "+grid_y); } if(Math.abs(r_spacing-grid_x) < Math.abs(r_spacing-grid_y)) { if(grid_x > 0) { if(r_spacing < grid_x) { while(r_spacing < grid_x) { if(Math.abs(r_spacing-grid_x)/(r_spacing+grid_x) < 0.667) { r_spacing = grid_x; break; } grid_x /= scale_change; radius_lines_this_time *= scale_change; r_min = ((int) r_min/grid_x) *grid_x; radius_lines_this_time++; if(scale_change == 2) { scale_change = 5; } else { scale_change = 2; } } } } else { while(r_spacing > grid_x) { if(Math.abs(r_spacing-grid_x)/(r_spacing+grid_x) < 0.667) { r_spacing = grid_x; break; } grid_x *= scale_change; r_min = ((int) r_min/grid_x) *grid_x; radius_lines_this_time++; if(scale_change == 2) { scale_change = 5; } else { scale_change = 2; } } } } else { if(grid_y > 0) { if(r_spacing < grid_y) { while(r_spacing < grid_y) { if(Math.abs(r_spacing-grid_y)/(r_spacing+grid_y) < 0.667) { r_spacing = grid_y; break; } grid_y /= scale_change; radius_lines_this_time *= scale_change; r_min = ((int) r_min/grid_y) *grid_y; radius_lines_this_time++; if(scale_change == 2) { scale_change = 5; } else { scale_change = 2; } } } else { while(r_spacing > grid_y) { if(Math.abs(r_spacing-grid_y)/(r_spacing+grid_y) < 0.667) { r_spacing = grid_y; break; } grid_y *= scale_change; r_min = ((int) r_min/grid_y) *grid_y; radius_lines_this_time++; if(scale_change == 2) { scale_change = 5; } else { scale_change = 2; } } } } } } int startAngle = (int) Math.floor(theta_min*180/Math.PI); int arcAngle = (int) Math.ceil((theta_max-theta_min)*180/Math.PI); if(debug_on) { System.out.println("r_spacing="+r_spacing); System.out.println("x_scale="+x_scale+",x_min="+x_min+",y_scale="+y_scale+",y_max="+y_max+",startAngle="+startAngle+",arcAngle="+arcAngle); } boolean set_grid_color = false; for(int i = 0; i < (radius_lines_this_time+1); i++) { r = r_min + i*r_spacing; if(debug_on) { System.out.println("i="+i+",r="+r); } if(r <= 0) { continue; } double xz = -r; double yz = r; int rwi = (int) ((2*r)*x_scale); int rhi = (int) ((2*r)*y_scale); int xzi = (int) ((xz - x_min)*x_scale); int yzi = (int) ((y_max - yz)*y_scale); double xm = r * Math.cos(theta_mid); double ym = r * Math.sin(theta_mid); int xmi = (int) ((xm - x_min)*x_scale); int ymi = (int) ((y_max - ym)*y_scale); if(debug_on) { System.out.println("r = "+r+", xzi="+xzi+", yzi="+yzi+",rwi="+rwi+",rhi="+rhi); } g.drawArc(xzi - orig_scroll_x, yzi-orig_scroll_y, rwi, rhi, startAngle, arcAngle); if(i != (radius_lines)/2) { if(dplotter.use_user_specified_radius_offset) { g.drawString(FormatDouble(r-dplotter.user_specified_radius_offset,4), xmi-orig_scroll_x, ymi-orig_scroll_y); } else { g.drawString(FormatDouble(r,4), xmi-orig_scroll_x, ymi-orig_scroll_y); } } } if(dplotter.use_user_specified_radius_offset && (dplotter.user_specified_radius_offset <= r_max) && (dplotter.user_specified_radius_offset >= r_min)) { if(m_color && null != zero_rad_color) { g.setColor(zero_rad_color); } r = dplotter.user_specified_radius_offset; double xz = -r; double yz = r; int rwi = (int) ((2*r)*x_scale); int rhi = (int) ((2*r)*y_scale); int xzi = (int) ((xz - x_min)*x_scale); int yzi = (int) ((y_max - yz)*y_scale); double xm = r * Math.cos(theta_mid); double ym = r * Math.sin(theta_mid); int xmi = (int) ((xm - x_min)*x_scale); int ymi = (int) ((y_max - ym)*y_scale); if(debug_on) { System.out.println("r = "+r+", xzi="+xzi+", yzi="+yzi+",rwi="+rwi+",rhi="+rhi); } g.drawArc(xzi - orig_scroll_x, yzi-orig_scroll_y, rwi, rhi, startAngle, arcAngle); } // paintCartesianGrid(g); } public void paintCartesianGrid(Graphics g) { try { if(m_color && grid_color != null) { g.setColor(grid_color); } int orig_scroll_x = m_scroll_x; int orig_scroll_y = m_scroll_y; int x_offset_orig = x_offset; int y_offset_orig = y_offset; double x_scale_orig = x_scale; double y_scale_orig = y_scale; double orig_grid_x = grid_x; double orig_grid_y = grid_y; int orig_grid_x_spacing = grid_x_spacing; int orig_grid_y_spacing = grid_y_spacing; int starting_x_grid_line = (orig_scroll_x-x_offset_orig-m_width)/orig_grid_x_spacing-1; int starting_y_grid_line = (y_offset_orig-orig_scroll_y+m_height)/orig_grid_y_spacing+1; int x_pos = 0; int y_pos = 0; int i = 0; for(i = starting_x_grid_line; x_pos -orig_scroll_x < m_width+1; i++) { double x_value = i*orig_grid_x; x_pos = (int) ((x_value - x_min)*x_scale_orig); g.drawLine(x_pos-orig_scroll_x,0,x_pos-orig_scroll_x,m_height); if(label_grid && orig_grid_x_spacing > 20) { if(y_offset_orig - orig_scroll_y < 0) { y_pos = 20; } else if(y_offset_orig - orig_scroll_y > m_height) { y_pos = m_height; } else { y_pos = y_offset_orig - orig_scroll_y; } if(x_value > (orig_grid_x*0.5) || x_value < (-0.5*orig_grid_x)) { g.drawString(format_double(x_value),x_pos-orig_scroll_x+5,y_pos-5); } } } for(i = starting_y_grid_line; y_pos -orig_scroll_y < m_height+1 ; i--) { double y_value = (i)*orig_grid_y; y_pos = (int) ((y_max - y_value)*y_scale_orig); g.drawLine(0,y_pos-orig_scroll_y,m_width,y_pos-orig_scroll_y); if(label_grid && orig_grid_y_spacing > 20) { if(x_offset_orig - orig_scroll_x < 0) { x_pos = 0; } else if(x_offset_orig - orig_scroll_x > m_width) { x_pos = m_width-25; } else { x_pos = x_offset_orig - orig_scroll_x; } if(y_value > (orig_grid_y*0.5) || y_value < (-0.5*orig_grid_y)) { g.drawString(format_double(y_value),x_pos+5,y_pos-orig_scroll_y-5); } } } } catch(Exception e) { e.printStackTrace(); } } Image bufferImage = null; boolean image_needs_to_be_updated =true; public void paint(Graphics g) { if(debug_on) { System.out.println("PlotGraph.paint() called. paint_count = "+paint_count); } if(dplotter.loading_url) { return; } if(null != back_color) { setBackground(back_color); } if(use_buffer) { if(null == bufferImage) { image_needs_to_be_updated = true; } if(image_needs_to_be_updated) { if(null == bufferImage) { // System.out.println("creating new buffer Image"); bufferImage = createImage(m_width, m_height); } Graphics image_g = bufferImage.getGraphics(); if(null == image_g) { // System.out.println("bufferImage.getGraphics = null"); paintGraph(g); paintDraggingRect(g); return; } // System.out.println("Painting image."); image_g.clearRect(0,0,m_width,m_height); paintGraph(image_g); image_needs_to_be_updated = false; } if(null != bufferImage) { g.drawImage(bufferImage, 0,0, m_width, m_height,null); } } else { paintGraph(g); } paintDraggingRect(g); } public void paintDraggingRect(Graphics g) { try { // System.out.println("paintDraggingRect() called. show_rect="+show_rect); if(show_rect) { if(m_color && axis_color != null) { g.setColor(axis_color); } g.drawRect(selected_rectangle.x,selected_rectangle.y,selected_rectangle.width, selected_rectangle.height); } } catch(Exception e) { e.printStackTrace(); } } public void paintGraph(Graphics g) { try { //System.out.println("paintGraph called.\n"); repaint_just_issued = false; repaint_needed = false; paint_count++; if(m_scroll_x < 0) { m_scroll_x = 0; } if(m_scroll_x > max_scroll_x) { m_scroll_x = max_scroll_x; } if(m_scroll_y < 0) { m_scroll_y = 0; } if(m_scroll_y > max_scroll_y) { m_scroll_y = max_scroll_y; } int orig_scroll_x = m_scroll_x; int orig_scroll_y = m_scroll_y; int x_offset_orig = x_offset; int y_offset_orig = y_offset; double x_scale_orig = x_scale; double y_scale_orig = y_scale; if(dplotter_num > 0 && debug_on) { System.out.println("Repainting PlotGraph dplotter_num = "+dplotter_num); } if(m_color) { g.setColor(Color.white); } else { g.setColor(Color.black); } if(show_grid) { paintGrid(g); } if(show_axis) { if(m_color && axis_color != null) { g.setColor(axis_color); } g.drawLine(x_offset_orig - orig_scroll_x,0,x_offset_orig - orig_scroll_x,m_height); g.drawLine(0,y_offset_orig - orig_scroll_y,m_width,y_offset_orig - orig_scroll_y); } if(label_grid && coordinate_type == CARTESIAN_COORD_TYPE) { g.drawString("(0,0)",x_offset_orig - orig_scroll_x+5,y_offset_orig - orig_scroll_y-5); } if(show_key) { paintKey(g); } if(plots != null) { if(dplotter_num > 0 && debug_on) { System.out.println("Repainting PlotGraph plots = "+plots); } Enumeration plots_enumeration = plots.elements(); while(plots_enumeration.hasMoreElements()) { PlotData plot_data = (PlotData) plots_enumeration.nextElement(); if(dplotter_num > 0 && debug_on) { System.out.println("Repainting PlotGraph plot_data = "+plot_data); System.out.println("Repainting PlotGraph plot_data.show = "+plot_data.show); } if(null != plot_data.show && dplotter_num >= 0 ) { if(plot_data.show.length >= dplotter_num) { if(!plot_data.show[dplotter_num]) { continue; } } } if(plot_data.line_width > 0) { line_width = plot_data.line_width; } line_style = plot_data.line_style; PlotPoint last_point = null; int j = 0; if(dplotter_num > 0 && debug_on) { System.out.println("Repainting PlotGraph orig_scroll_x = "+orig_scroll_x); System.out.println("Repainting PlotGraph orig_scroll_y = "+orig_scroll_y); System.out.println("Repainting PlotGraph m_width = "+m_width); System.out.println("Repainting PlotGraph m_height = "+m_height); } for( j = 0; j < plot_data.v.size(); j++) { PlotPoint current_point = (PlotPoint) plot_data.v.elementAt(j); current_point.x = (int) ((current_point.orig_x - x_min)*x_scale); current_point.y = (int) ((y_max - current_point.orig_y)*y_scale); if(dplotter_num > 0 && debug_on) { System.out.println("Repainting PlotGraph current_point.x = "+current_point.x); System.out.println("Repainting PlotGraph current_point.y = "+current_point.y); } if(m_color) { g.setColor(plot_data.line_color); } if(null != last_point && current_point.connected && show_lines) { if(last_point.x < orig_scroll_x && current_point.x < orig_scroll_x) { last_point = current_point; continue; } if(last_point.x - orig_scroll_x >m_width && current_point.x - orig_scroll_x >m_width) { last_point = current_point; continue; } if(last_point.y < orig_scroll_y && current_point.y < orig_scroll_y) { last_point = current_point; continue; } if(last_point.y - orig_scroll_y >m_height && current_point.y - orig_scroll_y >m_height) { last_point = current_point; continue; } EnhancedDrawLine(g,last_point.x- orig_scroll_x,last_point.y- orig_scroll_y,current_point.x- orig_scroll_x,current_point.y- orig_scroll_y); } else { if( current_point.x < orig_scroll_x) { last_point = current_point; continue; } if( current_point.x - orig_scroll_x >m_width) { last_point = current_point; continue; } if( current_point.y < orig_scroll_y) { last_point = current_point; continue; } if( current_point.y - orig_scroll_y >m_height) { last_point = current_point; continue; } } if(plot_data.mark_points) { if(m_color) { g.setColor(plot_data.point_color); } g.fillRect(current_point.x- orig_scroll_x-2,current_point.y- orig_scroll_y-2,4,4); } if(label_points) { if(null != last_point) { if(Math.abs(current_point.x - last_point.x) < 30 && Math.abs(current_point.y - last_point.y) < 10) { last_point = current_point; continue; } if(label_string != null) { if(null == font) { font = g.getFont(); fm = Toolkit.getDefaultToolkit().getFontMetrics(font); } if(null != fm) { if(Math.abs(current_point.x - last_point.x) < fm.stringWidth(label_string) && Math.abs(current_point.y - last_point.y) < fm.getHeight()) { last_point = current_point; continue; } } } } label_string = "("+current_point.orig_x+","+current_point.orig_y+")"; g.drawString(label_string,current_point.x- orig_scroll_x+5,current_point.y- orig_scroll_y-5); } last_point = current_point; } } } } catch(Exception e) { e.printStackTrace(); } } }