diff --git a/.idea/compiler.xml b/.idea/compiler.xml index f65d2590..ae46cc1f 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -6,16 +6,20 @@ - - + + + + + + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index dea81a50..aef94361 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -11,8 +11,12 @@ + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml index 17b8190b..4766f0f0 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -6,7 +6,9 @@ + + diff --git a/MeteoInfoLab/MeteoInfoLab.iml b/MeteoInfoLab/MeteoInfoLab.iml index 53ab16e2..42681240 100644 --- a/MeteoInfoLab/MeteoInfoLab.iml +++ b/MeteoInfoLab/MeteoInfoLab.iml @@ -22,6 +22,15 @@ + + + + + + + + + diff --git a/MeteoInfoLab/milconfig.xml b/MeteoInfoLab/milconfig.xml index f5aa03fb..02eae897 100644 --- a/MeteoInfoLab/milconfig.xml +++ b/MeteoInfoLab/milconfig.xml @@ -1,29 +1,32 @@ - - - + - - + + + + + - + + - + + diff --git a/MeteoInfoLab/pylib/mipylib/dataset/__init__$py.class b/MeteoInfoLab/pylib/mipylib/dataset/__init__$py.class index 1f33134b..8781f64f 100644 Binary files a/MeteoInfoLab/pylib/mipylib/dataset/__init__$py.class and b/MeteoInfoLab/pylib/mipylib/dataset/__init__$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/dataset/__init__.py b/MeteoInfoLab/pylib/mipylib/dataset/__init__.py index 54fe417b..a2a4017a 100644 --- a/MeteoInfoLab/pylib/mipylib/dataset/__init__.py +++ b/MeteoInfoLab/pylib/mipylib/dataset/__init__.py @@ -1,5 +1,6 @@ import midata from .midata import * +import ncutil from .dimvariable import DimVariable __all__ = ['ncutil', 'DimVariable'] diff --git a/MeteoInfoLab/pylib/mipylib/dataset/dimvariable$py.class b/MeteoInfoLab/pylib/mipylib/dataset/dimvariable$py.class index c31bd0e2..9b7dc6ce 100644 Binary files a/MeteoInfoLab/pylib/mipylib/dataset/dimvariable$py.class and b/MeteoInfoLab/pylib/mipylib/dataset/dimvariable$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/dataset/dimvariable.py b/MeteoInfoLab/pylib/mipylib/dataset/dimvariable.py index 3edf7899..a9b91e37 100644 --- a/MeteoInfoLab/pylib/mipylib/dataset/dimvariable.py +++ b/MeteoInfoLab/pylib/mipylib/dataset/dimvariable.py @@ -6,7 +6,7 @@ #----------------------------------------------------- from org.meteoinfo.ndarray import Dimension, DimensionType, Range, Array, MAMath from org.meteoinfo.math import ArrayMath, ArrayUtil -from org.meteoinfo.global import PointD +from org.meteoinfo.common import PointD from org.meteoinfo.projection import KnownCoordinateSystems, Reproject from org.meteoinfo.data.meteodata import Attribute from ucar.nc2 import Attribute as NCAttribute diff --git a/MeteoInfoLab/pylib/mipylib/geolib/geoutil$py.class b/MeteoInfoLab/pylib/mipylib/geolib/geoutil$py.class index 464b15c5..f2f74e84 100644 Binary files a/MeteoInfoLab/pylib/mipylib/geolib/geoutil$py.class and b/MeteoInfoLab/pylib/mipylib/geolib/geoutil$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/geolib/geoutil.py b/MeteoInfoLab/pylib/mipylib/geolib/geoutil.py index e6f4823a..69676af8 100644 --- a/MeteoInfoLab/pylib/mipylib/geolib/geoutil.py +++ b/MeteoInfoLab/pylib/mipylib/geolib/geoutil.py @@ -1,58 +1,58 @@ -#----------------------------------------------------- -# Author: Yaqiang Wang -# Date: 2017-11-28 -# Purpose: MeteoInfo geoutil module -# Note: Jython -#----------------------------------------------------- - -from org.meteoinfo.shape import ShapeUtil, PointShape -from org.meteoinfo.global import PointD -import mipylib.numeric as np - -__all__ = [ - 'makeshapes' - ] - -def makeshapes(x, y, type=None, z=None, m=None): - """ - Make shapes by x and y coordinates. - - :param x: (*array_like*) X coordinates. - :param y: (*array_like*) Y coordinates. - :param type: (*string*) Shape type [point | line | polygon]. - :param z: (*array_like*) Z coordinates. - :param m: (*array_like*) M coordinates. - - :returns: Shapes - """ - shapes = [] - if isinstance(x, (int, float)): - shape = PointShape() - shape.setPoint(PointD(x, y)) - shapes.append(shape) - else: - x = np.asarray(x)._array - y = np.asarray(y)._array - if not z is None: - if m is None: - m = np.zeros(len(z))._array - else: - m = np.asarray(m)._array - z = np.asarray(z)._array - if type == 'point': - if z is None: - shapes = ShapeUtil.createPointShapes(x, y) - else: - shapes = ShapeUtil.createPointShapes(x, y, z, m) - elif type == 'line': - if z is None: - shapes = ShapeUtil.createPolylineShapes(x, y) - else: - shapes = ShapeUtil.createPolylineShapes(x, y, z, m) - elif type == 'polygon': - if z is None: - shapes = ShapeUtil.createPolygonShapes(x, y) - else: - shapes = ShapeUtil.createPolygonShape(x, y, z, m) - return shapes +#----------------------------------------------------- +# Author: Yaqiang Wang +# Date: 2017-11-28 +# Purpose: MeteoInfo geoutil module +# Note: Jython +#----------------------------------------------------- + +from org.meteoinfo.shape import ShapeUtil, PointShape +from org.meteoinfo.common import PointD +import mipylib.numeric as np + +__all__ = [ + 'makeshapes' + ] + +def makeshapes(x, y, type=None, z=None, m=None): + """ + Make shapes by x and y coordinates. + + :param x: (*array_like*) X coordinates. + :param y: (*array_like*) Y coordinates. + :param type: (*string*) Shape type [point | line | polygon]. + :param z: (*array_like*) Z coordinates. + :param m: (*array_like*) M coordinates. + + :returns: Shapes + """ + shapes = [] + if isinstance(x, (int, float)): + shape = PointShape() + shape.setPoint(PointD(x, y)) + shapes.append(shape) + else: + x = np.asarray(x)._array + y = np.asarray(y)._array + if not z is None: + if m is None: + m = np.zeros(len(z))._array + else: + m = np.asarray(m)._array + z = np.asarray(z)._array + if type == 'point': + if z is None: + shapes = ShapeUtil.createPointShapes(x, y) + else: + shapes = ShapeUtil.createPointShapes(x, y, z, m) + elif type == 'line': + if z is None: + shapes = ShapeUtil.createPolylineShapes(x, y) + else: + shapes = ShapeUtil.createPolylineShapes(x, y, z, m) + elif type == 'polygon': + if z is None: + shapes = ShapeUtil.createPolygonShapes(x, y) + else: + shapes = ShapeUtil.createPolygonShape(x, y, z, m) + return shapes \ No newline at end of file diff --git a/MeteoInfoLab/pylib/mipylib/geolib/migeo$py.class b/MeteoInfoLab/pylib/mipylib/geolib/migeo$py.class index 51b06d24..719e584e 100644 Binary files a/MeteoInfoLab/pylib/mipylib/geolib/migeo$py.class and b/MeteoInfoLab/pylib/mipylib/geolib/migeo$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/geolib/migeo.py b/MeteoInfoLab/pylib/mipylib/geolib/migeo.py index a25ebd2a..55aa55da 100644 --- a/MeteoInfoLab/pylib/mipylib/geolib/migeo.py +++ b/MeteoInfoLab/pylib/mipylib/geolib/migeo.py @@ -16,8 +16,8 @@ from org.meteoinfo.math import ArrayMath, ArrayUtil from org.meteoinfo.data.mapdata import MapDataManage, AttributeTable from org.meteoinfo.projection import KnownCoordinateSystems, Reproject from org.meteoinfo.projection.info import ProjectionInfo -from org.meteoinfo.global import PointD -from org.meteoinfo.io import IOUtil +from org.meteoinfo.common import PointD +from org.meteoinfo.common.io import IOUtil from org.meteoinfo.geoprocess.analysis import ResampleMethods from milayer import MILayer diff --git a/MeteoInfoLab/pylib/mipylib/miutil$py.class b/MeteoInfoLab/pylib/mipylib/miutil$py.class index a9bc19c3..c15c33cf 100644 Binary files a/MeteoInfoLab/pylib/mipylib/miutil$py.class and b/MeteoInfoLab/pylib/mipylib/miutil$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/miutil.py b/MeteoInfoLab/pylib/mipylib/miutil.py index 569eed3c..75187f65 100644 --- a/MeteoInfoLab/pylib/mipylib/miutil.py +++ b/MeteoInfoLab/pylib/mipylib/miutil.py @@ -5,8 +5,8 @@ # Note: Jython #----------------------------------------------------- -from org.meteoinfo.global import PointD -from org.meteoinfo.global.util import JDateUtil +from org.meteoinfo.common import PointD +from org.meteoinfo.common.util import JDateUtil from org.meteoinfo.ndarray import Complex from org.meteoinfo.shape import PointShape, ShapeUtil from java.util import Locale diff --git a/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray$py.class b/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray$py.class index 8fa9be8c..2a3ab362 100644 Binary files a/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray$py.class and b/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray.py b/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray.py index d3b62a20..78fb7c55 100644 --- a/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray.py +++ b/MeteoInfoLab/pylib/mipylib/numeric/core/dimarray.py @@ -9,7 +9,7 @@ from org.meteoinfo.data import GridData, GridArray from org.meteoinfo.math import ArrayMath, ArrayUtil from org.meteoinfo.geoprocess import GeometryUtil from org.meteoinfo.geoprocess.analysis import ResampleMethods -from org.meteoinfo.global import PointD +from org.meteoinfo.common import PointD from org.meteoinfo.ndarray import Array, Range, MAMath, DataType, Dimension, DimensionType from multiarray import NDArray import math diff --git a/MeteoInfoLab/pylib/mipylib/plotlib/_axes$py.class b/MeteoInfoLab/pylib/mipylib/plotlib/_axes$py.class index c4944625..9ff0b5ae 100644 Binary files a/MeteoInfoLab/pylib/mipylib/plotlib/_axes$py.class and b/MeteoInfoLab/pylib/mipylib/plotlib/_axes$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/plotlib/_axes.py b/MeteoInfoLab/pylib/mipylib/plotlib/_axes.py index e5349018..aaeac407 100644 --- a/MeteoInfoLab/pylib/mipylib/plotlib/_axes.py +++ b/MeteoInfoLab/pylib/mipylib/plotlib/_axes.py @@ -14,7 +14,7 @@ from org.meteoinfo.chart.axis import Axis, LonLatAxis, TimeAxis, LogAxis from org.meteoinfo.legend import LegendManage, BarBreak, PolygonBreak, PolylineBreak, \ PointBreak, LineStyles, PointStyle, LegendScheme, LegendType from org.meteoinfo.shape import ShapeTypes, Graphic, GraphicCollection -from org.meteoinfo.global import MIMath, Extent +from org.meteoinfo.common import MIMath, Extent from org.meteoinfo.layer import MapLayer from java.awt import Font, Color, BasicStroke diff --git a/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes$py.class b/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes$py.class index 4fe95a53..7d3bddc9 100644 Binary files a/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes$py.class and b/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes$py.class differ diff --git a/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes.py b/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes.py index 232d4f46..6404ed7c 100644 --- a/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes.py +++ b/MeteoInfoLab/pylib/mipylib/plotlib/_mapaxes.py @@ -16,7 +16,7 @@ from org.meteoinfo.map import MapView from org.meteoinfo.legend import BreakTypes, LegendManage, LegendScheme, LegendType from org.meteoinfo.shape import Shape, PolylineShape, PolygonShape, ShapeTypes, Graphic from org.meteoinfo.projection.info import ProjectionInfo -from org.meteoinfo.global import Extent +from org.meteoinfo.common import Extent from org.meteoinfo.layer import LayerTypes, WebMapLayer from org.meteoinfo.data.mapdata.webmap import WebMapProvider from org.meteoinfo.layout import ScaleBarType diff --git a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/MeteoInfoLab.java b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/MeteoInfoLab.java index 48fef15b..9cbdd277 100644 --- a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/MeteoInfoLab.java +++ b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/MeteoInfoLab.java @@ -21,9 +21,9 @@ import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarkLaf; import com.formdev.flatlaf.FlatIntelliJLaf; import com.formdev.flatlaf.FlatLightLaf; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.global.DataConvert; import org.meteoinfo.global.util.FontUtil; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.laboratory.gui.FrmMain; import org.meteoinfo.console.jython.MyPythonInterpreter; import org.python.core.Py; diff --git a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/EditorDockable.java b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/EditorDockable.java index af05bf61..9c1c7035 100644 --- a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/EditorDockable.java +++ b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/EditorDockable.java @@ -1,733 +1,733 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.laboratory.gui; - -import bibliothek.gui.dock.common.DefaultSingleCDockable; -import bibliothek.gui.dock.common.action.CAction; -import java.awt.AWTException; -import java.awt.Component; -import java.awt.Font; -import java.awt.Robot; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JPopupMenu.Separator; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.SwingWorker; -import javax.swing.event.ChangeEvent; -import javax.swing.text.BadLocationException; - -import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; -import org.fife.ui.rsyntaxtextarea.TextEditorPane; -import org.fife.ui.rsyntaxtextarea.Theme; -import org.meteoinfo.console.editor.JTextAreaPrintStream; -import org.meteoinfo.console.editor.JTextAreaWriter; -import org.meteoinfo.console.editor.MITextEditorPane; -import org.meteoinfo.console.editor.TextEditor; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.console.jython.JIntrospect; -import org.meteoinfo.ui.ButtonTabComponent; -import org.python.util.PythonInterpreter; - -/** - * - * @author yaqiang - */ -public class EditorDockable extends DefaultSingleCDockable { - - private final FrmMain parent; - //private String startupPath; - private final JTabbedPane tabbedPanel; - private Font textFont; - private PythonInterpreter interp; - private Theme theme; - - public EditorDockable(FrmMain parent, String id, String title, CAction... actions) { - super(id, title, actions); - - this.parent = parent; - this.setTitleIcon(new FlatSVGIcon("org/meteoinfo/laboratory/icons/editor.svg")); - String lfName = this.parent.getOptions().getLookFeel(); - String themeName = "default"; - switch (lfName) { - case "FlatDarculaLaf": - case "FlatDarkLaf": - themeName = "dark"; - break; - } - try { - theme = Theme.load(getClass().getResourceAsStream( - "/org/fife/ui/rsyntaxtextarea/themes/" + themeName + ".xml")); - } catch (IOException ioe) { // Never happens - ioe.printStackTrace(); - } - tabbedPanel = new JTabbedPane(); - tabbedPanel.addChangeListener((ChangeEvent e) -> { - JTabbedPane sourceTabbedPane = (JTabbedPane) e.getSource(); - TextEditor te = (TextEditor) sourceTabbedPane.getSelectedComponent(); - if (te != null) { - EditorDockable.this.setTitleText("Editor - " + te.getFileName()); - } - }); - this.getContentPane().add(tabbedPanel); - //this.setCloseable(false); - } - -// /** -// * Set startup path -// * -// * @param path Startup path -// */ -// public void setStartupPath(String path) { -// this.startupPath = path; -// } - /** - * Get tabbed pane - * - * @return Tabbed pane - */ - public JTabbedPane getTabbedPane() { - return this.tabbedPanel; - } - - /** - * Get font - * - * @return Font - */ - public Font getTextFont() { - return this.textFont; - } - - /** - * Set font - * - * @param font Font - */ - public void setTextFont(Font font) { - this.textFont = font; - for (Component tab : this.tabbedPanel.getComponents()) { - if (tab instanceof TextEditor) { - ((TextEditor) tab).setTextFont(this.textFont); - } - } - } - - /** - * Set python interpreter - * - * @param value Python interpreter - */ - public void setInterp(PythonInterpreter value) { - this.interp = value; - } - - /** - * Add a new text editor - * - * @param title Title - * @return Text editor - */ - public final TextEditor addNewTextEditor(String title) { - final TextEditor tab = new TextEditor(tabbedPanel, title); - tabbedPanel.add(tab, title); - tabbedPanel.setSelectedComponent(tab); - final MITextEditorPane textArea = (MITextEditorPane) tab.getTextArea(); - textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON); - textArea.discardAllEdits(); - this.theme.apply(textArea); - tab.setTextFont(this.textFont); - - //Evaluate menu - JPopupMenu popup = textArea.getPopupMenu(); - JMenuItem evaluate = new JMenuItem("Evaluate Selection"); - evaluate.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - runCodeLines(textArea); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (BadLocationException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - }); - popup.insert(evaluate, 0); - popup.insert(new Separator(), 1); - - //Comment menu - JMenuItem comment = new JMenuItem("Comment or Uncomment"); - comment.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - comment(textArea); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (BadLocationException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - }); - popup.insert(comment, 2); - - //Insert Tab menu - JMenuItem insertTab = new JMenuItem("Insert Tab"); - insertTab.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - insertTab(textArea); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (AWTException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - }); - popup.insert(insertTab, 3); - - //Delete Tab menu - JMenuItem delTab = new JMenuItem("Delete Tab"); - delTab.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - try { - delTab(textArea); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (BadLocationException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - }); - popup.insert(delTab, 4); - - tab.getTextArea().setDirty(false); - tab.setTitle(title); - - //Set name completion - JIntrospect nameComplete = new JIntrospect(this.interp); - textArea.setNameCompletion(nameComplete); - -// //Set language support - code auto completion -// JythonLanguageSupport ac = new JythonLanguageSupport(); -// ac.install(textArea); -// JythonCompletionProvider cp = ac.getProvider(); -// if (this.interp != null) -// ((JythonSourceCompletionProvider)cp.getDefaultCompletionProvider()).setInterp(interp); - ButtonTabComponent btc = new ButtonTabComponent(tabbedPanel); - JButton button = btc.getTabButton(); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - closeFile(tab); - } - }); - tabbedPanel.setTabComponentAt(tabbedPanel.indexOfComponent(tab), btc); - - return tab; - } - - /** - * Get active text editor - * - * @return Active text editor - */ - public TextEditor getActiveTextEditor() { - if (this.tabbedPanel.getTabCount() == 0) { - return null; - } else { - return (TextEditor) this.tabbedPanel.getSelectedComponent(); - } - } - - /** - * Get all text editors - * - * @return All text editors - */ - public List getAllTextEditor() { - List tes = new ArrayList<>(); - Component comp; - for (int i = 0; i < this.tabbedPanel.getComponentCount(); i++) { - comp = this.tabbedPanel.getComponent(i); - if (comp instanceof TextEditor) - tes.add((TextEditor) comp); - } - - return tes; - } - - /** - * Set active text editor - * - * @param te Text editor - */ - public void setActiveTextEditor(TextEditor te) { - this.tabbedPanel.setSelectedComponent(te); - this.setTitleText("Editor - " + te.getFileName()); - } - - private TextEditorPane getActiveTextArea() { - TextEditor textEditor = getActiveTextEditor(); - if (textEditor != null) { - return textEditor.getTextArea(); - } else { - return null; - } - } - - /** - * Close file - */ - public void closeFile() { - closeFile(this.getActiveTextEditor()); - } - - private void closeFile(TextEditor textEditor) { - //TextEditor textEditor = getActiveTextEditor(); - if (textEditor != null) { - boolean ifClose = true; - if (textEditor.getTextArea().isDirty()) { - String fName = textEditor.getFileName(); - if (fName.isEmpty()) { - fName = "New file"; - } - int result = JOptionPane.showConfirmDialog(null, MessageFormat.format("Save changes to \"{0}\"", fName), "Save?", JOptionPane.YES_NO_CANCEL_OPTION); - if (result == JOptionPane.YES_OPTION) { - if (!doSave(textEditor)) { - ifClose = false; - } - } else if (result == JOptionPane.CANCEL_OPTION) { - ifClose = false; - } - } - - if (ifClose) { - removeTextEditor(textEditor); - } - } - } - - /** - * Close all files - */ - public void closeAllFiles() { - while (this.tabbedPanel.getTabCount() > 0) { - this.closeFile(); - } -// for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { -// this.closeFile((TextEditor) this.tabbedPanel.getComponentAt(0)); -// } - } - - /** - * Save file - * - * @param editor The text editor - * @return Boolean - */ - public boolean doSave(TextEditor editor) { - if (editor.getFileName().isEmpty()) { - return doSaveAs_Jython(editor); - } else { - editor.saveFile(editor.getFile()); - return true; - } - } - - /** - * Save as - * - * @param editor The text editor - * @return Boolean - */ - public boolean doSaveAs_Jython(TextEditor editor) { - JFileChooser aDlg = new JFileChooser(); - String[] fileExts = new String[]{"py"}; - GenericFileFilter mapFileFilter = new GenericFileFilter(fileExts, "Python File (*.py)"); - aDlg.setFileFilter(mapFileFilter); - if (editor.getFile() != null) { - aDlg.setSelectedFile(editor.getFile()); - } else { - File dir = new File(System.getProperty("user.dir")); - if (dir.isDirectory()) { - aDlg.setCurrentDirectory(dir); - } - } - if (aDlg.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) { - File file = aDlg.getSelectedFile(); - System.setProperty("user.dir", file.getParent()); - String extent = ((GenericFileFilter) aDlg.getFileFilter()).getFileExtent(); - String fileName = file.getAbsolutePath(); - if (!fileName.substring(fileName.length() - extent.length()).equals(extent)) { - fileName = fileName + "." + extent; - } - file = new File(fileName); - if (file.exists()) { - int overwrite = JOptionPane.showConfirmDialog(null, "File exists! Overwrite it?", "Confirm", JOptionPane.YES_NO_OPTION); - if (overwrite == JOptionPane.NO_OPTION) { - return false; - } - } - editor.saveFile(file); - this.setTitleText(editor.getFileName()); - return true; - } - return false; - } - - private void removeTextEditor(TextEditor editor) { - this.tabbedPanel.remove(editor); - } - - /** - * Open Jython script file - */ - public void doOpen_Jython() { - // TODO add your handling code here: - JFileChooser aDlg = new JFileChooser(); - aDlg.setMultiSelectionEnabled(true); - aDlg.setAcceptAllFileFilterUsed(false); - //File dir = new File(this._parent.getCurrentDataFolder()); - File dir = new File(System.getProperty("user.dir")); - if (dir.isDirectory()) { - aDlg.setCurrentDirectory(dir); - } - String[] fileExts = new String[]{"py"}; - GenericFileFilter mapFileFilter = new GenericFileFilter(fileExts, "Jython File (*.py)"); - aDlg.setFileFilter(mapFileFilter); - if (JFileChooser.APPROVE_OPTION == aDlg.showOpenDialog(parent)) { - File[] files = aDlg.getSelectedFiles(); - //this._parent.setCurrentDataFolder(files[0].getParent()); - System.setProperty("user.dir", files[0].getParent()); - this.openFiles(files); - } - } - - /** - * Open files - * - * @param fileNames File name list - */ - public void openFiles(List fileNames) { - List files = new ArrayList<>(); - for (String fn : fileNames) { - File file = new File(fn); - if (file.exists()) { - files.add(file); - } - } - - if (files.size() > 0) { - File[] fs = new File[files.size()]; - for (int i = 0; i < files.size(); i++) { - fs[i] = files.get(i); - } - this.openFiles(fs); - } - } - - /** - * Open script files - * - * @param files The files - */ - public void openFiles(File[] files) { - // Close default untitled document if it is still empty - if (this.tabbedPanel.getTabCount() == 1) { - TextEditor textEditor = getActiveTextEditor(); - if (textEditor.getTextArea().getDocument().getLength() == 0 && textEditor.getFileName().isEmpty()) { - this.removeTextEditor(textEditor); - } - } - - // Open file(s) - for (File file : files) { - boolean isExist = false; - for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { - TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); - if (file.getAbsolutePath().equals(te.getFileName())) { - isExist = true; - this.setActiveTextEditor(te); - break; - } - } - if (isExist) { - continue; - } - TextEditor editor = addNewTextEditor(file.getName()); - editor.openFile(file); - this.setTitleText(editor.getFileName()); - } - } - - /** - * Open script file - * - * @param file The file - */ - public void openFile(File file) { - // Close default untitled document if it is still empty - if (this.tabbedPanel.getTabCount() == 1) { - TextEditor textEditor = getActiveTextEditor(); - if (textEditor.getTextArea().getDocument().getLength() == 0 && textEditor.getFileName().isEmpty()) { - this.removeTextEditor(textEditor); - } - } - - // Open file - boolean isExist = false; - for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { - TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); - if (file.getAbsolutePath().equals(te.getFileName())) { - isExist = true; - this.setActiveTextEditor(te); - break; - } - } - if (!isExist) { - TextEditor editor = addNewTextEditor(file.getName()); - editor.openFile(file); - this.parent.getOptions().addRecentFile(file.getAbsolutePath()); - this.setTitleText(editor.getFileName()); - } - } - - /** - * Get opened file names - * - * @return Opened file names - */ - public List getOpenedFiles() { - List fns = new ArrayList<>(); - for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { - TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); - fns.add(te.getFileName()); - } - - return fns; - } - - private void runCodeLines(MITextEditorPane textArea) throws InterruptedException, BadLocationException { - int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); - int sIdx = textArea.getLineStartOffset(sLine); - int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); - int eIdx = textArea.getLineEndOffset(eLine); - textArea.setSelectionStart(sIdx); - textArea.setSelectionEnd(eIdx); - String code = textArea.getSelectedText(); - - this.parent.getConsoleDockable().run(code); - } - - /** - * Toggle comment to the selected lines - */ - public void Comment() { - try { - comment((MITextEditorPane)this.getActiveTextArea()); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (BadLocationException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - private void comment(MITextEditorPane textArea) throws InterruptedException, BadLocationException { - int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); - int sIdx = textArea.getLineStartOffset(sLine); - int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); - int eIdx = textArea.getLineEndOffset(eLine); - textArea.setSelectionStart(sIdx); - textArea.setSelectionEnd(eIdx); - String text = textArea.getSelectedText(); - - String[] lines = text.split("\n"); - StringBuilder sb = new StringBuilder(); - for (String line : lines) { - String nLine = line.trim(); - if (nLine.startsWith("#")) { - sb.append(line.replaceFirst("#", "")); - } else { - sb.append("#" + line); - } - - sb.append("\n"); - } - text = sb.toString(); - textArea.replaceSelection(text); - } - - /** - * Delete first 4 spaces to the seleted lines - */ - public void delTab() { - try { - delTab((MITextEditorPane)this.getActiveTextArea()); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (BadLocationException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - private void delTab(MITextEditorPane textArea) throws InterruptedException, BadLocationException { - int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); - int sIdx = textArea.getLineStartOffset(sLine); - int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); - int eIdx = textArea.getLineEndOffset(eLine); - textArea.setSelectionStart(sIdx); - textArea.setSelectionEnd(eIdx); - String text = textArea.getSelectedText(); - - String[] lines = text.split("\n"); - StringBuilder sb = new StringBuilder(); - for (String line : lines) { - if (line.startsWith(" ")) - sb.append(line.substring(4)); - else if (line.startsWith(" ")) - sb.append(line.substring(3)); - else if (line.startsWith(" ")) - sb.append(line.substring(2)); - else if (line.startsWith(" ")) - sb.append(line.substring(1)); - else - sb.append(line); - - sb.append("\n"); - } - text = sb.toString(); - textArea.replaceSelection(text); - } - - /** - * Insert first 4 spaces to the seleted lines - */ - public void insertTab() { - try { - insertTab((MITextEditorPane)this.getActiveTextArea()); - } catch (InterruptedException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } catch (AWTException ex) { - Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - private void insertTab(MITextEditorPane textArea) throws InterruptedException, AWTException { - Robot robot = new Robot(); - robot.keyPress(KeyEvent.VK_TAB); - } - - /** - * Run Jython script - * - * @param jTextArea_Output - */ - public void runPythonScript(final JTextArea jTextArea_Output) { - - SwingWorker worker = new SwingWorker() { - PrintStream oout = System.out; - PrintStream oerr = System.err; - - @Override - protected String doInBackground() throws Exception { - JTextAreaWriter writer = new JTextAreaWriter(jTextArea_Output); - JTextAreaPrintStream printStream = new JTextAreaPrintStream(System.out, jTextArea_Output); - jTextArea_Output.setText(""); - - // Create an instance of the PythonInterpreter - //Py.getSystemState().setdefaultencoding("utf-8"); - //UPythonInterpreter interp = new UPythonInterpreter(); - PythonInterpreter interp = new PythonInterpreter(); - interp.setOut(writer); - interp.setErr(writer); - System.setOut(printStream); - System.setErr(printStream); - //System.out.println("Out test!"); - //System.err.println("Error test!"); - -// boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean(). -// getInputArguments().toString().contains("jdwp"); - //String pluginPath = startupPath + File.separator + "plugins"; - //List jarfns = GlobalUtil.getFiles(pluginPath, ".jar"); - //String path = startupPath + File.separator + "pylib"; -// if (isDebug) { -// path = "D:/MyProgram/Distribution/Java/MeteoInfo/MeteoInfo/pylib"; -// } - try { - interp.exec("import sys"); - interp.set("milapp", EditorDockable.this.parent); - //interp.exec("sys.path.append('" + path + "')"); - //interp.exec("import mipylib"); - //interp.exec("from mipylib.miscript import *"); - //interp.exec("from meteoinfo.numeric.JNumeric import *"); - //interp.exec("mis = MeteoInfoScript()"); - //interp.set("miapp", _parent); - //for (String jarfn : jarfns) { - // interp.exec("sys.path.append('" + jarfn + "')"); - //} - } catch (Exception e) { - e.printStackTrace(); - } - - TextEditorPane textArea = getActiveTextArea(); - //textArea.setEncoding(fn); - String code = textArea.getText(); -// if (code.contains("coding=utf-8")){ -// code = code.replace("coding=utf-8", "coding = utf-8"); -// } - String encoding = EncodingUtil.findEncoding(code); - if (encoding != null) { - try { - interp.execfile(new ByteArrayInputStream(code.getBytes(encoding))); - } catch (Exception e) { - e.printStackTrace(); - } - } else { - try { - interp.execfile(new ByteArrayInputStream(code.getBytes())); - } catch (Exception e) { - e.printStackTrace(); - } - } -// try { -// //interp.exec(code); -// interp.execfile(new ByteArrayInputStream(code.getBytes())); -// } catch (Exception e) { -// e.printStackTrace(); -// } - - return ""; - } - - @Override - protected void done() { - System.setOut(oout); - System.setErr(oerr); - } - }; - worker.execute(); - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.laboratory.gui; + +import bibliothek.gui.dock.common.DefaultSingleCDockable; +import bibliothek.gui.dock.common.action.CAction; +import java.awt.AWTException; +import java.awt.Component; +import java.awt.Font; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JPopupMenu.Separator; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.text.BadLocationException; + +import com.formdev.flatlaf.extras.FlatSVGIcon; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rsyntaxtextarea.TextEditorPane; +import org.fife.ui.rsyntaxtextarea.Theme; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.console.editor.JTextAreaPrintStream; +import org.meteoinfo.console.editor.JTextAreaWriter; +import org.meteoinfo.console.editor.MITextEditorPane; +import org.meteoinfo.console.editor.TextEditor; +import org.meteoinfo.console.jython.JIntrospect; +import org.meteoinfo.ui.ButtonTabComponent; +import org.python.util.PythonInterpreter; + +/** + * + * @author yaqiang + */ +public class EditorDockable extends DefaultSingleCDockable { + + private final FrmMain parent; + //private String startupPath; + private final JTabbedPane tabbedPanel; + private Font textFont; + private PythonInterpreter interp; + private Theme theme; + + public EditorDockable(FrmMain parent, String id, String title, CAction... actions) { + super(id, title, actions); + + this.parent = parent; + this.setTitleIcon(new FlatSVGIcon("org/meteoinfo/laboratory/icons/editor.svg")); + String lfName = this.parent.getOptions().getLookFeel(); + String themeName = "default"; + switch (lfName) { + case "FlatDarculaLaf": + case "FlatDarkLaf": + themeName = "dark"; + break; + } + try { + theme = Theme.load(getClass().getResourceAsStream( + "/org/fife/ui/rsyntaxtextarea/themes/" + themeName + ".xml")); + } catch (IOException ioe) { // Never happens + ioe.printStackTrace(); + } + tabbedPanel = new JTabbedPane(); + tabbedPanel.addChangeListener((ChangeEvent e) -> { + JTabbedPane sourceTabbedPane = (JTabbedPane) e.getSource(); + TextEditor te = (TextEditor) sourceTabbedPane.getSelectedComponent(); + if (te != null) { + EditorDockable.this.setTitleText("Editor - " + te.getFileName()); + } + }); + this.getContentPane().add(tabbedPanel); + //this.setCloseable(false); + } + +// /** +// * Set startup path +// * +// * @param path Startup path +// */ +// public void setStartupPath(String path) { +// this.startupPath = path; +// } + /** + * Get tabbed pane + * + * @return Tabbed pane + */ + public JTabbedPane getTabbedPane() { + return this.tabbedPanel; + } + + /** + * Get font + * + * @return Font + */ + public Font getTextFont() { + return this.textFont; + } + + /** + * Set font + * + * @param font Font + */ + public void setTextFont(Font font) { + this.textFont = font; + for (Component tab : this.tabbedPanel.getComponents()) { + if (tab instanceof TextEditor) { + ((TextEditor) tab).setTextFont(this.textFont); + } + } + } + + /** + * Set python interpreter + * + * @param value Python interpreter + */ + public void setInterp(PythonInterpreter value) { + this.interp = value; + } + + /** + * Add a new text editor + * + * @param title Title + * @return Text editor + */ + public final TextEditor addNewTextEditor(String title) { + final TextEditor tab = new TextEditor(tabbedPanel, title); + tabbedPanel.add(tab, title); + tabbedPanel.setSelectedComponent(tab); + final MITextEditorPane textArea = (MITextEditorPane) tab.getTextArea(); + textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON); + textArea.discardAllEdits(); + this.theme.apply(textArea); + tab.setTextFont(this.textFont); + + //Evaluate menu + JPopupMenu popup = textArea.getPopupMenu(); + JMenuItem evaluate = new JMenuItem("Evaluate Selection"); + evaluate.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + runCodeLines(textArea); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (BadLocationException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + popup.insert(evaluate, 0); + popup.insert(new Separator(), 1); + + //Comment menu + JMenuItem comment = new JMenuItem("Comment or Uncomment"); + comment.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + comment(textArea); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (BadLocationException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + popup.insert(comment, 2); + + //Insert Tab menu + JMenuItem insertTab = new JMenuItem("Insert Tab"); + insertTab.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + insertTab(textArea); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (AWTException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + popup.insert(insertTab, 3); + + //Delete Tab menu + JMenuItem delTab = new JMenuItem("Delete Tab"); + delTab.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + delTab(textArea); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (BadLocationException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + popup.insert(delTab, 4); + + tab.getTextArea().setDirty(false); + tab.setTitle(title); + + //Set name completion + JIntrospect nameComplete = new JIntrospect(this.interp); + textArea.setNameCompletion(nameComplete); + +// //Set language support - code auto completion +// JythonLanguageSupport ac = new JythonLanguageSupport(); +// ac.install(textArea); +// JythonCompletionProvider cp = ac.getProvider(); +// if (this.interp != null) +// ((JythonSourceCompletionProvider)cp.getDefaultCompletionProvider()).setInterp(interp); + ButtonTabComponent btc = new ButtonTabComponent(tabbedPanel); + JButton button = btc.getTabButton(); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + closeFile(tab); + } + }); + tabbedPanel.setTabComponentAt(tabbedPanel.indexOfComponent(tab), btc); + + return tab; + } + + /** + * Get active text editor + * + * @return Active text editor + */ + public TextEditor getActiveTextEditor() { + if (this.tabbedPanel.getTabCount() == 0) { + return null; + } else { + return (TextEditor) this.tabbedPanel.getSelectedComponent(); + } + } + + /** + * Get all text editors + * + * @return All text editors + */ + public List getAllTextEditor() { + List tes = new ArrayList<>(); + Component comp; + for (int i = 0; i < this.tabbedPanel.getComponentCount(); i++) { + comp = this.tabbedPanel.getComponent(i); + if (comp instanceof TextEditor) + tes.add((TextEditor) comp); + } + + return tes; + } + + /** + * Set active text editor + * + * @param te Text editor + */ + public void setActiveTextEditor(TextEditor te) { + this.tabbedPanel.setSelectedComponent(te); + this.setTitleText("Editor - " + te.getFileName()); + } + + private TextEditorPane getActiveTextArea() { + TextEditor textEditor = getActiveTextEditor(); + if (textEditor != null) { + return textEditor.getTextArea(); + } else { + return null; + } + } + + /** + * Close file + */ + public void closeFile() { + closeFile(this.getActiveTextEditor()); + } + + private void closeFile(TextEditor textEditor) { + //TextEditor textEditor = getActiveTextEditor(); + if (textEditor != null) { + boolean ifClose = true; + if (textEditor.getTextArea().isDirty()) { + String fName = textEditor.getFileName(); + if (fName.isEmpty()) { + fName = "New file"; + } + int result = JOptionPane.showConfirmDialog(null, MessageFormat.format("Save changes to \"{0}\"", fName), "Save?", JOptionPane.YES_NO_CANCEL_OPTION); + if (result == JOptionPane.YES_OPTION) { + if (!doSave(textEditor)) { + ifClose = false; + } + } else if (result == JOptionPane.CANCEL_OPTION) { + ifClose = false; + } + } + + if (ifClose) { + removeTextEditor(textEditor); + } + } + } + + /** + * Close all files + */ + public void closeAllFiles() { + while (this.tabbedPanel.getTabCount() > 0) { + this.closeFile(); + } +// for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { +// this.closeFile((TextEditor) this.tabbedPanel.getComponentAt(0)); +// } + } + + /** + * Save file + * + * @param editor The text editor + * @return Boolean + */ + public boolean doSave(TextEditor editor) { + if (editor.getFileName().isEmpty()) { + return doSaveAs_Jython(editor); + } else { + editor.saveFile(editor.getFile()); + return true; + } + } + + /** + * Save as + * + * @param editor The text editor + * @return Boolean + */ + public boolean doSaveAs_Jython(TextEditor editor) { + JFileChooser aDlg = new JFileChooser(); + String[] fileExts = new String[]{"py"}; + GenericFileFilter mapFileFilter = new GenericFileFilter(fileExts, "Python File (*.py)"); + aDlg.setFileFilter(mapFileFilter); + if (editor.getFile() != null) { + aDlg.setSelectedFile(editor.getFile()); + } else { + File dir = new File(System.getProperty("user.dir")); + if (dir.isDirectory()) { + aDlg.setCurrentDirectory(dir); + } + } + if (aDlg.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) { + File file = aDlg.getSelectedFile(); + System.setProperty("user.dir", file.getParent()); + String extent = ((GenericFileFilter) aDlg.getFileFilter()).getFileExtent(); + String fileName = file.getAbsolutePath(); + if (!fileName.substring(fileName.length() - extent.length()).equals(extent)) { + fileName = fileName + "." + extent; + } + file = new File(fileName); + if (file.exists()) { + int overwrite = JOptionPane.showConfirmDialog(null, "File exists! Overwrite it?", "Confirm", JOptionPane.YES_NO_OPTION); + if (overwrite == JOptionPane.NO_OPTION) { + return false; + } + } + editor.saveFile(file); + this.setTitleText(editor.getFileName()); + return true; + } + return false; + } + + private void removeTextEditor(TextEditor editor) { + this.tabbedPanel.remove(editor); + } + + /** + * Open Jython script file + */ + public void doOpen_Jython() { + // TODO add your handling code here: + JFileChooser aDlg = new JFileChooser(); + aDlg.setMultiSelectionEnabled(true); + aDlg.setAcceptAllFileFilterUsed(false); + //File dir = new File(this._parent.getCurrentDataFolder()); + File dir = new File(System.getProperty("user.dir")); + if (dir.isDirectory()) { + aDlg.setCurrentDirectory(dir); + } + String[] fileExts = new String[]{"py"}; + GenericFileFilter mapFileFilter = new GenericFileFilter(fileExts, "Jython File (*.py)"); + aDlg.setFileFilter(mapFileFilter); + if (JFileChooser.APPROVE_OPTION == aDlg.showOpenDialog(parent)) { + File[] files = aDlg.getSelectedFiles(); + //this._parent.setCurrentDataFolder(files[0].getParent()); + System.setProperty("user.dir", files[0].getParent()); + this.openFiles(files); + } + } + + /** + * Open files + * + * @param fileNames File name list + */ + public void openFiles(List fileNames) { + List files = new ArrayList<>(); + for (String fn : fileNames) { + File file = new File(fn); + if (file.exists()) { + files.add(file); + } + } + + if (files.size() > 0) { + File[] fs = new File[files.size()]; + for (int i = 0; i < files.size(); i++) { + fs[i] = files.get(i); + } + this.openFiles(fs); + } + } + + /** + * Open script files + * + * @param files The files + */ + public void openFiles(File[] files) { + // Close default untitled document if it is still empty + if (this.tabbedPanel.getTabCount() == 1) { + TextEditor textEditor = getActiveTextEditor(); + if (textEditor.getTextArea().getDocument().getLength() == 0 && textEditor.getFileName().isEmpty()) { + this.removeTextEditor(textEditor); + } + } + + // Open file(s) + for (File file : files) { + boolean isExist = false; + for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { + TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); + if (file.getAbsolutePath().equals(te.getFileName())) { + isExist = true; + this.setActiveTextEditor(te); + break; + } + } + if (isExist) { + continue; + } + TextEditor editor = addNewTextEditor(file.getName()); + editor.openFile(file); + this.setTitleText(editor.getFileName()); + } + } + + /** + * Open script file + * + * @param file The file + */ + public void openFile(File file) { + // Close default untitled document if it is still empty + if (this.tabbedPanel.getTabCount() == 1) { + TextEditor textEditor = getActiveTextEditor(); + if (textEditor.getTextArea().getDocument().getLength() == 0 && textEditor.getFileName().isEmpty()) { + this.removeTextEditor(textEditor); + } + } + + // Open file + boolean isExist = false; + for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { + TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); + if (file.getAbsolutePath().equals(te.getFileName())) { + isExist = true; + this.setActiveTextEditor(te); + break; + } + } + if (!isExist) { + TextEditor editor = addNewTextEditor(file.getName()); + editor.openFile(file); + this.parent.getOptions().addRecentFile(file.getAbsolutePath()); + this.setTitleText(editor.getFileName()); + } + } + + /** + * Get opened file names + * + * @return Opened file names + */ + public List getOpenedFiles() { + List fns = new ArrayList<>(); + for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) { + TextEditor te = (TextEditor) this.tabbedPanel.getComponentAt(i); + fns.add(te.getFileName()); + } + + return fns; + } + + private void runCodeLines(MITextEditorPane textArea) throws InterruptedException, BadLocationException { + int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); + int sIdx = textArea.getLineStartOffset(sLine); + int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); + int eIdx = textArea.getLineEndOffset(eLine); + textArea.setSelectionStart(sIdx); + textArea.setSelectionEnd(eIdx); + String code = textArea.getSelectedText(); + + this.parent.getConsoleDockable().run(code); + } + + /** + * Toggle comment to the selected lines + */ + public void Comment() { + try { + comment((MITextEditorPane)this.getActiveTextArea()); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (BadLocationException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private void comment(MITextEditorPane textArea) throws InterruptedException, BadLocationException { + int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); + int sIdx = textArea.getLineStartOffset(sLine); + int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); + int eIdx = textArea.getLineEndOffset(eLine); + textArea.setSelectionStart(sIdx); + textArea.setSelectionEnd(eIdx); + String text = textArea.getSelectedText(); + + String[] lines = text.split("\n"); + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + String nLine = line.trim(); + if (nLine.startsWith("#")) { + sb.append(line.replaceFirst("#", "")); + } else { + sb.append("#" + line); + } + + sb.append("\n"); + } + text = sb.toString(); + textArea.replaceSelection(text); + } + + /** + * Delete first 4 spaces to the seleted lines + */ + public void delTab() { + try { + delTab((MITextEditorPane)this.getActiveTextArea()); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (BadLocationException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private void delTab(MITextEditorPane textArea) throws InterruptedException, BadLocationException { + int sLine = textArea.getLineOfOffset(textArea.getSelectionStart()); + int sIdx = textArea.getLineStartOffset(sLine); + int eLine = textArea.getLineOfOffset(textArea.getSelectionEnd()); + int eIdx = textArea.getLineEndOffset(eLine); + textArea.setSelectionStart(sIdx); + textArea.setSelectionEnd(eIdx); + String text = textArea.getSelectedText(); + + String[] lines = text.split("\n"); + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + if (line.startsWith(" ")) + sb.append(line.substring(4)); + else if (line.startsWith(" ")) + sb.append(line.substring(3)); + else if (line.startsWith(" ")) + sb.append(line.substring(2)); + else if (line.startsWith(" ")) + sb.append(line.substring(1)); + else + sb.append(line); + + sb.append("\n"); + } + text = sb.toString(); + textArea.replaceSelection(text); + } + + /** + * Insert first 4 spaces to the seleted lines + */ + public void insertTab() { + try { + insertTab((MITextEditorPane)this.getActiveTextArea()); + } catch (InterruptedException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } catch (AWTException ex) { + Logger.getLogger(EditorDockable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private void insertTab(MITextEditorPane textArea) throws InterruptedException, AWTException { + Robot robot = new Robot(); + robot.keyPress(KeyEvent.VK_TAB); + } + + /** + * Run Jython script + * + * @param jTextArea_Output + */ + public void runPythonScript(final JTextArea jTextArea_Output) { + + SwingWorker worker = new SwingWorker() { + PrintStream oout = System.out; + PrintStream oerr = System.err; + + @Override + protected String doInBackground() throws Exception { + JTextAreaWriter writer = new JTextAreaWriter(jTextArea_Output); + JTextAreaPrintStream printStream = new JTextAreaPrintStream(System.out, jTextArea_Output); + jTextArea_Output.setText(""); + + // Create an instance of the PythonInterpreter + //Py.getSystemState().setdefaultencoding("utf-8"); + //UPythonInterpreter interp = new UPythonInterpreter(); + PythonInterpreter interp = new PythonInterpreter(); + interp.setOut(writer); + interp.setErr(writer); + System.setOut(printStream); + System.setErr(printStream); + //System.out.println("Out test!"); + //System.err.println("Error test!"); + +// boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean(). +// getInputArguments().toString().contains("jdwp"); + //String pluginPath = startupPath + File.separator + "plugins"; + //List jarfns = GlobalUtil.getFiles(pluginPath, ".jar"); + //String path = startupPath + File.separator + "pylib"; +// if (isDebug) { +// path = "D:/MyProgram/Distribution/Java/MeteoInfo/MeteoInfo/pylib"; +// } + try { + interp.exec("import sys"); + interp.set("milapp", EditorDockable.this.parent); + //interp.exec("sys.path.append('" + path + "')"); + //interp.exec("import mipylib"); + //interp.exec("from mipylib.miscript import *"); + //interp.exec("from meteoinfo.numeric.JNumeric import *"); + //interp.exec("mis = MeteoInfoScript()"); + //interp.set("miapp", _parent); + //for (String jarfn : jarfns) { + // interp.exec("sys.path.append('" + jarfn + "')"); + //} + } catch (Exception e) { + e.printStackTrace(); + } + + TextEditorPane textArea = getActiveTextArea(); + //textArea.setEncoding(fn); + String code = textArea.getText(); +// if (code.contains("coding=utf-8")){ +// code = code.replace("coding=utf-8", "coding = utf-8"); +// } + String encoding = EncodingUtil.findEncoding(code); + if (encoding != null) { + try { + interp.execfile(new ByteArrayInputStream(code.getBytes(encoding))); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + try { + interp.execfile(new ByteArrayInputStream(code.getBytes())); + } catch (Exception e) { + e.printStackTrace(); + } + } +// try { +// //interp.exec(code); +// interp.execfile(new ByteArrayInputStream(code.getBytes())); +// } catch (Exception e) { +// e.printStackTrace(); +// } + + return ""; + } + + @Override + protected void done() { + System.setOut(oout); + System.setErr(oerr); + } + }; + worker.execute(); + } +} diff --git a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FileExplorer.java b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FileExplorer.java index fc655def..4e960018 100644 --- a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FileExplorer.java +++ b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FileExplorer.java @@ -22,7 +22,7 @@ import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.laboratory.event.CurrentPathChangedEvent; import org.meteoinfo.laboratory.event.ICurrentPathChangedListener; import org.meteoinfo.table.IconRenderer; diff --git a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAbout.java b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAbout.java index 5e23ff1e..61e957dc 100644 --- a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAbout.java +++ b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAbout.java @@ -4,6 +4,8 @@ */ package org.meteoinfo.laboratory.gui; +import org.meteoinfo.common.util.GlobalUtil; + import java.awt.Cursor; import java.awt.Desktop; import java.io.IOException; @@ -11,7 +13,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.global.util.GlobalUtil; /** * diff --git a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAppsManager.java b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAppsManager.java index e88117e1..60f31fc1 100644 --- a/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAppsManager.java +++ b/MeteoInfoLab/src/main/java/org/meteoinfo/laboratory/gui/FrmAppsManager.java @@ -15,9 +15,10 @@ import java.util.logging.Logger; import javax.swing.DefaultListModel; import javax.swing.JFrame; import javax.xml.parsers.ParserConfigurationException; + +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.laboratory.application.Application; import org.meteoinfo.laboratory.application.AppCollection; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.plugin.IPlugin; import org.meteoinfo.ui.CheckBoxListEntry; import org.python.core.PyObject; diff --git a/MeteoInfoLib/MeteoInfoLib.iml b/MeteoInfoLib/MeteoInfoLib.iml index ff1ddf53..f8c4cec5 100644 --- a/MeteoInfoLib/MeteoInfoLib.iml +++ b/MeteoInfoLib/MeteoInfoLib.iml @@ -12,6 +12,15 @@ + + + + + + + + + diff --git a/MeteoInfoLib/pom.xml b/MeteoInfoLib/pom.xml index fc6ad5d4..32963e46 100644 --- a/MeteoInfoLib/pom.xml +++ b/MeteoInfoLib/pom.xml @@ -47,6 +47,11 @@ + + ${project.groupId} + meteoinfo-math + ${project.version} + ${project.groupId} meteoinfo-ndarray diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayMath.java b/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayMath.java deleted file mode 100644 index ed9f3a17..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayMath.java +++ /dev/null @@ -1,6718 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.bak; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.meteoinfo.math.meteo.MeteoMath; -import org.meteoinfo.data.analysis.Statistics; -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.ndarray.Complex; -import org.meteoinfo.shape.PolygonShape; -import org.python.core.PyComplex; -import org.meteoinfo.ndarray.Array; -import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.ndarray.Index; -import org.meteoinfo.ndarray.IndexIterator; -import org.meteoinfo.ndarray.InvalidRangeException; -import org.meteoinfo.ndarray.MAMath; -import org.meteoinfo.ndarray.Range; - -/** - * - * @author wyq - */ -public class ArrayMath { - - public static double fill_value = -9999.0; - - // - /** - * Get data type - * - * @param o Object - * @return Data type - */ - public static DataType getDataType(Object o) { - if (o instanceof Integer) { - return DataType.INT; - } else if (o instanceof Float) { - return DataType.FLOAT; - } else if (o instanceof Double) { - return DataType.DOUBLE; - } else if (o instanceof Boolean) { - return DataType.BOOLEAN; - } else { - return DataType.OBJECT; - } - } - - private static DataType commonType(DataType aType, DataType bType) { - if (aType == bType) { - return aType; - } - - if (aType == DataType.OBJECT || bType == DataType.OBJECT) { - return DataType.OBJECT; - } - - short anb = ArrayMath.typeToNBytes(aType); - short bnb = ArrayMath.typeToNBytes(bType); - if (anb == bnb) { - switch (aType) { - case INT: - case LONG: - return bType; - case FLOAT: - case DOUBLE: - return aType; - } - } - - return (anb > bnb) ? aType : bType; - } - - /** - * Return the number of bytes per element for the given typecode. - * - * @param dataType Data type - * @return Bytes number - */ - public static short typeToNBytes(final DataType dataType) { - switch (dataType) { - case BYTE: - return 1; - case SHORT: - return 2; - case INT: - case FLOAT: - return 4; - case LONG: - case DOUBLE: - return 8; - default: - return 0; - } - } - - /** - * Check if an array is complex data type - * - * @param a The array - * @return Complex data type or not - */ - public static boolean isComplex(Array a) { - Object a0 = a.getObject(0); - return a0 instanceof Complex; - } - - /** - * Check if an array is numeric array - * - * @param a The array - * @return Numeric or not - */ - public static boolean isNumeric(Array a) { - boolean r = a.getDataType().isNumeric(); - if (!r) { - r = isComplex(a); - } - return r; - } - - // - // - /** - * Broadcast check for two arrays. - * - * @param a Array a - * @param b Array b - * @return Can broadcast (1), can not broadcast (-1), same dimensions (0) - */ - public static int broadcastCheck(Array a, Array b) { - int[] ashape = a.getShape(); - int[] bshape = b.getShape(); - int n = ashape.length; - int m = bshape.length; - if (n != m) { - int len = Math.min(n, m); - int na, nb; - for (int i = 0; i < len; i++) { - na = ashape[n - i - 1]; - nb = bshape[m - i - 1]; - if (na != nb && na != 1 && nb != 1) { - return -1; - } - } - return 1; - } else { - boolean sameDim = true; - for (int i = 0; i < n; i++) { - if (ashape[i] != bshape[i]) { - sameDim = false; - break; - } - } - if (sameDim) { - return 0; - } else { - for (int i = 0; i < n; i++) { - if (ashape[i] != bshape[i] && ashape[i] != 1 && bshape[i] != 1) { - return -1; - } - } - return 1; - } - } - } - - /** - * Get broadcast shape from two arrays - * - * @param a Array a - * @param b Array b - * @return Broadcast shape - */ - public static int[] broadcast(Array a, Array b) { - int[] ashape = a.getShape(); - int[] bshape = b.getShape(); - int n = ashape.length; - int m = bshape.length; - if (n == m) { - int[] shape = new int[n]; - for (int i = 0; i < n; i++) { - shape[i] = Math.max(ashape[i], bshape[i]); - } - return shape; - } else { - int len = Math.max(n, m); - int[] shape = new int[len]; - int na, nb; - for (int i = 0; i < len; i++) { - if (m < n) { - na = ashape[n - i - 1]; - if (m - i - 1 >= 0) { - nb = bshape[m - i - 1]; - shape[n - i - 1] = Math.max(na, nb); - } else { - shape[n - i - 1] = na; - } - } else { - nb = bshape[m - i - 1]; - if (n - i - 1 >= 0) { - na = ashape[n - i - 1]; - shape[m - i - 1] = Math.max(na, nb); - } else { - shape[m - i - 1] = nb; - } - } - } - return shape; - } - } - - private static void setIndex(int broadcast, Index aindex, Index bindex, int[] current, int n, int na, int nb) { - if (broadcast == 0) { - aindex.set(current); - bindex.set(current); - } else { - int ia, ib; - for (int j = 0; j < n; j++) { - ia = na - j - 1; - if (ia >= 0) { - if (aindex.getShape(ia) == 1) { - aindex.setDim(ia, 0); - } else { - aindex.setDim(ia, current[n - j - 1]); - } - } - ib = nb - j - 1; - if (ib >= 0) { - if (bindex.getShape(ib) == 1) { - bindex.setDim(ib, 0); - } else { - bindex.setDim(ib, current[n - j - 1]); - } - } - } - } - } - - private static void setIndex(Index aindex, Index bindex, int[] current, int n, int na, int nb) { - int ia, ib; - for (int j = 0; j < n; j++) { - ia = na - j - 1; - if (ia >= 0) { - if (aindex.getShape(ia) == 1) { - aindex.setDim(ia, 0); - } else { - aindex.setDim(ia, current[n - j - 1]); - } - } - ib = nb - j - 1; - if (ib >= 0) { - if (bindex.getShape(ib) == 1) { - bindex.setDim(ib, 0); - } else { - bindex.setDim(ib, current[n - j - 1]); - } - } - } - } - - /** - * Array add - * - * @param a Array a - * @param b Array b - * @return Added array - */ - public static Array add(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.addInt(a, b); - case FLOAT: - return ArrayMath.addFloat(a, b); - case DOUBLE: - return ArrayMath.addDouble(a, b); - case OBJECT: - if (isComplex(a) || isComplex(b)) { - return ArrayMath.addComplex(a, b); - } - break; - } - return null; - } - - /** - * Array add - * - * @param a Array a - * @param b Number b - * @return Added array - */ - public static Array add(Array a, Number b) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.addInt(a, b.intValue()); - case FLOAT: - return ArrayMath.addFloat(a, b.floatValue()); - case DOUBLE: - return ArrayMath.addDouble(a, b.doubleValue()); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.addComplex(a, b.doubleValue()); - } - break; - } - return null; - } - - /** - * Array add - * - * @param a Array a - * @param b Complex number b - * @return Added array - */ - public static Array add(Array a, Complex b) { - return addComplex(a, b); - } - - /** - * Array add - * - * @param a Array a - * @param b Complex number b - * @return Added array - */ - public static Array add(Array a, PyComplex b) { - return addComplex(a, new Complex(b.real, b.imag)); - } - - private static Array addInt_bak(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - if (broadcast != -1) { - int[] shape; - if (broadcast == 0) { - shape = a.getShape(); - } else { - shape = broadcast(a, b); - } - Array r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(broadcast, aindex, bindex, current, n, na, nb); - if (a.getInt(aindex) == Integer.MIN_VALUE || b.getInt(bindex) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(aindex) + b.getInt(bindex)); - } - index.incr(); - } - return r; - } else { - return null; - } - } - - private static Array addInt(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getInt(i) == Integer.MIN_VALUE || b.getInt(i) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(i) + b.getInt(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (a.getInt(aindex) == Integer.MIN_VALUE || b.getInt(bindex) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(aindex) + b.getInt(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array addInt(Array a, int b) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getInt(i) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(i) + b); - } - } - - return r; - } - - private static Array addFloat(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i)) || Float.isNaN(b.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) + b.getFloat(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.FLOAT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Float.isNaN(a.getFloat(aindex)) || Float.isNaN(b.getFloat(bindex))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(aindex) + b.getFloat(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array addFloat(Array a, float b) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) + b); - } - } - - return r; - } - - private static Array addDouble(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i)) || Double.isNaN(b.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) + b.getDouble(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.DOUBLE, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Double.isNaN(a.getDouble(aindex)) || Double.isNaN(b.getDouble(bindex))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(aindex) + b.getDouble(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array addDouble(Array a, double b) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) + b); - } - } - - return r; - } - - private static Array addComplex(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.OBJECT, a.getShape()); - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < a.getSize(); i++) { - v1 = (Complex) a.getObject(i); - v2 = (Complex) b.getObject(i); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.add(v2)); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN() || Double.isNaN(b.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.add(b.getDouble(i))); - } - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) b.getObject(i); - if (v.isNaN() || Double.isNaN(a.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.add(a.getDouble(i))); - } - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.OBJECT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v1 = (Complex) a.getObject(aindex); - v2 = (Complex) b.getObject(bindex); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.add(v2)); - } - index.incr(); - } - } else { - Complex v; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) a.getObject(aindex); - if (v.isNaN() || Double.isNaN(b.getDouble(bindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.add(b.getDouble(bindex))); - } - index.incr(); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) b.getObject(bindex); - if (v.isNaN() || Double.isNaN(a.getDouble(aindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.add(a.getDouble(aindex))); - } - } - } - return r; - default: - return null; - } - } - - private static Array addComplex(Array a, double b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.add(b)); - } - } - - return r; - } - - private static Array addComplex(Array a, Complex b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.add(b)); - } - } - - return r; - } - - /** - * Array subtract - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array sub(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.subInt(a, b); - case FLOAT: - return ArrayMath.subFloat(a, b); - case DOUBLE: - return ArrayMath.subDouble(a, b); - case OBJECT: - if (isComplex(a) || isComplex(b)) { - return ArrayMath.subComplex(a, b); - } - break; - } - return null; - } - - /** - * Array subtract - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array sub(Array a, Number b) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.subInt(a, b.intValue()); - case FLOAT: - return ArrayMath.subFloat(a, b.floatValue()); - case DOUBLE: - return ArrayMath.subDouble(a, b.doubleValue()); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.subComplex(a, b.doubleValue()); - } - break; - } - return null; - } - - /** - * Array subtract - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array sub(Array a, Complex b) { - return subComplex(a, b); - } - - /** - * Array subtract - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array sub(Array a, PyComplex b) { - return subComplex(a, new Complex(b.real, b.imag)); - } - - /** - * Array subtract - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array sub(Number b, Array a) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.subInt(b.intValue(), a); - case FLOAT: - return ArrayMath.subFloat(b.floatValue(), a); - case DOUBLE: - return ArrayMath.subDouble(b.doubleValue(), a); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.subComplex(b.doubleValue(), a); - } - break; - } - return null; - } - - /** - * Array subtract - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array sub(Complex b, Array a) { - return subComplex(b, a); - } - - /** - * Array subtract - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array sub(PyComplex b, Array a) { - return subComplex(new Complex(b.real, b.imag), a); - } - - private static Array subInt(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, a.getInt(i) - b.getInt(i)); - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - r.setInt(i, a.getInt(aindex) - b.getInt(bindex)); - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array subInt(Array a, int b) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, a.getInt(i) - b); - } - - return r; - } - - private static Array subInt(int b, Array a) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, b - a.getInt(i)); - } - - return r; - } - - private static Array subFloat(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i)) || Float.isNaN(b.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) - b.getFloat(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.FLOAT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Float.isNaN(a.getFloat(aindex)) || Float.isNaN(b.getFloat(bindex))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(aindex) - b.getFloat(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array subFloat(Array a, float b) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setFloat(i, a.getFloat(i) - b); - } - - return r; - } - - private static Array subFloat(float b, Array a) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setFloat(i, b - a.getFloat(i)); - } - - return r; - } - - private static Array subDouble(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i)) || Double.isNaN(b.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) - b.getDouble(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.DOUBLE, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Double.isNaN(a.getDouble(aindex)) || Double.isNaN(b.getDouble(bindex))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(aindex) - b.getDouble(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array subDouble(Array a, double b) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, a.getDouble(i) - b); - } - - return r; - } - - private static Array subDouble(double b, Array a) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, b - a.getDouble(i)); - } - - return r; - } - - private static Array subComplex(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.OBJECT, a.getShape()); - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < a.getSize(); i++) { - v1 = (Complex) a.getObject(i); - v2 = (Complex) b.getObject(i); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.subtract(v2)); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN() || Double.isNaN(b.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.subtract(b.getDouble(i))); - } - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) b.getObject(i); - if (v.isNaN() || Double.isNaN(a.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.subtract(a.getDouble(i))); - } - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.OBJECT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v1 = (Complex) a.getObject(aindex); - v2 = (Complex) b.getObject(bindex); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.subtract(v2)); - } - index.incr(); - } - } else { - Complex v; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) a.getObject(aindex); - if (v.isNaN() || Double.isNaN(b.getDouble(bindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.subtract(b.getDouble(bindex))); - } - index.incr(); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) b.getObject(bindex); - if (v.isNaN() || Double.isNaN(a.getDouble(aindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.subtract(a.getDouble(aindex))); - } - } - } - return r; - default: - return null; - } - } - - private static Array subComplex(Array a, double b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.subtract(b)); - } - } - - return r; - } - - private static Array subComplex(Array a, Complex b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.subtract(b)); - } - } - - return r; - } - - private static Array subComplex(double b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.rSubtract(b)); - } - } - - return r; - } - - private static Array subComplex(Complex b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, b.subtract(v)); - } - } - - return r; - } - - /** - * Array mutiply - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array mul(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.mulInt(a, b); - case FLOAT: - return ArrayMath.mulFloat(a, b); - case DOUBLE: - return ArrayMath.mulDouble(a, b); - case OBJECT: - if (isComplex(a) || isComplex(b)) { - return ArrayMath.mulComplex(a, b); - } - break; - } - return null; - } - - /** - * Array multiply - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array mul(Array a, Number b) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.mulInt(a, b.intValue()); - case FLOAT: - return ArrayMath.mulFloat(a, b.floatValue()); - case DOUBLE: - return ArrayMath.mulDouble(a, b.doubleValue()); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.mulComplex(a, b.doubleValue()); - } - break; - } - return null; - } - - /** - * Array multiply - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array mul(Array a, Complex b) { - return ArrayMath.mulComplex(a, b); - } - - /** - * Array multiply - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array mul(Array a, PyComplex b) { - return ArrayMath.mulComplex(a, new Complex(b.real, b.imag)); - } - - private static Array mulInt(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getInt(i) == Integer.MIN_VALUE || b.getInt(i) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(i) * b.getInt(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (a.getInt(aindex) == Integer.MIN_VALUE || b.getInt(bindex) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(aindex) * b.getInt(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array mulInt(Array a, int b) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getInt(i) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(i) * b); - } - } - - return r; - } - - private static Array mulFloat(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i)) || Float.isNaN(b.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) * b.getFloat(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.FLOAT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Float.isNaN(a.getFloat(aindex)) || Float.isNaN(b.getFloat(bindex))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(aindex) * b.getFloat(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array mulFloat(Array a, float b) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) * b); - } - } - - return r; - } - - private static Array mulDouble(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i)) || Double.isNaN(b.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) * b.getDouble(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.DOUBLE, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Double.isNaN(a.getDouble(aindex)) || Double.isNaN(b.getDouble(bindex))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(aindex) * b.getDouble(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array mulDouble(Array a, double b) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) * b); - } - } - - return r; - } - - private static Array mulComplex(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.OBJECT, a.getShape()); - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < a.getSize(); i++) { - v1 = (Complex) a.getObject(i); - v2 = (Complex) b.getObject(i); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.multiply(v2)); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN() || Double.isNaN(b.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.multiply(b.getDouble(i))); - } - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) b.getObject(i); - if (v.isNaN() || Double.isNaN(a.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.multiply(a.getDouble(i))); - } - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.OBJECT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v1 = (Complex) a.getObject(aindex); - v2 = (Complex) b.getObject(bindex); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.multiply(v2)); - } - index.incr(); - } - } else { - Complex v; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) a.getObject(aindex); - if (v.isNaN() || Double.isNaN(b.getDouble(bindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.multiply(b.getDouble(bindex))); - } - index.incr(); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) b.getObject(bindex); - if (v.isNaN() || Double.isNaN(a.getDouble(aindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.multiply(a.getDouble(aindex))); - } - } - } - return r; - default: - return null; - } - } - - private static Array mulComplex(Array a, double b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.multiply(b)); - } - } - - return r; - } - - private static Array mulComplex(Array a, Complex b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.multiply(b)); - } - } - - return r; - } - - /** - * Array divide - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array div(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.divInt(a, b); - case FLOAT: - return ArrayMath.divFloat(a, b); - case DOUBLE: - return ArrayMath.divDouble(a, b); - case OBJECT: - if (isComplex(a) || isComplex(b)) { - return ArrayMath.divComplex(a, b); - } - break; - } - return null; - } - - /** - * Array divide - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array div(Array a, Number b) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.divInt(a, b.intValue()); - case FLOAT: - return ArrayMath.divFloat(a, b.floatValue()); - case DOUBLE: - return ArrayMath.divDouble(a, b.doubleValue()); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.divComplex(a, b.doubleValue()); - } - break; - } - return null; - } - - /** - * Array divide - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array div(Array a, Complex b) { - return divComplex(a, b); - } - - /** - * Array divide - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array div(Array a, PyComplex b) { - return divComplex(a, new Complex(b.real, b.imag)); - } - - /** - * Array divide - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array div(Number b, Array a) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.divInt(b.intValue(), a); - case FLOAT: - return ArrayMath.divFloat(b.floatValue(), a); - case DOUBLE: - return ArrayMath.divDouble(b.doubleValue(), a); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.divComplex(b.doubleValue(), a); - } - break; - } - return null; - } - - /** - * Array divide - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array div(Complex b, Array a) { - return divComplex(b, a); - } - - /** - * Array divide - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array div(PyComplex b, Array a) { - return divComplex(new Complex(b.real, b.imag), a); - } - - private static Array divInt(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getInt(i) == Integer.MIN_VALUE || b.getInt(i) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(i) / b.getInt(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (a.getInt(aindex) == Integer.MIN_VALUE || b.getInt(bindex) == Integer.MIN_VALUE) { - r.setInt(i, Integer.MIN_VALUE); - } else { - r.setInt(i, a.getInt(aindex) / b.getInt(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array divInt(Array a, int b) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, a.getInt(i) / b); - } - - return r; - } - - private static Array divInt(int b, Array a) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, b / a.getInt(i)); - } - - return r; - } - - private static Array divFloat(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Float.isNaN(a.getFloat(i)) || Float.isNaN(b.getFloat(i))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(i) / b.getFloat(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.FLOAT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Float.isNaN(a.getFloat(aindex)) || Float.isNaN(b.getFloat(bindex))) { - r.setFloat(i, Float.NaN); - } else { - r.setFloat(i, a.getFloat(aindex) / b.getFloat(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array divFloat(Array a, float b) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setFloat(i, a.getFloat(i) / b); - } - - return r; - } - - private static Array divFloat(float b, Array a) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setFloat(i, b / a.getFloat(i)); - } - - return r; - } - - private static Array divDouble(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i)) || Double.isNaN(b.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(i) / b.getDouble(i)); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.DOUBLE, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Double.isNaN(a.getDouble(aindex)) || Double.isNaN(b.getDouble(bindex))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a.getDouble(aindex) / b.getDouble(bindex)); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array divDouble(Array a, double b) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, a.getDouble(i) / b); - } - - return r; - } - - private static Array divDouble(double b, Array a) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, b / a.getDouble(i)); - } - - return r; - } - - private static Array divComplex(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.OBJECT, a.getShape()); - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < a.getSize(); i++) { - v1 = (Complex) a.getObject(i); - v2 = (Complex) b.getObject(i); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.divide(v2)); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN() || Double.isNaN(b.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.divide(b.getDouble(i))); - } - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) b.getObject(i); - if (v.isNaN() || Double.isNaN(a.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.divide(a.getDouble(i))); - } - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.OBJECT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v1 = (Complex) a.getObject(aindex); - v2 = (Complex) b.getObject(bindex); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.divide(v2)); - } - index.incr(); - } - } else { - Complex v; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) a.getObject(aindex); - if (v.isNaN() || Double.isNaN(b.getDouble(bindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.divide(b.getDouble(bindex))); - } - index.incr(); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) b.getObject(bindex); - if (v.isNaN() || Double.isNaN(a.getDouble(aindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.divide(a.getDouble(aindex))); - } - } - } - return r; - default: - return null; - } - } - - private static Array divComplex(Array a, double b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.divide(b)); - } - } - - return r; - } - - private static Array divComplex(Array a, Complex b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.divide(b)); - } - } - - return r; - } - - private static Array divComplex(double b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.rDivide(b)); - } - } - - return r; - } - - private static Array divComplex(Complex b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, b.divide(v)); - } - } - - return r; - } - - /** - * Array pow function - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array pow(Array a, Number b) { - DataType bType = ArrayMath.getDataType(b); - DataType type = ArrayMath.commonType(a.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.powInt(a, b.intValue()); - case FLOAT: - case DOUBLE: - return ArrayMath.powDouble(a, b.doubleValue()); - case OBJECT: - if (isComplex(a)) { - return ArrayMath.powComplex(a, b.doubleValue()); - } - break; - } - return null; - } - - /** - * Array pow function - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array pow(Array a, Complex b) { - return powComplex(a, b); - } - - /** - * Array pow function - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array pow(Array a, PyComplex b) { - return powComplex(a, new Complex(b.real, b.imag)); - } - - /** - * Array pow function - * - * @param a Number a - * @param b Array b - * @return Result array - */ - public static Array pow(Number a, Array b) { - DataType bType = ArrayMath.getDataType(a); - DataType type = ArrayMath.commonType(b.getDataType(), bType); - switch (type) { - case SHORT: - case INT: - case BOOLEAN: - return ArrayMath.powInt(a.intValue(), b); - case FLOAT: - case DOUBLE: - return ArrayMath.powDouble(a.doubleValue(), b); - case OBJECT: - if (isComplex(b)) { - return ArrayMath.powComplex(a.doubleValue(), b); - } - break; - } - return null; - } - - /** - * Array pow function - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array pow(Complex b, Array a) { - return powComplex(b, a); - } - - /** - * Array pow function - * - * @param a Array a - * @param b Complex number b - * @return Result array - */ - public static Array pow(PyComplex b, Array a) { - return powComplex(new Complex(b.real, b.imag), a); - } - - /** - * Array pow function - * - * @param a Number a - * @param b Array b - * @return Result array - */ - public static Array pow(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - switch (type) { - case SHORT: - case INT: - return ArrayMath.powInt(a, b); - case FLOAT: - case DOUBLE: - return ArrayMath.powDouble(a, b); - case OBJECT: - if (isComplex(a) || isComplex(b)) { - return ArrayMath.powComplex(a, b); - } - break; - } - return null; - } - - private static Array powInt(Array a, int b) { - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, (int) Math.pow(a.getInt(i), b)); - } - - return r; - } - - private static Array powInt(int a, Array b) { - Array r = Array.factory(DataType.INT, b.getShape()); - for (int i = 0; i < b.getSize(); i++) { - r.setInt(i, (int) Math.pow(a, b.getInt(i))); - } - - return r; - } - - private static Array powInt(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setInt(i, (int) Math.pow(a.getInt(i), b.getInt(i))); - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.INT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - r.setInt(i, (int) Math.pow(a.getInt(aindex), b.getInt(bindex))); - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array powDouble(Array a, double b) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.pow(a.getDouble(i), b)); - } - - return r; - } - - private static Array powDouble(double a, Array b) { - Array r = Array.factory(DataType.DOUBLE, b.getShape()); - for (int i = 0; i < b.getSize(); i++) { - r.setDouble(i, Math.pow(a, b.getDouble(i))); - } - - return r; - } - - private static Array powDouble(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i)) || Double.isNaN(b.getDouble(i))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, Math.pow(a.getDouble(i), b.getDouble(i))); - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.DOUBLE, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - if (Double.isNaN(a.getDouble(aindex)) || Double.isNaN(b.getDouble(bindex))) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, Math.pow(a.getDouble(aindex), b.getDouble(bindex))); - } - index.incr(); - } - return r; - default: - return null; - } - } - - private static Array powComplex(Array a, Array b) { - int broadcast = broadcastCheck(a, b); - switch (broadcast) { - case 0: - Array r = Array.factory(DataType.OBJECT, a.getShape()); - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < a.getSize(); i++) { - v1 = (Complex) a.getObject(i); - v2 = (Complex) b.getObject(i); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.pow(v2)); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN() || Double.isNaN(b.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.pow(b.getDouble(i))); - } - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) b.getObject(i); - if (v.isNaN() || Double.isNaN(a.getDouble(i))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.pow(a.getDouble(i))); - } - } - } - return r; - case 1: - int[] shape = broadcast(a, b); - r = Array.factory(DataType.OBJECT, shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - Index bindex = b.getIndex(); - int n = r.getRank(); - int na = a.getRank(); - int nb = b.getRank(); - int[] current; - if (isComplex(a)) { - if (isComplex(b)) { - Complex v1, v2; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v1 = (Complex) a.getObject(aindex); - v2 = (Complex) b.getObject(bindex); - if (v1.isNaN() || v2.isNaN()) { - r.setObject(i, v1); - } else { - r.setObject(i, v1.pow(v2)); - } - index.incr(); - } - } else { - Complex v; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) a.getObject(aindex); - if (v.isNaN() || Double.isNaN(b.getDouble(bindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.pow(b.getDouble(bindex))); - } - index.incr(); - } - } - } else { - Complex v; - for (int i = 0; i < a.getSize(); i++) { - current = index.getCurrentCounter(); - setIndex(aindex, bindex, current, n, na, nb); - v = (Complex) b.getObject(bindex); - if (v.isNaN() || Double.isNaN(a.getDouble(aindex))) { - r.setObject(i, new Complex(Double.NaN)); - } else { - r.setObject(i, v.pow(a.getDouble(aindex))); - } - } - } - return r; - default: - return null; - } - } - - private static Array powComplex(Array a, double b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.pow(b)); - } - } - - return r; - } - - private static Array powComplex(Array a, Complex b) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.pow(b)); - } - } - - return r; - } - - private static Array powComplex(double b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, v.rPow(b)); - } - } - - return r; - } - - private static Array powComplex(Complex b, Array a) { - Array r = Array.factory(DataType.OBJECT, a.getShape()); - Complex v; - for (int i = 0; i < a.getSize(); i++) { - v = (Complex) a.getObject(i); - if (v.isNaN()) { - r.setObject(i, v); - } else { - r.setObject(i, b.pow(v)); - } - } - - return r; - } - - /** - * Sqrt function - * - * @param a Array a - * @return Result array - */ - public static Array sqrt(Array a) { - return ArrayMath.pow(a, 0.5); - } - - /** - * Exponent function - * - * @param a Array a - * @return Result array - */ - public static Array exp(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).exp()); - } - } else { - r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.exp(a.getDouble(i))); - } - } - - return r; - } - - /** - * Log function - * - * @param a Array a - * @return Result array - */ - public static Array log(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).log()); - } - } else { - r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.log(a.getDouble(i))); - } - } - - return r; - } - - /** - * Log10 function - * - * @param a Array a - * @return Result array - */ - public static Array log10(Array a) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.log10(a.getDouble(i))); - } - - return r; - } - - /** - * Array absolute - * - * @param a Array a - * @return Result array - */ - public static Array abs(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.DOUBLE, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, ((Complex) a.getObject(i)).abs()); - } - } else { - r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.abs(a.getDouble(i))); - } - } - - return r; - } - - /** - * Array equal - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array equal(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) == b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array equal - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array equal(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - double v = b.doubleValue(); - if (Double.isNaN(v)) { - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i))) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - } else { - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) == v) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - } - - return r; - } - - /** - * Array equal - * - * @param a Array a - * @param b String b - * @return Result array - */ - public static Array equal(Array a, String b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getObject(i).equals(b)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array less than - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array lessThan(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) < b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array less than - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array lessThan(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) < b.doubleValue()) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array less than or equal - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array lessThanOrEqual(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) <= b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array less than or equal - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array lessThanOrEqual(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) <= b.doubleValue()) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array greater than - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array greaterThan(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) > b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array greater than - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array greaterThan(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) > b.doubleValue()) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array greater than or equal - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array greaterThanOrEqual(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) >= b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array greater than or equal - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array greaterThanOrEqual(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) >= b.doubleValue()) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array not equal - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array notEqual(Array a, Array b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) != b.getDouble(i)) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Array not equal - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array notEqual(Array a, Number b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - double v = b.doubleValue(); - if (Double.isNaN(v)) { - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i))) { - r.setBoolean(i, false); - } else { - r.setBoolean(i, true); - } - } - } else { - for (int i = 0; i < a.getSize(); i++) { - if (a.getDouble(i) != v) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - } - - return r; - } - - /** - * Test whether any array element evaluates to True. - * - * @param a The array - * @return Boolean - */ - public static boolean any(Array a) { - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - if (ii.getBooleanNext()) { - return true; - } - } - return false; - } - - /** - * Test whether any array element along a given axis evaluates to True. - * - * @param a Array a - * @param axis Axis - * @return Boolean array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array any(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.BOOLEAN, shape); - boolean b; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - IndexIterator ii = a.getRangeIterator(ranges); - b = false; - while (ii.hasNext()) { - if (ii.getBooleanNext()) { - b = true; - break; - } - } - r.setBoolean(i, b); - indexr.incr(); - } - - return r; - } - - /** - * Test whether all array element evaluates to True. - * - * @param a The array - * @return Boolean - */ - public static boolean all(Array a) { - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - if (!ii.getBooleanNext()) { - return false; - } - } - return true; - } - - /** - * Test whether all array element along a given axis evaluates to True. - * - * @param a Array a - * @param axis Axis - * @return Boolean array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array all(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.BOOLEAN, shape); - boolean b; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - IndexIterator ii = a.getRangeIterator(ranges); - b = true; - while (ii.hasNext()) { - if (!ii.getBooleanNext()) { - b = false; - break; - } - } - r.setBoolean(i, b); - indexr.incr(); - } - - return r; - } - - /** - * Return the array with the value of 1 when the input array element value - * in the list b, otherwise set value as 0. - * - * @param a Array a - * @param b List b - * @return Result array - */ - public static Array inValues(Array a, List b) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (b.contains(a.getObject(i))) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * Check if the array contains NaN value - * - * @param a Input array - * @return Boolean - */ - public static boolean containsNaN(Array a) { - boolean hasNaN = false; - for (int i = 0; i < a.getSize(); i++) { - if (Double.isNaN(a.getDouble(i))) { - hasNaN = true; - break; - } - } - - return hasNaN; - } - - /** - * Remove NaN values in an array - * - * @param a The array - * @return The array withou NaN values - */ - public static Array removeNaN(Array a) { - List d = new ArrayList<>(); - for (int i = 0; i < a.getSize(); i++) { - if (!Double.isNaN(a.getDouble(i))) { - d.add(a.getObject(i)); - } - } - - if (d.isEmpty()) { - return null; - } - - Array r = Array.factory(a.getDataType(), new int[]{d.size()}); - for (int i = 0; i < d.size(); i++) { - r.setObject(i, d.get(i)); - } - - return r; - } - - /** - * Remove NaN values in arrays - * - * @param a The arrays - * @return The array withou NaN values - */ - public static Array[] removeNaN(Array... a) { - if (a.length == 1) { - Array r0 = removeNaN(a[0]); - return r0 == null ? null : new Array[]{removeNaN(a[0])}; - } - - List d = new ArrayList<>(); - int n = (int) a[0].getSize(); - int m = a.length; - boolean isNan; - for (int i = 0; i < n; i++) { - isNan = false; - for (Array aa : a) { - if (Double.isNaN(aa.getDouble(i))) { - isNan = true; - break; - } - } - if (!isNan) { - for (Array aa : a) { - d.add(aa.getObject(i)); - } - } - } - - if (d.isEmpty()) { - return null; - } - - int len = d.size() / m; - Array[] r = new Array[m]; - for (int i = 0; i < m; i++) { - r[i] = Array.factory(a[i].getDataType(), new int[]{len}); - int jj = i; - for (int j = 0; j < len; j++) { - r[i].setObject(j, d.get(jj)); - jj += m; - } - } - - return r; - } - - /** - * Return the indices of the elements that are non-zero. - * - * @param a Input array - * @return Indices - */ - public static List nonzero(Array a) { - List> r = new ArrayList<>(); - int ndim = a.getRank(); - for (int i = 0; i < ndim; i++) { - r.add(new ArrayList()); - } - Index index = a.getIndex(); - int[] counter; - double v; - for (int i = 0; i < a.getSize(); i++) { - v = a.getDouble(i); - if (!Double.isNaN(v) && v != 0) { - counter = index.getCurrentCounter(); - for (int j = 0; j < ndim; j++) { - r.get(j).add(counter[j]); - } - } - index.incr(); - } - - if (r.get(0).isEmpty()) { - return null; - } - - List ra = new ArrayList<>(); - for (int i = 0; i < ndim; i++) { - ra.add(ArrayUtil.array(r.get(i))); - } - return ra; - } - - /** - * Bit and operation - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array bitAnd(Array a, Number b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) & b.intValue()); - } - - return r; - } - - /** - * Bit and operation - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array bitAnd(Array a, Array b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) & b.getInt(i)); - } - - return r; - } - - /** - * Bit or | operation - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array bitOr(Array a, Number b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) | b.intValue()); - } - - return r; - } - - /** - * Bit or | operation - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array bitOr(Array a, Array b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) | b.getInt(i)); - } - - return r; - } - - /** - * Bit exclusive or ^ operation - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array bitXor(Array a, Number b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) ^ b.intValue()); - } - - return r; - } - - /** - * Bit exclusive or | operation - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array bitXor(Array a, Array b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) ^ b.getInt(i)); - } - - return r; - } - - /** - * Bit inversion ~ operation - * - * @param a Array a - * @return Result array - */ - public static Array bitInvert(Array a) { - Array r = Array.factory(a.getDataType(), a.getShape()); - if (a.getDataType() == DataType.BOOLEAN) { - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, !a.getBoolean(i)); - } - } else { - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ~a.getInt(i)); - } - } - - return r; - } - - /** - * Bit left shift operation - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array leftShift(Array a, Number b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) << b.intValue()); - } - - return r; - } - - /** - * Bit left shift operation - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array leftShift(Array a, Array b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) << b.getInt(i)); - } - - return r; - } - - /** - * Bit right shift operation - * - * @param a Array a - * @param b Number b - * @return Result array - */ - public static Array rightShift(Array a, Number b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) >> b.intValue()); - } - - return r; - } - - /** - * Bit right shift operation - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array rightShift(Array a, Array b) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, a.getInt(i) >> b.getInt(i)); - } - - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param y Vecotr array - * @param dx Spacing between all y elements - * @return Definite integral as approximated by trapezoidal rule - */ - public static double trapz(Array y, double dx) { - int n = (int) y.getSize() - 1; - double a = 1; - double b = n * dx + a; - double r = 0, v; - int nn = 0; - for (int i = 0; i < y.getSize(); i++) { - v = y.getDouble(i); - if (Double.isNaN(v)) { - continue; - } - r += y.getDouble(i); - if (i > 0 && i < n) { - r += y.getDouble(i); - } - nn += 1; - } - if (nn >= 2) { - r = r * ((b - a) / (2 * n)); - } else { - r = Double.NaN; - } - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param y Vecotr array - * @param dx Spacing between all y elements - * @param ranges - * @return Definite integral as approximated by trapezoidal rule - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double trapz(Array y, double dx, List ranges) throws InvalidRangeException { - int n = 1; - for (Range range : ranges) { - n = n * range.length(); - } - n -= 1; - double a = 1; - double b = n * dx + a; - double r = 0; - double v; - IndexIterator ii = y.getRangeIterator(ranges); - int i = 0; - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (Double.isNaN(v)) { - continue; - } - r += v; - if (i > 0 && i < n) { - r += v; - } - i += 1; - } - if (i >= 2) { - r = r * ((b - a) / (2 * n)); - } else { - r = Double.NaN; - } - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param y Vecotr array - * @param x Spacing array between all y elements - * @return Definite integral as approximated by trapezoidal rule - */ - public static double trapz(Array y, Array x) { - int n = (int) y.getSize() - 1; - double r = 0; - double v; - int nn = 0; - for (int i = 0; i < n; i++) { - v = y.getDouble(i); - if (Double.isNaN(v)) { - continue; - } - r += (x.getDouble(i + 1) - x.getDouble(i)) * (y.getDouble(i + 1) + v); - nn += 1; - } - if (nn >= 2) { - r = r / 2; - } else { - r = Double.NaN; - } - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param y Vecotr array - * @param x Spacing array between all y elements - * @param ranges Ranges - * @return Definite integral as approximated by trapezoidal rule - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double trapz(Array y, Array x, List ranges) throws InvalidRangeException { - double r = 0; - double v; - double v0 = Double.NEGATIVE_INFINITY; - IndexIterator ii = y.getRangeIterator(ranges); - int i = 0, n = 0; - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (Double.isNaN(v)) { - i += 1; - continue; - } - if (Double.isInfinite(v0)) { - v0 = v; - continue; - } - r += (x.getDouble(i + 1) - x.getDouble(i)) * (v + v0); - v0 = v; - i += 1; - n += 1; - } - if (n >= 2) { - r = r / 2; - } else { - r = Double.NaN; - } - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param a Array a - * @param dx - * @param axis Axis - * @return Mean value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array trapz(Array a, double dx, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = trapz(a, dx, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Integrate vector array using the composite trapezoidal rule. - * - * @param a Array a - * @param x Array x - * @param axis Axis - * @return Mean value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array trapz(Array a, Array x, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = trapz(a, x, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Returns an element-wise indication of the sign of a number. The sign - * function returns -1 if x less than 0, 0 if x==0, 1 if x bigger than 0. - * nan is returned for nan inputs. - * - * @param x Input array - * @return The sign of x array - */ - public static Array sign(Array x) { - Array r = Array.factory(DataType.FLOAT, x.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setFloat(i, Math.signum(x.getFloat(i))); - } - - return r; - } - - // - // - /** - * Matrix multiplication - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array dot(Array a, Array b) { - DataType type = ArrayMath.commonType(a.getDataType(), b.getDataType()); - int[] shape; - if (a.getRank() == 2) { - if (a.getShape()[1] != b.getShape()[0]) { - return null; - } - if (b.getRank() == 2) { - shape = new int[2]; - shape[0] = a.getShape()[0]; - shape[1] = b.getShape()[1]; - } else { - shape = new int[1]; - shape[0] = a.getShape()[0]; - } - Array r = Array.factory(type, shape); - Index aIndex = a.getIndex(); - Index bIndex = b.getIndex(); - Index rIndex = r.getIndex(); - int n = a.getShape()[1]; - double v; - if (b.getRank() == 2) { - for (int i = 0; i < shape[0]; i++) { - for (int j = 0; j < shape[1]; j++) { - v = 0; - for (int m = 0; m < n; m++) { - v = v + a.getDouble(aIndex.set(i, m)) * b.getDouble(bIndex.set(m, j)); - } - r.setDouble(rIndex.set(i, j), v); - } - } - } else { - for (int i = 0; i < shape[0]; i++) { - v = 0; - for (int m = 0; m < n; m++) { - v = v + a.getDouble(aIndex.set(i, m)) * b.getDouble(bIndex.set(m)); - } - r.setDouble(rIndex.set(i), v); - } - } - return r; - } else { - if (a.getShape()[0] != b.getShape()[0]) { - return null; - } - shape = new int[1]; - shape[0] = b.getShape()[1]; - Array r = Array.factory(type, shape); - double v; - int n = a.getShape()[0]; - Index bIndex = b.getIndex(); - for (int i = 0; i < shape[0]; i++) { - v = 0; - for (int j = 0; j < n; j++) { - v += a.getDouble(j) * b.getDouble(bIndex.set(j, i)); - } - r.setDouble(i, v); - } - return r; - } - } - - /** - * Return the dot product of two vectors. - * - * @param a Vector a - * @param b Vector b - * @return Result - */ - public static double vdot(Array a, Array b) { - double r = 0; - for (int i = 0; i < a.getSize(); i++) { - r += a.getDouble(i) * b.getDouble(i); - } - - return r; - } - - // - // - /** - * Convert radians to degrees function - * - * @param a Array a - * @return Result array - */ - public static Array toDegrees(Array a) { - Array r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.toDegrees(a.getDouble(i))); - } - - return r; - } - - /** - * Convert radians to degrees function - * - * @param a Array a - * @return Result array - */ - public static Array toRadians(Array a) { - Array r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.toRadians(a.getDouble(i))); - } - - return r; - } - - /** - * Sine function - * - * @param a Array a - * @return Result array - */ - public static Array sin(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).sin()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.sin(a.getDouble(i))); - } - } - - return r; - } - - /** - * Cosine function - * - * @param a Array a - * @return Result array - */ - public static Array cos(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).cos()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.cos(a.getDouble(i))); - } - } - - return r; - } - - /** - * Tangent function - * - * @param a Array a - * @return Result array - */ - public static Array tan(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).tan()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.tan(a.getDouble(i))); - } - } - - return r; - } - - /** - * Arc sine function - * - * @param a Array a - * @return Result array - */ - public static Array asin(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).asin()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.asin(a.getDouble(i))); - } - } - - return r; - } - - /** - * Arc cosine function - * - * @param a Array a - * @return Result array - */ - public static Array acos(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).acos()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.acos(a.getDouble(i))); - } - } - - return r; - } - - /** - * Arc tangen function - * - * @param a Array a - * @return Result array - */ - public static Array atan(Array a) { - Array r; - if (isComplex(a)) { - r = Array.factory(DataType.OBJECT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setObject(i, ((Complex) a.getObject(i)).atan()); - } - } else { - r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.atan(a.getDouble(i))); - } - } - - return r; - } - - /** - * Arc tangen function - * - * @param a Array a - * @param b Array b - * @return Result array - */ - public static Array atan2(Array a, Array b) { - Array r = Array.factory(a.getDataType() == DataType.DOUBLE ? DataType.DOUBLE : DataType.FLOAT, a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - r.setDouble(i, Math.atan2(a.getDouble(i), b.getDouble(i))); - } - - return r; - } - - /** - * Convert cartesian to polar coordinate - * - * @param x X array - * @param y Y array - * @return Angle and radius - */ - public static Array[] cartesianToPolar(Array x, Array y) { - Array r = Array.factory(DataType.DOUBLE, x.getShape()); - Array B = Array.factory(DataType.DOUBLE, x.getShape()); - double[] rr; - for (int i = 0; i < x.getSize(); i++) { - rr = cartesianToPolar(x.getDouble(i), y.getDouble(i)); - r.setDouble(i, rr[1]); - B.setDouble(i, rr[0]); - } - - return new Array[]{B, r}; - } - - /** - * Convert poar to cartesian coordinate - * - * @param r Radius - * @param B Angle in radians - * @return X and y in cartesian coordinate - */ - public static Array[] polarToCartesian(Array B, Array r) { - Array x = Array.factory(DataType.DOUBLE, r.getShape()); - Array y = Array.factory(DataType.DOUBLE, r.getShape()); - double[] rr; - for (int i = 0; i < r.getSize(); i++) { - rr = polarToCartesian(B.getDouble(i), r.getDouble(i)); - x.setDouble(i, rr[0]); - y.setDouble(i, rr[1]); - } - - return new Array[]{x, y}; - } - - /** - * Convert cartesian to polar coordinate - * - * @param x X - * @param y Y - * @return Angle and radius - */ - public static double[] cartesianToPolar(double x, double y) { - double r; // Radius - double B; // Angle in radians - r = Math.hypot(x, y); - if (y >= 0) { - if (x == 0) { - B = Math.PI / 2;// 90° - } else { - B = Math.asin(x / y); - } - } else if (x == 0) { - B = 3 * Math.PI / 2;// 270° - } else { - B = Math.asin(x / y); - } - return new double[]{B, r}; - } - - /** - * Convert poar to cartesian coordinate - * - * @param r Radius - * @param B Angle in radians - * @return X and y in cartesian coordinate - */ - public static double[] polarToCartesian(double B, double r) { - double x = Math.cos(B) * r; - double y = Math.sin(B) * r; - - return new double[]{x, y}; - } - - // - // - /** - * Copy array - * - * @param a Input array - * @return Copied array - */ - public static Array copy(Array a) { - Array r = Array.factory(a.getDataType(), a.getShape()); - MAMath.copy(r, a); - return r; - } - - /** - * Section array - * - * @param a Array a - * @param origin Origin array - * @param size Size array - * @param stride Stride array - * @return Result array - * @throws InvalidRangeException - */ - public static Array section(Array a, int[] origin, int[] size, int[] stride) throws InvalidRangeException { - Array r = a.section(origin, size, stride); - Array rr = Array.factory(r.getDataType(), r.getShape()); - MAMath.copy(rr, r); - return rr; - } - - /** - * Section array - * - * @param a Array a - * @param ranges Ranges - * @return Result array - * @throws InvalidRangeException - */ - public static Array section(Array a, List ranges) throws InvalidRangeException { - Array r = a.section(ranges); - Array rr = Array.factory(r.getDataType(), r.getShape()); - MAMath.copy(rr, r); - return rr; - } - - /** - * Take elements from an array along an axis. - * - * @param a The array - * @param ranges The indices of the values to extract. - * @return The returned array has the same type as a. - */ - public static Array take(Array a, List ranges) { - int n = a.getRank(); - int[] shape = new int[n]; - List> indexlist = new ArrayList<>(); - List list; - for (int i = 0; i < n; i++) { - Object k = ranges.get(i); - if (k instanceof Range) { - Range kr = (Range) k; - shape[i] = kr.length(); - list = new ArrayList<>(); - for (int j = kr.first(); j <= kr.last(); j += kr.stride()) { - list.add(j); - } - indexlist.add(list); - } else { - List kl = (List) k; - shape[i] = kl.size(); - indexlist.add(kl); - } - } - - Array r = Array.factory(a.getDataType(), shape); - IndexIterator ii = r.getIndexIterator(); - int[] current, acurrent = new int[n]; - Index index = a.getIndex(); - while (ii.hasNext()) { - ii.next(); - current = ii.getCurrentCounter(); - for (int i = 0; i < n; i++) { - acurrent[i] = indexlist.get(i).get(current[i]); - } - index.set(acurrent); - ii.setObjectCurrent(a.getObject(index)); - } - - return r; - } - - /** - * Take elements from an array. - * - * @param a The array - * @param ranges The indices of the values to extract. - * @return The returned array has the same type as a. - */ - public static Array takeValues(Array a, List> ranges) { - int n = a.getRank(); - int nn = ranges.get(0).size(); - int[] shape = new int[]{nn}; - Array r = Array.factory(a.getDataType(), shape); - Index index = a.getIndex(); - int[] current = new int[n]; - for (int i = 0; i < nn; i++) { - for (int j = 0; j < n; j++) { - current[j] = ranges.get(j).get(i); - } - index.set(current); - r.setObject(i, a.getObject(index)); - } - - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Number value - * @return Result array - * @throws InvalidRangeException - */ - public static Array setSection(Array a, List ranges, Number v) throws InvalidRangeException { - Array r = a.section(ranges); - IndexIterator iter = r.getIndexIterator(); - if (a.getDataType() == DataType.BOOLEAN) { - boolean b = true; - if (v.doubleValue() == 0) { - b = false; - } - while (iter.hasNext()) { - iter.setObjectNext(b); - } - } else { - while (iter.hasNext()) { - iter.setObjectNext(v); - } - } - r = Array.factory(a.getDataType(), a.getShape(), r.getStorage()); - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Array value - * @return Result array - * @throws InvalidRangeException - */ - public static Array setSection(Array a, List ranges, Array v) throws InvalidRangeException { - Array r = a.section(ranges); - IndexIterator iter = r.getIndexIterator(); - //int[] current; - Index index = v.getIndex(); - while (iter.hasNext()) { - iter.next(); - //current = iter.getCurrentCounter(); - //index.set(current); - iter.setObjectCurrent(v.getObject(index)); - index.incr(); - } - r = Array.factory(a.getDataType(), a.getShape(), r.getStorage()); - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Number value - * @return Result array - */ - public static Array setSection_Mix(Array a, List ranges, Number v) { - Array r = Array.factory(a.getDataType(), a.getShape()); - int n = a.getRank(); - IndexIterator iter = r.getIndexIterator(); - Index aidx = a.getIndex(); - int[] current; - boolean isIn; - while (iter.hasNext()) { - iter.next(); - current = iter.getCurrentCounter(); - isIn = true; - for (int i = 0; i < n; i++) { - Object k = ranges.get(i); - if (k instanceof Range) { - if (!((Range) k).contains(current[i])) { - isIn = false; - break; - } - } else { - if (!((List) k).contains(current[i])) { - isIn = false; - break; - } - } - } - aidx.set(current); - if (isIn) { - iter.setObjectCurrent(v); - } else { - iter.setObjectCurrent(a.getObject(aidx)); - } - } - - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Array value - * @return Result array - */ - public static Array setSection_Mix(Array a, List ranges, Array v) { - Array r = Array.factory(a.getDataType(), a.getShape()); - int n = a.getRank(); - IndexIterator iter = r.getIndexIterator(); - Index aidx = a.getIndex(); - Index vidx = v.getIndex(); - int[] current; - boolean isIn; - while (iter.hasNext()) { - iter.next(); - current = iter.getCurrentCounter(); - isIn = true; - for (int i = 0; i < n; i++) { - Object k = ranges.get(i); - if (k instanceof Range) { - if (!((Range) k).contains(current[i])) { - isIn = false; - break; - } - } else { - if (!((List) k).contains(current[i])) { - isIn = false; - break; - } - } - } - if (isIn) { - iter.setObjectCurrent(v.getObject(vidx)); - vidx.incr(); - } else { - aidx.set(current); - iter.setObjectCurrent(a.getObject(aidx)); - } - } - - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Number value - * @return Result array - */ - public static Array setSection_List(Array a, List> ranges, Number v) { - Array r = copy(a); - int n = r.getRank(); - int[] count = new int[n]; - Index index = Index.factory(count); - int m = ranges.get(0).size(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - count[j] = ranges.get(j).get(i); - } - index.set(count); - r.setObject(index, v); - } - - return r; - } - - /** - * Set section - * - * @param a Array a - * @param ranges Ranges - * @param v Array value - * @return Result array - */ - public static Array setSection_List(Array a, List> ranges, Array v) { - Array r = copy(a); - int n = r.getRank(); - int[] count = new int[n]; - Index index = Index.factory(count); - Index vIndex = v.getIndex(); - int m = ranges.get(0).size(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - count[j] = ranges.get(j).get(i); - } - index.set(count); - r.setObject(index, v.getObject(vIndex)); - vIndex.incr(); - } - - return r; - } - - /** - * Flip array - * - * @param a Array a - * @param idxs Dimension index list - * @return Result array - */ - public static Array flip(Array a, List idxs) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i : idxs) { - r = a.flip(i); - } - Array rr = Array.factory(r.getDataType(), r.getShape()); - MAMath.copy(rr, r); - return rr; - } - - /** - * Flip array - * - * @param a Array a - * @param idx Dimension idex - * @return Result array - */ - public static Array flip(Array a, int idx) { - Array r = a.flip(idx); - Array rr = Array.factory(r.getDataType(), r.getShape()); - MAMath.copy(rr, r); - return rr; - } - - /** - * Transpose array - * - * @param a Array a - * @param dim1 Dimension index 1 - * @param dim2 Dimension index 2 - * @return Result array - */ - public static Array transpose(Array a, int dim1, int dim2) { - Array r = a.transpose(dim1, dim2); - Array rr = Array.factory(r.getDataType(), r.getShape()); - MAMath.copy(rr, r); - return rr; - } - - /** - * Rotate an array by 90 degrees in counter-clockwise direction. - * - * @param a The array - * @param k Rotate times - * @return Rotated array - */ - public static Array rot90(Array a, int k) { - int[] shape = new int[a.getRank()]; - if (Math.abs(k) % 2 == 1) { - shape[0] = a.getShape()[1]; - shape[1] = a.getShape()[0]; - } else { - shape[0] = a.getShape()[0]; - shape[1] = a.getShape()[1]; - } - if (a.getRank() > 2) { - for (int i = 2; i < a.getRank(); i++) { - shape[i] = a.getShape()[i]; - } - } - Array r = Array.factory(a.getDataType(), shape); - Index indexa = a.getIndex(); - Index indexr = r.getIndex(); - int[] countera, counterr; - switch (k) { - case 1: - case -3: - for (int i = 0; i < r.getSize(); i++) { - countera = indexa.getCurrentCounter(); - counterr = indexa.getCurrentCounter(); - counterr[0] = shape[0] - countera[1] - 1; - counterr[1] = countera[0]; - indexr.set(counterr); - r.setObject(indexr, a.getObject(indexa)); - indexa.incr(); - } - break; - case 2: - case -2: - for (int i = 0; i < r.getSize(); i++) { - countera = indexa.getCurrentCounter(); - counterr = indexa.getCurrentCounter(); - counterr[0] = shape[0] - countera[0] - 1; - counterr[1] = shape[1] - countera[1] - 1; - indexr.set(counterr); - r.setObject(indexr, a.getObject(indexa)); - indexa.incr(); - } - break; - case 3: - case -1: - for (int i = 0; i < r.getSize(); i++) { - countera = indexa.getCurrentCounter(); - counterr = indexa.getCurrentCounter(); - counterr[0] = countera[1]; - counterr[1] = shape[1] - countera[0] - 1; - indexr.set(counterr); - r.setObject(indexr, a.getObject(indexa)); - indexa.incr(); - } - break; - default: - r = null; - } - - return r; - } - - /** - * Join two arrays by a dimension - * - * @param a Array a - * @param b Array b - * @param dim Dimension for join - * @return Joined array - */ - public static Array join(Array a, Array b, int dim) { - int[] shape = a.getShape(); - int na = shape[dim]; - shape[dim] = shape[dim] + b.getShape()[dim]; - int n = shape[dim]; - Array r = Array.factory(a.getDataType(), shape); - IndexIterator iter = r.getIndexIterator(); - IndexIterator itera = a.getIndexIterator(); - IndexIterator iterb = b.getIndexIterator(); - int[] current; - int i = 0; - while (iter.hasNext()) { - if (i > 0) { - current = iter.getCurrentCounter(); - if (current[dim] < na - 1 || current[dim] == n - 1) { - iter.setObjectNext(itera.getObjectNext()); - } else { - iter.setObjectNext(iterb.getObjectNext()); - } - } else { - iter.setObjectNext(itera.getObjectNext()); - } - i += 1; - } - - return r; - } - - // - // - /** - * Get minimum value - * - * @param a Array a - * @return Minimum value - */ - public static double getMinimum(Array a) { - IndexIterator iter = a.getIndexIterator(); - double min = 1.7976931348623157E+308D; - while (iter.hasNext()) { - double val = iter.getDoubleNext(); - if (!Double.isNaN(val)) { - if (val < min) { - min = val; - } - } - } - if (min == 1.7976931348623157E+308D) { - return Double.NaN; - } else { - return min; - } - } - - /** - * Get maximum value - * - * @param a Array a - * @return Maximum value - */ - public static double getMaximum(Array a) { - IndexIterator iter = a.getIndexIterator(); - double max = -1.797693134862316E+307D; - while (iter.hasNext()) { - double val = iter.getDoubleNext(); - if (!Double.isNaN(val)) { - if (val > max) { - max = val; - } - } - } - if (max == -1.797693134862316E+307D) { - return Double.NaN; - } else { - return max; - } - } - - /** - * Get minimum value - * - * @param a Array a - * @param missingv Missing value - * @return Minimum value - */ - public static double getMinimum(Array a, double missingv) { - IndexIterator iter = a.getIndexIterator(); - double min = 1.7976931348623157E+308D; - while (iter.hasNext()) { - double val = iter.getDoubleNext(); - if (!MIMath.doubleEquals(val, missingv)) { - if (val < min) { - min = val; - } - } - } - return min; - } - - /** - * Get maximum value - * - * @param a Array a - * @param missingv Missing value - * @return Maximum value - */ - public static double getMaximum(Array a, double missingv) { - IndexIterator iter = a.getIndexIterator(); - double max = -1.797693134862316E+307D; - while (iter.hasNext()) { - double val = iter.getDoubleNext(); - if (!MIMath.doubleEquals(val, missingv)) { - if (val > max) { - max = val; - } - } - } - return max; - } - - /** - * Compute minimum value of an array - * - * @param a Array a - * @return Minimum value - */ - public static double min(Array a) { - double min = 1.7976931348623157E+308D; - double v; - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - if (v < min) { - min = v; - } - } - } - if (min == 1.7976931348623157E+308D) { - return Double.NaN; - } else { - return min; - } - } - - /** - * Compute minimum value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Minimum value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array min(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double s; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - s = min(a, ranges); - r.setDouble(i, s); - indexr.incr(); - } - - return r; - } - - /** - * Compute minimum value of an array - * - * @param a Array a - * @param ranges Range list - * @return Minimum value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double min(Array a, List ranges) throws InvalidRangeException { - double min = 1.7976931348623157E+308D; - double v; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - if (v < min) { - min = v; - } - } - } - if (min == 1.7976931348623157E+308D) { - return Double.NaN; - } else { - return min; - } - } - - /** - * Compute maximum value of an array - * - * @param a Array a - * @return Maximum value - */ - public static double max(Array a) { - double max = -1.797693134862316E+307D; - double v; - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - if (v > max) { - max = v; - } - } - } - if (max == -1.797693134862316E+307D) { - return Double.NaN; - } else { - return max; - } - } - - /** - * Compute maximum value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Maximum value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array max(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double s; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - s = max(a, ranges); - r.setDouble(i, s); - indexr.incr(); - } - - return r; - } - - /** - * Compute maximum value of an array - * - * @param a Array a - * @param ranges Range list - * @return Maximum value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double max(Array a, List ranges) throws InvalidRangeException { - double max = -1.797693134862316E+307D; - double v; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - if (v > max) { - max = v; - } - } - } - if (max == -1.797693134862316E+307D) { - return Double.NaN; - } else { - return max; - } - } - - /** - * Compute sum value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Sum value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array sum(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double s; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - s = sum(a, ranges); - r.setDouble(i, s); - indexr.incr(); - } - - return r; - } - - /** - * Compute sum value of an array - * - * @param a Array a - * @param ranges Range list - * @return Sum value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double sum(Array a, List ranges) throws InvalidRangeException { - double s = 0.0, v; - int n = 0; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - s += v; - n += 1; - } - } - if (n == 0) { - s = Double.NaN; - } - return s; - } - - /** - * Compute the sum arry from a list of arrays - * - * @param alist list of arrays - * @return Sum array - */ - public static Array sum(List alist) { - Array r = Array.factory(DataType.DOUBLE, alist.get(0).getShape()); - double sum, v; - int n; - for (int i = 0; i < r.getSize(); i++) { - sum = 0.0; - n = 0; - for (Array a : alist) { - v = a.getDouble(i); - if (!Double.isNaN(v)) { - sum += v; - n += 1; - } - } - if (n == 0) { - sum = Double.NaN; - } - r.setDouble(i, sum); - } - - return r; - } - - /** - * Summarize array - * - * @param a Array a - * @return Summarize value - */ - public static double sum(Array a) { - double sum = 0.0D; - double v; - int n = 0; - IndexIterator iterA = a.getIndexIterator(); - while (iterA.hasNext()) { - v = iterA.getDoubleNext(); - if (!Double.isNaN(v)) { - sum += v; - n += 1; - } - } - if (n == 0) { - return Double.NaN; - } else { - return sum; - } - } - - /** - * Summarize array skip missing value - * - * @param a Array a - * @param missingValue Missing value - * @return Summarize value - */ - public static double sum(Array a, double missingValue) { - double sum = 0.0D; - IndexIterator iterA = a.getIndexIterator(); - while (iterA.hasNext()) { - double val = iterA.getDoubleNext(); - if ((val != missingValue) && (!Double.isNaN(val))) { - sum += val; - } - } - return sum; - } - - /** - * Return the cumulative sum of the elements along a given axis. - * - * @param a Array a - * @param axis Axis - * @return Sum value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array cumsum(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(a.getDataType(), shape); - Array rr = Array.factory(a.getDataType(), dataShape); - List s; - Index indexr = r.getIndex(); - Index indexrr = rr.getIndex(); - int[] current, currentrr = indexrr.getCurrentCounter(); - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - currentrr[j] = current[idx]; - } - } - s = cumsum(a, ranges); - for (int j = 0; j < s.size(); j++) { - currentrr[axis] = j; - rr.setDouble(indexrr.set(currentrr), s.get(j)); - } - indexr.incr(); - } - r = null; - - return rr; - } - - /** - * Compute cumulative sum value of an array - * - * @param a Array a - * @param ranges Range list - * @return Sum value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static List cumsum(Array a, List ranges) throws InvalidRangeException { - double s = 0.0, v; - IndexIterator ii = a.getRangeIterator(ranges); - List r = new ArrayList<>(); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - s += v; - r.add(s); - } - - return r; - } - - /** - * Produce array - * - * @param a Array a - * @return Produce value - */ - public static double prodDouble(Array a) { - double prod = 1.0D; - double v; - IndexIterator iterA = a.getIndexIterator(); - while (iterA.hasNext()) { - v = iterA.getDoubleNext(); - if (!Double.isNaN(v)) { - prod *= v; - } - } - return prod; - } - - /** - * Average array - * - * @param a Array a - * @return Average value - */ - public static double aveDouble(Array a) { - double sum = 0.0D; - double v; - int n = 0; - IndexIterator iterA = a.getIndexIterator(); - while (iterA.hasNext()) { - v = iterA.getDoubleNext(); - if (!Double.isNaN(v)) { - sum += v; - n += 1; - } - } - if (n == 0) { - return Double.NaN; - } else { - return sum / n; - } - } - - /** - * Average array skip missing value - * - * @param a Array a - * @param missingValue Missing value - * @return Average value - */ - public static double aveDouble(Array a, double missingValue) { - double sum = 0.0D; - int n = 0; - IndexIterator iterA = a.getIndexIterator(); - while (iterA.hasNext()) { - double val = iterA.getDoubleNext(); - if ((val != missingValue) && (!Double.isNaN(val))) { - sum += val; - n += 1; - } - } - return sum / n; - } - - /** - * Get the index of the minimum value into the flattened array. - * - * @param a Array a - * @return Minimum value index - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static int argMin(Array a) throws InvalidRangeException { - double min = Double.MAX_VALUE, v; - int idx = 0; - IndexIterator iterator = a.getIndexIterator(); - int i = 0; - while (iterator.hasNext()) { - v = iterator.getDoubleNext(); - if (!Double.isNaN(v)) { - if (min > v) { - min = v; - idx = i; - } - } - i += 1; - } - return idx; - } - - /** - * Get the indices of the minimum values along an axis. - * - * @param a Array a - * @param axis Axis - * @return Indices - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array argMin(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.INT, shape); - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - idx = argMin(a.section(ranges)); - r.setInt(i, idx); - indexr.incr(); - } - - return r; - } - - /** - * Get the index of the maximum value into the flattened array. - * - * @param a Array a - * @return Maximum value index - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static int argMax(Array a) throws InvalidRangeException { - double max = Double.MIN_VALUE, v; - int idx = 0; - IndexIterator iterator = a.getIndexIterator(); - int i = 0; - while (iterator.hasNext()) { - v = iterator.getDoubleNext(); - if (!Double.isNaN(v)) { - if (max < v) { - max = v; - idx = i; - } - } - i += 1; - } - return idx; - } - - /** - * Get the indices of the maximum values along an axis. - * - * @param a Array a - * @param axis Axis - * @return Indices - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array argMax(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.INT, shape); - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - idx = argMax(a.section(ranges)); - r.setInt(i, idx); - indexr.incr(); - } - - return r; - } - - /** - * Compute mean value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Mean value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array mean(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = mean(a, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Compute mean value of an array - * - * @param a Array a - * @return Mean value - */ - public static double mean(Array a) { - double mean = 0.0, v; - int n = 0; - for (int i = 0; i < a.getSize(); i++) { - v = a.getDouble(i); - if (!Double.isNaN(v)) { - mean += v; - n += 1; - } - } - if (n > 0) { - mean = mean / n; - } else { - mean = Double.NaN; - } - return mean; - } - - /** - * Compute the arithmetic mean arry from a list of arrays - * - * @param alist list of arrays - * @return Mean array - */ - public static Array mean(List alist) { - Array r = Array.factory(DataType.DOUBLE, alist.get(0).getShape()); - double sum, v; - int n; - for (int i = 0; i < r.getSize(); i++) { - sum = 0.0; - n = 0; - for (Array a : alist) { - v = a.getDouble(i); - if (!Double.isNaN(v)) { - sum += v; - n += 1; - } - } - if (n > 0) { - sum = sum / n; - } else { - sum = Double.NaN; - } - r.setDouble(i, sum); - } - - return r; - } - - /** - * Compute mean value of an array - * - * @param a Array a - * @param ranges Range list - * @return Mean value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double mean(Array a, List ranges) throws InvalidRangeException { - double mean = 0.0, v; - int n = 0; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - mean += v; - n += 1; - } - } - if (n > 0) { - mean = mean / n; - } else { - mean = Double.NaN; - } - return mean; - } - - /** - * Compute standard deviation value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Standard deviation value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array std(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = std(a, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Compute standard deviation value of an array - * - * @param a Array a - * @param ranges Range list - * @return Standard deviation value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double std(Array a, List ranges) throws InvalidRangeException { - double mean = 0.0, v; - int n = 0; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - mean += v; - n += 1; - } - } - if (n > 0) { - mean = mean / n; - } else { - mean = Double.NaN; - } - - if (Double.isNaN(mean)) { - return Double.NaN; - } - - double sum = 0; - ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - sum += Math.pow((v - mean), 2); - } - } - sum = Math.sqrt(sum / n); - - return sum; - } - - /** - * Compute standard deviation value of an array - * - * @param a Array a - * @return Standard deviation value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double std(Array a) throws InvalidRangeException { - double mean = 0.0, v; - int n = 0; - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - mean += v; - n += 1; - } - } - if (n > 0) { - mean = mean / n; - } else { - mean = Double.NaN; - return mean; - } - - double sum = 0; - ii = a.getIndexIterator(); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - sum += Math.pow((v - mean), 2); - } - } - sum = Math.sqrt(sum / n); - - return sum; - } - - /** - * Compute variance value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Variance value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array var(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = std(a, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Compute variance value of an array - * - * @param a Array a - * @param ranges Range list - * @return Variance value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double var(Array a, List ranges) throws InvalidRangeException { - double mean = 0.0, v; - int n = 0; - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - mean += v; - n += 1; - } - } - if (n > 0) { - mean = mean / n; - } else { - mean = Double.NaN; - } - - if (Double.isNaN(mean)) { - return Double.NaN; - } - - double sum = 0; - ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getDoubleNext(); - if (!Double.isNaN(v)) { - sum += Math.pow((v - mean), 2); - } - } - sum = sum / n; - - return sum; - } - - /** - * Compute median value of an array along an axis (dimension) - * - * @param a Array a - * @param axis Axis - * @return Median value array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array median(Array a, int axis) throws InvalidRangeException { - int[] dataShape = a.getShape(); - int[] shape = new int[dataShape.length - 1]; - int idx; - for (int i = 0; i < dataShape.length; i++) { - idx = i; - if (idx == axis) { - continue; - } else if (idx > axis) { - idx -= 1; - } - shape[idx] = dataShape[i]; - } - Array r = Array.factory(DataType.DOUBLE, shape); - double mean; - Index indexr = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - } - } - mean = median(a, ranges); - r.setDouble(i, mean); - indexr.incr(); - } - - return r; - } - - /** - * Compute median value of an array - * - * @param a Array a - * @param ranges Range list - * @return Median value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static double median(Array a, List ranges) throws InvalidRangeException { - Array b = a.section(ranges); - double median = Statistics.quantile(b, 2); - return median; - } - - /** - * Compute median value of an array - * - * @param a Array a - * @return Median value - */ - public static double median(Array a) { - return Statistics.quantile(a, 2); - } - - /** - * Element-wise maximum of array elements. - * - * @param x1 Array 1 - * @param x2 Array 2 - * @return The maximum of x1 and x2, element-wise. - */ - public static Array maximum(Array x1, Array x2) { - DataType dt = commonType(x1.getDataType(), x2.getDataType()); - Array r = Array.factory(dt, x1.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setObject(i, Math.max(x1.getDouble(i), x2.getDouble(i))); - } - - return r; - } - - /** - * Element-wise maximum of array elements, ignores NaNs. - * - * @param x1 Array 1 - * @param x2 Array 2 - * @return The maximum of x1 and x2, element-wise. - */ - public static Array fmax(Array x1, Array x2) { - DataType dt = commonType(x1.getDataType(), x2.getDataType()); - Array r = Array.factory(dt, x1.getShape()); - for (int i = 0; i < r.getSize(); i++) { - if (Double.isNaN(x1.getDouble(i))) { - r.setObject(i, x2.getDouble(i)); - } else if (Double.isNaN(x2.getDouble(i))) { - r.setObject(i, x1.getDouble(i)); - } else { - r.setObject(i, Math.max(x1.getDouble(i), x2.getDouble(i))); - } - } - - return r; - } - - /** - * Element-wise minimum of array elements. - * - * @param x1 Array 1 - * @param x2 Array 2 - * @return The minimum of x1 and x2, element-wise. - */ - public static Array minimum(Array x1, Array x2) { - DataType dt = commonType(x1.getDataType(), x2.getDataType()); - Array r = Array.factory(dt, x1.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setObject(i, Math.min(x1.getDouble(i), x2.getDouble(i))); - } - - return r; - } - - /** - * Element-wise minimum of array elements, ignores NaNs. - * - * @param x1 Array 1 - * @param x2 Array 2 - * @return The minimum of x1 and x2, element-wise. - */ - public static Array fmin(Array x1, Array x2) { - DataType dt = commonType(x1.getDataType(), x2.getDataType()); - Array r = Array.factory(dt, x1.getShape()); - for (int i = 0; i < r.getSize(); i++) { - if (Double.isNaN(x1.getDouble(i))) { - r.setObject(i, x2.getDouble(i)); - } else if (Double.isNaN(x2.getDouble(i))) { - r.setObject(i, x1.getDouble(i)); - } else { - r.setObject(i, Math.min(x1.getDouble(i), x2.getDouble(i))); - } - } - - return r; - } - - /** - * Moving average function - * - * @param x The data array - * @param window Size of moving window - * @param center Set the data in center moving window - * @return Moving averaged array - */ - public static Array rolling_mean(Array x, int window, boolean center) { - int n = (int) x.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{n}); - double v, vv; - int dn; - if (center) { - int halfn = (window - 1) / 2; - int idx; - for (int i = 0; i < n; i++) { - v = 0; - dn = 0; - for (int j = 0; j < window; j++) { - if (j < halfn) { - idx = i - j; - } else if (j == halfn) { - idx = i; - } else { - idx = i + (j - halfn); - } - if (idx < 0 || idx >= n) { - break; - } - vv = x.getDouble(idx); - if (!Double.isNaN(vv)) { - v += vv; - dn += 1; - } - } - if (dn > 0) { - v = v / dn; - } else { - v = Double.NaN; - } - r.setDouble(i, v); - } - } else { - for (int i = 0; i < n; i++) { - v = 0; - dn = 0; - for (int j = 0; j < window; j++) { - if (i - j < 0) { - break; - } - vv = x.getDouble(i - j); - if (!Double.isNaN(vv)) { - v += vv; - dn += 1; - } - } - if (dn > 0) { - v = v / dn; - } else { - v = Double.NaN; - } - r.setDouble(i, v); - } - } - - return r; - } - - // - // - /** - * Set missing value to NaN - * - * @param a Array a - * @param missingv Missing value - */ - public static void missingToNaN(Array a, Number missingv) { - if (!a.getDataType().isNumeric()) { - return; - } - - IndexIterator iterA = a.getIndexIterator(); - switch (a.getDataType()) { - case INT: - case FLOAT: - while (iterA.hasNext()) { - float val = iterA.getFloatNext(); - if (val == missingv.floatValue()) { - iterA.setFloatCurrent(Float.NaN); - } - } - default: - while (iterA.hasNext()) { - double val = iterA.getDoubleNext(); - if (MIMath.doubleEquals(val, missingv.doubleValue())) { - iterA.setDoubleCurrent(Double.NaN); - } - } - } - } - - /** - * Set value - * - * @param a Array a - * @param b Array b - 0/1 data - * @param value Value - */ - public static void setValue(Array a, Array b, Number value) { - if (b.getDataType() == DataType.BOOLEAN) { - for (int i = 0; i < a.getSize(); i++) { - if (b.getBoolean(i)) { - a.setObject(i, value); - } - } - } else { - for (int i = 0; i < a.getSize(); i++) { - if (b.getInt(i) == 1) { - a.setObject(i, value); - } - } - } - } - - /** - * Set value - * - * @param a Array a - * @param b Array b - 0/1 data - * @param value Value array - */ - public static void setValue(Array a, Array b, Array value) { - if (b.getDataType() == DataType.BOOLEAN) { - for (int i = 0; i < a.getSize(); i++) { - if (b.getBoolean(i)) { - a.setObject(i, value.getObject(i)); - } - } - } else { - for (int i = 0; i < a.getSize(); i++) { - if (b.getInt(i) == 1) { - a.setObject(i, value.getObject(i)); - } - } - } - } - - /** - * As number list - * - * @param a Array a - * @return Result number list - */ - public static List asList(Array a) { - IndexIterator iterA = a.getIndexIterator(); - List r = new ArrayList<>(); - switch (a.getDataType()) { - case SHORT: - case INT: - while (iterA.hasNext()) { - r.add(iterA.getIntNext()); - } - break; - case FLOAT: - while (iterA.hasNext()) { - r.add(iterA.getFloatNext()); - } - break; - case DOUBLE: - while (iterA.hasNext()) { - r.add(iterA.getDoubleNext()); - } - break; - case BOOLEAN: - while (iterA.hasNext()) { - r.add(iterA.getBooleanNext()); - } - break; - case OBJECT: - while (iterA.hasNext()) { - r.add(iterA.getObjectNext()); - } - break; - } - return r; - } - - /** - * Get wind direction and wind speed from U/V - * - * @param u U component - * @param v V component - * @return Wind direction and wind speed - */ - public static Array[] uv2ds(Array u, Array v) { - Array windSpeed = ArrayMath.sqrt(ArrayMath.add(ArrayMath.mul(u, u), ArrayMath.mul(v, v))); - Array windDir = Array.factory(windSpeed.getDataType(), windSpeed.getShape()); - double ws, wd, U, V; - for (int i = 0; i < windSpeed.getSize(); i++) { - U = u.getDouble(i); - V = v.getDouble(i); - if (Double.isNaN(U) || Double.isNaN(V)) { - windDir.setDouble(i, Double.NaN); - continue; - } - ws = windSpeed.getDouble(i); - if (ws == 0) { - wd = 0; - } else { - wd = Math.asin(U / ws) * 180 / Math.PI; - if (U <= 0 && V < 0) { - wd = 180.0 - wd; - } else if (U > 0 && V < 0) { - wd = 180.0 - wd; - } else if (U < 0 && V > 0) { - wd = 360.0 + wd; - } - wd += 180; - if (wd >= 360) { - wd -= 360; - } - } - windDir.setDouble(i, wd); - } - - return new Array[]{windDir, windSpeed}; - } - - /** - * Get wind direction and wind speed from U/V - * - * @param u U component - * @param v V component - * @return Wind direction and wind speed - */ - public static double[] uv2ds(double u, double v) { - double ws = Math.sqrt(u * u + v * v); - double wd; - if (ws == 0) { - wd = 0; - } else { - wd = Math.asin(u / ws) * 180 / Math.PI; - if (u <= 0 && v < 0) { - wd = 180.0 - wd; - } else if (u > 0 && v < 0) { - wd = 180.0 - wd; - } else if (u < 0 && v > 0) { - wd = 360.0 + wd; - } - wd += 180; - if (wd >= 360) { - wd -= 360; - } - } - - return new double[]{wd, ws}; - } - - /** - * Get wind U/V components from wind direction and speed - * - * @param windDir Wind direction - * @param windSpeed Wind speed - * @return Wind U/V components - */ - public static Array[] ds2uv(Array windDir, Array windSpeed) { - Array U = Array.factory(DataType.DOUBLE, windDir.getShape()); - Array V = Array.factory(DataType.DOUBLE, windDir.getShape()); - double dir; - for (int i = 0; i < U.getSize(); i++) { - if (Double.isNaN(windDir.getDouble(i)) || Double.isNaN(windSpeed.getDouble(i))) { - U.setDouble(i, Double.NaN); - V.setDouble(i, Double.NaN); - } - dir = windDir.getDouble(i) + 180; - if (dir > 360) { - dir = dir - 360; - } - dir = dir * Math.PI / 180; - U.setDouble(i, windSpeed.getDouble(i) * Math.sin(dir)); - V.setDouble(i, windSpeed.getDouble(i) * Math.cos(dir)); - } - - return new Array[]{U, V}; - } - - /** - * Get wind U/V components from wind direction and speed - * - * @param windDir Wind direction - * @param windSpeed Wind speed - * @return Wind U/V components - */ - public static double[] ds2uv(double windDir, double windSpeed) { - double dir; - dir = windDir + 180; - if (dir > 360) { - dir = dir - 360; - } - dir = dir * Math.PI / 180; - double u = windSpeed * Math.sin(dir); - double v = windSpeed * Math.cos(dir); - - return new double[]{u, v}; - } - - // - // - /** - * In polygon function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param layer Polygon vector layer - * @return Result array with cell values of 1 inside polygons and -1 outside - * polygons - */ - public static Array inPolygon(Array a, List x, List y, VectorLayer layer) { - List polygons = (List) layer.getShapes(); - return ArrayMath.inPolygon(a, x, y, polygons); - } - - /** - * In polygon function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param ps Polygon shape - * @return Result array with cell values of 1 inside polygons and -1 outside - * polygons - */ - public static Array inPolygon(Array a, List x, List y, PolygonShape ps) { - List polygons = new ArrayList<>(); - polygons.add(ps); - return ArrayMath.inPolygon(a, x, y, polygons); - } - - /** - * In polygon function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param polygons PolygonShape list - * @return Result array with cell values of 1 inside polygons and -1 outside - * polygons - */ - public static Array inPolygon(Array a, List x, List y, List polygons) { - if (a.getRank() == 2) { - int xNum = x.size(); - int yNum = y.size(); - - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < yNum; i++) { - for (int j = 0; j < xNum; j++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.get(j).doubleValue(), y.get(i).doubleValue()))) { - r.setInt(i * xNum + j, 1); - } else { - r.setInt(i * xNum + j, -1); - } - } - } - - return r; - } else if (a.getRank() == 1) { - int n = x.size(); - Array r = Array.factory(DataType.INT, a.getShape()); - for (int i = 0; i < n; i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.get(i).doubleValue(), y.get(i).doubleValue()))) { - r.setInt(i, 1); - } else { - r.setInt(i, -1); - } - } - - return r; - } - - return null; - } - - /** - * In polygon function - * - * @param x X coordinates - * @param y Y coordinates - * @param polygons PolygonShape list - * @return Result boolean array - */ - public static Array inPolygon(Array x, Array y, List polygons) { - Array r = Array.factory(DataType.BOOLEAN, x.getShape()); - for (int i = 0; i < r.getSize(); i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.getDouble(i), y.getDouble(i)))) { - r.setBoolean(i, true); - } else { - r.setBoolean(i, false); - } - } - - return r; - } - - /** - * In polygon function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param x_p X coordinate of the polygon - * @param y_p Y coordinate of the polygon - * @return Result array with cell values of 1 inside polygons and -1 outside - * polygons - */ - public static Array inPolygon(Array a, List x, List y, List x_p, List y_p) { - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - for (int i = 0; i < x_p.size(); i++) { - points.add(new PointD(x_p.get(i).doubleValue(), y_p.get(i).doubleValue())); - } - ps.setPoints(points); - List shapes = new ArrayList<>(); - shapes.add(ps); - - return inPolygon(a, x, y, shapes); - } - - /** - * In polygon function - * - * @param x X coordinates - * @param y Y coordinates - * @param x_p X coordinate of the polygon - * @param y_p Y coordinate of the polygon - * @return Result boolean array - */ - public static Array inPolygon(Array x, Array y, Array x_p, Array y_p) { - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - for (int i = 0; i < x_p.getSize(); i++) { - points.add(new PointD(x_p.getDouble(i), y_p.getDouble(i))); - } - ps.setPoints(points); - List shapes = new ArrayList<>(); - shapes.add(ps); - - return inPolygon(x, y, shapes); - } - - /** - * Maskout function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param layer VectorLayer - * @param missingValue Missing value - * @return Result array with cell values of missing outside polygons - */ - public static Array maskout(Array a, List x, List y, VectorLayer layer, Number missingValue) { - List polygons = (List) layer.getShapes(); - return ArrayMath.maskout(a, x, y, polygons, missingValue); - } - - /** - * Maskout function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param polygon Polygon shape - * @param missingValue Missing value - * @return Result array with cell values of missing outside polygons - */ - public static Array maskout(Array a, List x, List y, PolygonShape polygon, Number missingValue) { - List polygons = new ArrayList<>(); - polygons.add(polygon); - return ArrayMath.maskout(a, x, y, polygons, missingValue); - } - - /** - * Maskout function - * - * @param a Array a - * @param x X Array - * @param y Y Array - * @param polygons Polygons for maskout - * @return Result array with cell values of missing outside polygons - */ - public static Array maskout(Array a, Array x, Array y, List polygons) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.getDouble(i), y.getDouble(i)))) { - r.setObject(i, a.getObject(i)); - } else { - r.setObject(i, Double.NaN); - } - } - return r; - } - - /** - * Maskin function - * - * @param a Array a - * @param x X Array - * @param y Y Array - * @param polygons Polygons for maskin - * @return Result array with cell values of missing inside polygons - */ - public static Array maskin(Array a, Array x, Array y, List polygons) { - Array r = Array.factory(a.getDataType(), a.getShape()); - for (int i = 0; i < a.getSize(); i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.getDouble(i), y.getDouble(i)))) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, a.getObject(i)); - } - } - return r; - } - - /** - * Maskout function - * - * @param a Array a - * @param x X Array - * @param y Y Array - * @param polygons Polygons for maskout - * @return Result arrays removing cells outside polygons - */ - public static Array[] maskout_Remove(Array a, Array x, Array y, List polygons) { - List rdata = new ArrayList<>(); - List rxdata = new ArrayList<>(); - List rydata = new ArrayList<>(); - for (int i = 0; i < a.getSize(); i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.getDouble(i), y.getDouble(i)))) { - rdata.add(a.getObject(i)); - rxdata.add(x.getDouble(i)); - rydata.add(y.getDouble(i)); - } - } - - int n = rdata.size(); - int[] shape = new int[1]; - shape[0] = n; - Array r = Array.factory(a.getDataType(), shape); - Array rx = Array.factory(x.getDataType(), shape); - Array ry = Array.factory(y.getDataType(), shape); - for (int i = 0; i < n; i++) { - r.setObject(i, rdata.get(i)); - rx.setDouble(i, rxdata.get(i)); - ry.setDouble(i, rydata.get(i)); - } - - return new Array[]{r, rx, ry}; - } - - /** - * Maskin function - * - * @param a Array a - * @param x X Array - * @param y Y Array - * @param polygons Polygons for maskin - * @return Result arrays removing cells inside polygons - */ - public static Array[] maskin_Remove(Array a, Array x, Array y, List polygons) { - List rdata = new ArrayList<>(); - List rxdata = new ArrayList<>(); - List rydata = new ArrayList<>(); - for (int i = 0; i < a.getSize(); i++) { - if (!GeoComputation.pointInPolygons(polygons, new PointD(x.getDouble(i), y.getDouble(i)))) { - rdata.add(a.getObject(i)); - rxdata.add(x.getDouble(i)); - rydata.add(y.getDouble(i)); - } - } - - int n = rdata.size(); - int[] shape = new int[1]; - shape[0] = n; - Array r = Array.factory(a.getDataType(), shape); - Array rx = Array.factory(x.getDataType(), shape); - Array ry = Array.factory(y.getDataType(), shape); - for (int i = 0; i < n; i++) { - r.setObject(i, rdata.get(i)); - rx.setDouble(i, rxdata.get(i)); - ry.setDouble(i, rydata.get(i)); - } - - return new Array[]{r, rx, ry}; - } - - /** - * Maskout function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param polygons PolygonShape list - * @return Result array with cell values of missing outside polygons - */ - public static Array maskout(Array a, List x, List y, List polygons) { - return maskout(a, x, y, polygons, Double.NaN); - } - - /** - * Maskout function - * - * @param a Array a - * @param x X dimension values - * @param y Y dimension values - * @param polygons PolygonShape list - * @param missingValue Missing value - * @return Result array with cell values of missing outside polygons - */ - public static Array maskout(Array a, List x, List y, List polygons, Number missingValue) { - int xNum = x.size(); - int yNum = y.size(); - - Array r = Array.factory(a.getDataType(), a.getShape()); - if (a.getRank() == 1) { - for (int i = 0; i < xNum; i++) { - if (GeoComputation.pointInPolygons(polygons, new PointD(x.get(i).doubleValue(), y.get(i).doubleValue()))) { - r.setObject(i, a.getObject(i)); - } else { - r.setObject(i, missingValue); - } - } - } else if (a.getRank() == 2) { - int idx; - for (int i = 0; i < yNum; i++) { - for (int j = 0; j < xNum; j++) { - idx = i * xNum + j; - if (GeoComputation.pointInPolygons(polygons, new PointD(x.get(j).doubleValue(), y.get(i).doubleValue()))) { - r.setObject(idx, a.getObject(idx)); - } else { - r.setObject(idx, missingValue); - } - } - } - } - - return r; - } - - /** - * Maskout function - * - * @param a Array a - * @param m Array mask - * @param missingValue Missing value - * @return Result array - */ - public static Array maskout(Array a, Array m, Number missingValue) { - Array r = Array.factory(a.getDataType(), a.getShape()); - int n = (int) a.getSize(); - for (int i = 0; i < n; i++) { - if (m.getDouble(i) < 0) { - r.setObject(i, missingValue); - } else { - r.setObject(i, a.getObject(i)); - } - } - - return r; - } - - /** - * Maskout function - * - * @param a Array a - * @param m Array mask - * @return Result array - */ - public static Array maskout(Array a, Array m) { - Array r = Array.factory(a.getDataType(), a.getShape()); - int n = (int) a.getSize(); - for (int i = 0; i < n; i++) { - if (m.getDouble(i) < 0) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, a.getObject(i)); - } - } - - return r; - } - - /** - * Maskin function - * - * @param a Array a - * @param m Array mask - * @return Result array - */ - public static Array maskin(Array a, Array m) { - Array r = Array.factory(a.getDataType(), a.getShape()); - int n = (int) a.getSize(); - for (int i = 0; i < n; i++) { - if (m.getDouble(i) < 0) { - r.setObject(i, a.getObject(i)); - } else { - r.setObject(i, Double.NaN); - } - } - - return r; - } - - // - // - /** - * Get correlation coefficient How well did the forecast values correspond - * to the observed values? Range: -1 to 1. Perfect score: 1. - * - * @param xData X data array - * @param yData Y data array - * @return Correlation coefficent - */ - public static float getR(List xData, List yData) { - int n = xData.size(); - double x_sum = 0; - double y_sum = 0; - for (int i = 0; i < n; i++) { - x_sum += xData.get(i).doubleValue(); - y_sum += yData.get(i).doubleValue(); - } - double sx_sum = 0.0; - double sy_sum = 0.0; - double xy_sum = 0.0; - for (int i = 0; i < n; i++) { - sx_sum += xData.get(i).doubleValue() * xData.get(i).doubleValue(); - sy_sum += yData.get(i).doubleValue() * yData.get(i).doubleValue(); - xy_sum += xData.get(i).doubleValue() * yData.get(i).doubleValue(); - } - - double r = (n * xy_sum - x_sum * y_sum) / (Math.sqrt(n * sx_sum - x_sum * x_sum) * Math.sqrt(n * sy_sum - y_sum * y_sum)); - return (float) r; - } - - /** - * Get correlation coefficient How well did the forecast values correspond - * to the observed values? Range: -1 to 1. Perfect score: 1. - * - * @param xData X data array - * @param yData Y data array - * @return Correlation coefficent - */ - public static float getR(Array xData, Array yData) { - int n = (int) xData.getSize(); - double x_sum = 0; - double y_sum = 0; - double sx_sum = 0.0; - double sy_sum = 0.0; - double xy_sum = 0.0; - int nn = 0; - double x, y; - for (int i = 0; i < n; i++) { - x = xData.getDouble(i); - y = yData.getDouble(i); - if (Double.isNaN(x) || Double.isNaN(y)) { - continue; - } - x_sum += x; - y_sum += y; - sx_sum += x * x; - sy_sum += y * y; - xy_sum += x * y; - nn += 1; - } - - double r = (nn * xy_sum - x_sum * y_sum) / (Math.sqrt(nn * sx_sum - x_sum * x_sum) * Math.sqrt(nn * sy_sum - y_sum * y_sum)); - return (float) r; - } - - /** - * Determine the least square trend equation - linear fitting - * - * @param xData X data array - * @param yData Y data array - * @return Result array - y intercept and slope - */ - public static double[] leastSquareTrend(List xData, List yData) { - int n = xData.size(); - double sumX = 0.0; - double sumY = 0.0; - double sumSquareX = 0.0; - double sumXY = 0.0; - for (int i = 0; i < n; i++) { - sumX += xData.get(i).doubleValue(); - sumY += yData.get(i).doubleValue(); - sumSquareX += xData.get(i).doubleValue() * xData.get(i).doubleValue(); - sumXY += xData.get(i).doubleValue() * yData.get(i).doubleValue(); - } - - double a = (sumSquareX * sumY - sumX * sumXY) / (n * sumSquareX - sumX * sumX); - double b = (n * sumXY - sumX * sumY) / (n * sumSquareX - sumX * sumX); - - return new double[]{a, b}; - } - - /** - * Linear regress - * - * @param xData X data array - * @param yData Y data array - * @return Result array - y intercept, slope and correlation coefficent - */ - public static double[] lineRegress(List xData, List yData) { - int n = xData.size(); - double x_sum = 0; - double y_sum = 0; - double sx_sum = 0.0; - double sy_sum = 0.0; - double xy_sum = 0.0; - for (int i = 0; i < n; i++) { - x_sum += xData.get(i).doubleValue(); - y_sum += yData.get(i).doubleValue(); - sx_sum += xData.get(i).doubleValue() * xData.get(i).doubleValue(); - sy_sum += yData.get(i).doubleValue() * yData.get(i).doubleValue(); - xy_sum += xData.get(i).doubleValue() * yData.get(i).doubleValue(); - } - - double r = (n * xy_sum - x_sum * y_sum) / (Math.sqrt(n * sx_sum - x_sum * x_sum) * Math.sqrt(n * sy_sum - y_sum * y_sum)); - double a = (sx_sum * y_sum - x_sum * xy_sum) / (n * sx_sum - x_sum * x_sum); - double b = (n * xy_sum - x_sum * y_sum) / (n * sx_sum - x_sum * x_sum); - - return new double[]{a, b, r}; - } - - /** - * Linear regress - * - * @param xData X data array - * @param yData Y data array - * @return Slope, intercept, correlation coefficent, two-sided p-value, the - * standard error of the estimate for the slope, valid data number - */ - public static double[] lineRegress(Array xData, Array yData) { - double x_sum = 0; - double y_sum = 0; - double sx_sum = 0.0; - double sy_sum = 0.0; - double xy_sum = 0.0; - int n = 0; - List xi = new ArrayList<>(); - List yi = new ArrayList<>(); - for (int i = 0; i < xData.getSize(); i++) { - if (Double.isNaN(xData.getDouble(i))) { - continue; - } - if (Double.isNaN(yData.getDouble(i))) { - continue; - } - xi.add(xData.getDouble(i)); - yi.add(yData.getDouble(i)); - x_sum += xData.getDouble(i); - y_sum += yData.getDouble(i); - sx_sum += xData.getDouble(i) * xData.getDouble(i); - sy_sum += yData.getDouble(i) * yData.getDouble(i); - xy_sum += xData.getDouble(i) * yData.getDouble(i); - n += 1; - } - - double r = (n * xy_sum - x_sum * y_sum) / (Math.sqrt(n * sx_sum - x_sum * x_sum) * Math.sqrt(n * sy_sum - y_sum * y_sum)); - double intercept = (sx_sum * y_sum - x_sum * xy_sum) / (n * sx_sum - x_sum * x_sum); - double slope = (n * xy_sum - x_sum * y_sum) / (n * sx_sum - x_sum * x_sum); - int df = n - 2; //degress of freedom - double TINY = 1.0e-20; - double t = r * Math.sqrt(df / ((1.0 - r + TINY) * (1.0 + r + TINY))); - //two-sided p-value for a hypothesis test whose null hypothesis is that the slope is zero - double p = studpval(t, df); - - // more statistical analysis - double xbar = x_sum / n; - double ybar = y_sum / n; - double rss = 0.0; // residual sum of squares - double ssr = 0.0; // regression sum of squares - double fit; - double xxbar = 0.0; - for (int i = 0; i < n; i++) { - fit = slope * xi.get(i) + intercept; - rss += (fit - yi.get(i)) * (fit - yi.get(i)); - ssr += (fit - ybar) * (fit - ybar); - xxbar += (xi.get(i) - xbar) * (xi.get(i) - xbar); - } - double svar = rss / df; - double svar1 = svar / xxbar; - double svar0 = svar / n + xbar * xbar * svar1; - svar0 = Math.sqrt(svar0); //the standard error of the estimate for the intercept - svar1 = Math.sqrt(svar1); //the standard error of the estimate for the slope - -// double xbar = x_sum / n; -// double ybar = y_sum / n; -// double bhat = 0.0; -// double ssqx = 0.0; -// for (int i = 0; i < n; i++) { -// bhat = bhat + (yi.get(i) - ybar) * (xi.get(i) - xbar); -// ssqx = ssqx + (xi.get(i) - xbar) * (xi.get(i) - xbar); -// } -// bhat = bhat / ssqx; -// double ahat = ybar - bhat * xbar; -// double sigmahat2 = 0.0; -// double[] ri = new double[n]; -// for (int i = 0; i < n; i++) { -// ri[i] = yi.get(i) - (ahat + bhat * xi.get(i)); -// sigmahat2 = sigmahat2 + ri[i] * ri[i]; -// } -// sigmahat2 = sigmahat2 / (n * 1.0 - 2.0); -// double seb = Math.sqrt(sigmahat2 / ssqx); -// double sigmahat = Math.sqrt((seb * seb) * ssqx); -// double sea = Math.sqrt(sigmahat * sigmahat * (1 / (n * 1.0) + xbar * xbar / ssqx)); -// double b0 = 0; -// double Tb = (bhat - b0) / seb; -// double a0 = 0; -// double Ta = (ahat - a0) / sea; -// p = studpval(Ta, n); - return new double[]{slope, intercept, r, p, svar1, n}; - } - - private static double statcom(double mq, int mi, int mj, double mb) { - double zz = 1; - double mz = zz; - int mk = mi; - while (mk <= mj) { - zz = zz * mq * mk / (mk - mb); - mz = mz + zz; - mk = mk + 2; - } - return mz; - } - - private static double studpval(double mt, int mn) { - mt = Math.abs(mt); - double mw = mt / Math.sqrt(mn); - double th = Math.atan2(mw, 1); - if (mn == 1) { - return 1.0 - th / (Math.PI / 2.0); - } - double sth = Math.sin(th); - double cth = Math.cos(th); - if (mn % 2 == 1) { - return 1.0 - (th + sth * cth * statcom(cth * cth, 2, mn - 3, -1)) / (Math.PI / 2.0); - } else { - return 1.0 - sth * statcom(cth * cth, 1, mn - 3, -1); - } - } - - /** - * Evaluate a polynomial at specific values. If p is of length N, this - * function returns the value: p[0]*x**(N-1) + p[1]*x**(N-2) + ... + - * p[N-2]*x + p[N-1] - * - * @param p array_like or poly1d object - * @param x array_like or poly1d object - * @return ndarray or poly1d - */ - public static Array polyVal(List p, Array x) { - int n = p.size(); - Array r = Array.factory(DataType.DOUBLE, x.getShape()); - for (int i = 0; i < x.getSize(); i++) { - double val = x.getDouble(i); - double rval = 0.0; - for (int j = 0; j < n; j++) { - rval += p.get(j).doubleValue() * Math.pow(val, n - j - 1); - } - r.setDouble(i, rval); - } - - return r; - } - - // - // - /** - * Performs a centered difference operation on a grid data along one - * dimension direction - * - * @param data The grid data - * @param dimIdx Direction dimension index - * @return Result grid data - */ - public static Array cdiff(Array data, int dimIdx) { - Array r = Array.factory(DataType.DOUBLE, data.getShape()); - Index index = data.getIndex(); - Index indexr = r.getIndex(); - int[] shape = data.getShape(); - int[] current, cc; - double a, b; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - if (current[dimIdx] == 0 || current[dimIdx] == shape[dimIdx] - 1) { - r.setDouble(indexr, Double.NaN); - } else { - cc = Arrays.copyOf(current, current.length); - cc[dimIdx] = cc[dimIdx] - 1; - index.set(cc); - a = data.getDouble(index); - cc[dimIdx] = cc[dimIdx] + 2; - index.set(cc); - b = data.getDouble(index); - if (Double.isNaN(a) || Double.isNaN(b)) { - r.setDouble(indexr, Double.NaN); - } else { - r.setDouble(indexr, a - b); - } - } - indexr.incr(); - } - - return r; - } - - /** - * Performs a centered difference operation on a grid data in the x or y - * direction - * - * @param data The grid data - * @param isX If is x direction - * @return Result grid data - */ - public static Array cdiff_bak(Array data, boolean isX) { - if (data.getRank() == 2) { - int xnum = data.getShape()[1]; - int ynum = data.getShape()[0]; - Array r = Array.factory(DataType.DOUBLE, data.getShape()); - for (int i = 0; i < ynum; i++) { - for (int j = 0; j < xnum; j++) { - if (i == 0 || i == ynum - 1 || j == 0 || j == xnum - 1) { - r.setDouble(i * xnum + j, Double.NaN); - } else { - double a, b; - if (isX) { - a = data.getDouble(i * xnum + j + 1); - b = data.getDouble(i * xnum + j - 1); - } else { - a = data.getDouble((i + 1) * xnum + j); - b = data.getDouble((i - 1) * xnum + j); - } - if (Double.isNaN(a) || Double.isNaN(b)) { - r.setDouble(i * xnum + j, Double.NaN); - } else { - r.setDouble(i * xnum + j, a - b); - } - } - } - } - - return r; - } else if (data.getRank() == 1) { - int n = data.getShape()[0]; - Array r = Array.factory(DataType.DOUBLE, data.getShape()); - for (int i = 0; i < n; i++) { - if (i == 0 || i == n - 1) { - r.setDouble(i, Double.NaN); - } else { - double a, b; - a = data.getDouble(i + 1); - b = data.getDouble(i - 1); - if (Double.isNaN(a) || Double.isNaN(b)) { - r.setDouble(i, Double.NaN); - } else { - r.setDouble(i, a - b); - } - } - } - - return r; - } else { - System.out.println("Data dimension number must be 1 or 2!"); - return null; - } - } - - /** - * Calculates the vertical component of the curl (ie, vorticity) - * - * @param uData U component - * @param vData V component - * @param xx X dimension value - * @param yy Y dimension value - * @return Curl - */ - public static Array hcurl(Array uData, Array vData, List xx, List yy) { - int rank = uData.getRank(); - int[] shape = uData.getShape(); - Array lonData = Array.factory(DataType.DOUBLE, shape); - Array latData = Array.factory(DataType.DOUBLE, shape); - Index index = lonData.getIndex(); - int[] current; - for (int i = 0; i < lonData.getSize(); i++) { - current = index.getCurrentCounter(); - lonData.setDouble(index, xx.get(current[rank - 1]).doubleValue()); - latData.setDouble(index, yy.get(current[rank - 2]).doubleValue()); - index.incr(); - } - - Array dv = cdiff(vData, rank - 1); - Array dx = mul(cdiff(lonData, rank - 1), Math.PI / 180); - Array du = cdiff(mul(uData, cos(mul(latData, Math.PI / 180))), rank - 2); - Array dy = mul(cdiff(latData, rank - 2), Math.PI / 180); - Array gData = div(sub(div(dv, dx), div(du, dy)), mul(cos(mul(latData, Math.PI / 180)), 6.37e6)); - - return gData; - } - - /** - * Calculates the horizontal divergence using finite differencing - * - * @param uData U component - * @param vData V component - * @param xx X dimension value - * @param yy Y dimension value - * @return Divergence - */ - public static Array hdivg(Array uData, Array vData, List xx, List yy) { - int rank = uData.getRank(); - int[] shape = uData.getShape(); - Array lonData = Array.factory(DataType.DOUBLE, shape); - Array latData = Array.factory(DataType.DOUBLE, shape); - Index index = lonData.getIndex(); - int[] current; - for (int i = 0; i < lonData.getSize(); i++) { - current = index.getCurrentCounter(); - lonData.setDouble(index, xx.get(current[rank - 1]).doubleValue()); - latData.setDouble(index, yy.get(current[rank - 2]).doubleValue()); - index.incr(); - } - - Array du = cdiff(uData, rank - 1); - Array dx = mul(cdiff(lonData, rank - 1), Math.PI / 180); - Array dv = cdiff(mul(vData, cos(mul(latData, Math.PI / 180))), rank - 2); - Array dy = mul(cdiff(latData, rank - 2), Math.PI / 180); - Array gData = div(add(div(du, dx), div(dv, dy)), mul(cos(mul(latData, Math.PI / 180)), 6.37e6)); - - return gData; - } - - /** - * Take magnitude value from U/V grid data - * - * @param uData U grid data - * @param vData V grid data - * @return Magnitude grid data - */ - public static Array magnitude(Array uData, Array vData) { - int[] shape = uData.getShape(); - int xNum = shape[1]; - int yNum = shape[0]; - int idx; - - Array r = Array.factory(DataType.DOUBLE, shape); - for (int i = 0; i < yNum; i++) { - for (int j = 0; j < xNum; j++) { - idx = i * xNum + j; - if (Double.isNaN(uData.getDouble(idx)) || Double.isNaN(vData.getDouble(idx))) { - r.setDouble(idx, Double.NaN); - } else { - r.setDouble(idx, Math.sqrt(Math.pow(uData.getDouble(idx), 2) + Math.pow(vData.getDouble(idx), 2))); - } - } - } - - return r; - } - - /** - * Calculate fahrenheit temperature from celsius temperature - * - * @param tc Celsius temperature - * @return Fahrenheit temperature - */ - public static Array tc2tf(Array tc) { - Array r = Array.factory(tc.getDataType(), tc.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, MeteoMath.tc2tf(tc.getDouble(i))); - } - - return r; - } - - /** - * Calculate celsius temperature from fahrenheit temperature - * - * @param tf Fahrenheit temperature - * @return Celsius temperature - */ - public static Array tf2tc(Array tf) { - Array r = Array.factory(tf.getDataType(), tf.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, MeteoMath.tf2tc(tf.getDouble(i))); - } - - return r; - } - - /** - * Calculate relative humidity from specific humidity - * - * @param qair Specific humidity, dimensionless (e.g. kg/kg) ratio of water - * mass / total air mass - * @param temp Temperature - degree c - * @param press Pressure - hPa (mb) - * @return Relative humidity as percent (i.e. 80%) - */ - public static Array qair2rh(Array qair, Array temp, double press) { - Array r = Array.factory(DataType.DOUBLE, qair.getShape()); - double rh; - for (int i = 0; i < r.getSize(); i++) { - rh = MeteoMath.qair2rh(qair.getDouble(i), temp.getDouble(i), press); - r.setDouble(i, rh); - } - - return r; - } - - /** - * Calculate relative humidity - * - * @param qair Specific humidity, dimensionless (e.g. kg/kg) ratio of water - * mass / total air mass - * @param temp Temperature - degree c - * @param press Pressure - hPa (mb) - * @return Relative humidity as percent (i.e. 80%) - */ - public static Array qair2rh(Array qair, Array temp, Array press) { - Array r = Array.factory(DataType.DOUBLE, qair.getShape()); - double rh; - for (int i = 0; i < r.getSize(); i++) { - rh = MeteoMath.qair2rh(qair.getDouble(i), temp.getDouble(i), press.getDouble(i)); - r.setDouble(i, rh); - } - - return r; - } - - /** - * Calculate height from pressure - * - * @param press Pressure - hPa - * @return Height - m - */ - public static Array press2Height(Array press) { - Array r = Array.factory(DataType.DOUBLE, press.getShape()); - double rh; - for (int i = 0; i < r.getSize(); i++) { - rh = MeteoMath.press2Height(press.getDouble(i)); - r.setDouble(i, rh); - } - - return r; - } - - /** - * Calculate pressure from height - * - * @param height Height - m - * @return Pressure - hPa - */ - public static Array height2Press(Array height) { - Array r = Array.factory(DataType.DOUBLE, height.getShape()); - double rh; - for (int i = 0; i < r.getSize(); i++) { - rh = MeteoMath.height2Press(height.getDouble(i)); - r.setDouble(i, rh); - } - - return r; - } - // -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java deleted file mode 100644 index c7a38c84..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java +++ /dev/null @@ -1,5546 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.bak; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.Scanner; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.meteoinfo.data.mapdata.Field; -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.geoprocess.analysis.ResampleMethods; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.io.EndianDataOutputStream; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; -import org.meteoinfo.data.StationData; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.legend.LegendScheme; -import org.meteoinfo.ndarray.Complex; -import org.meteoinfo.math.ListIndexComparator; -import org.meteoinfo.math.spatial.KDTree; -import org.meteoinfo.math.spatial.KDTree.SearchResult; -import org.meteoinfo.ndarray.util.BigDecimalUtil; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.info.ProjectionInfo; -import org.meteoinfo.projection.ProjectionUtil; -import org.meteoinfo.projection.Reproject; -import org.meteoinfo.shape.PolygonShape; -import org.meteoinfo.shape.ShapeTypes; -import org.python.core.PyComplex; -import org.meteoinfo.ndarray.Array; -import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.ndarray.Index; -import org.meteoinfo.ndarray.Index2D; -import org.meteoinfo.ndarray.IndexIterator; -import org.meteoinfo.ndarray.InvalidRangeException; -import org.meteoinfo.ndarray.Range; - -/** - * - * @author yaqiang - */ -public class ArrayUtil { - - // - /** - * Read ASCII data file to an array - * - * @param fileName File name - * @param delimiter Delimiter - * @param headerLines Headerline number - * @param dataType Data type string - * @param shape Shape - * @param readFirstCol Read first column data or not - * @return Result array - * @throws UnsupportedEncodingException - * @throws FileNotFoundException - * @throws IOException - */ - public static Array readASCIIFile(String fileName, String delimiter, int headerLines, String dataType, - List shape, boolean readFirstCol) throws UnsupportedEncodingException, FileNotFoundException, IOException { - BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); - if (headerLines > 0) { - for (int i = 0; i < headerLines; i++) { - sr.readLine(); - } - } - - DataType dt = DataType.DOUBLE; - if (dataType != null) { - if (dataType.contains("%")) { - dataType = dataType.split("%")[1]; - } - dt = ArrayUtil.toDataType(dataType); - } - - int i; - int[] ss = new int[shape.size()]; - for (i = 0; i < shape.size(); i++) { - ss[i] = shape.get(i); - } - Array a = Array.factory(dt, ss); - - String[] dataArray; - i = 0; - String line = sr.readLine(); - int sCol = 0; - if (!readFirstCol) { - sCol = 1; - } - while (line != null) { - line = line.trim(); - if (line.isEmpty()) { - line = sr.readLine(); - continue; - } - dataArray = GlobalUtil.split(line, delimiter); - for (int j = sCol; j < dataArray.length; j++) { - a.setDouble(i, Double.parseDouble(dataArray[j])); - i += 1; - if (i >= a.getSize()) { - break; - } - } - if (i >= a.getSize()) { - break; - } - - line = sr.readLine(); - } - sr.close(); - - return a; - } - - /** - * Get row number of a ASCII file - * - * @param fileName File name - * @return Row number - * @throws FileNotFoundException - */ - public static int numASCIIRow(String fileName) throws FileNotFoundException { - File f = new File(fileName); - int lineNumber; - try (Scanner fileScanner = new Scanner(f)) { - lineNumber = 0; - while (fileScanner.hasNextLine()) { - fileScanner.nextLine(); - lineNumber++; - } - } - - return lineNumber; - } - - /** - * Get row number of a ASCII file - * - * @param fileName File name - * @param delimiter - * @param headerLines - * @return Row number - * @throws FileNotFoundException - */ - public static int numASCIICol(String fileName, String delimiter, int headerLines) throws FileNotFoundException, IOException { - String[] dataArray; - try (BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) { - if (headerLines > 0) { - for (int i = 0; i < headerLines; i++) { - sr.readLine(); - } - } - String line = sr.readLine().trim(); - dataArray = GlobalUtil.split(line, delimiter); - } - - return dataArray.length; - } - - /** - * Save an array data to a binary file - * - * @param fn File path - * @param a Array - * @param byteOrder Byte order - * @param append If append to existing file - * @param sequential If write as sequential binary file - Fortran - */ - public static void saveBinFile(String fn, Array a, String byteOrder, boolean append, - boolean sequential) { - try (DataOutputStream out = new DataOutputStream(new FileOutputStream(new File(fn), append))) { - EndianDataOutputStream outs = new EndianDataOutputStream(out); - ByteBuffer bb = a.getDataAsByteBuffer(); - int n = (int) a.getSize(); - ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN; - if (byteOrder.equalsIgnoreCase("big_endian")) { - bOrder = ByteOrder.BIG_ENDIAN; - } - - if (sequential) { - if (bOrder == ByteOrder.BIG_ENDIAN) { - outs.writeIntBE(n * 4); - } else { - outs.writeIntLE(n * 4); - } - } - - if (bOrder == ByteOrder.BIG_ENDIAN) { - outs.write(bb.array()); - } else if (a.getDataType() == DataType.BYTE) { - outs.write(bb.array()); - } else { - ByteBuffer nbb = ByteBuffer.allocate(bb.array().length); - nbb.order(bOrder); - switch (a.getDataType()) { - case INT: - for (int i = 0; i < a.getSize(); i++) { - nbb.putInt(i * 4, bb.getInt()); - //nbb.putInt(a.getInt(i)); - } - break; - case FLOAT: - for (int i = 0; i < a.getSize(); i++) { - nbb.putFloat(i * 4, bb.getFloat()); - } - break; - case DOUBLE: - for (int i = 0; i < a.getSize(); i++) { - nbb.putDouble(i * 8, bb.getDouble()); - } - break; - default: - nbb.put(bb); - } - outs.write(nbb.array()); - } - - if (sequential) { - if (bOrder == ByteOrder.BIG_ENDIAN) { - outs.writeIntBE(n * 4); - } else { - outs.writeIntLE(n * 4); - } - } - - outs.close(); - } catch (FileNotFoundException ex) { - Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex); - } - } - - /** - * Save an array data to a ASCII file - * - * @param fn File path - * @param a Array - * @param colNum Column number of each line - * @param format String format - * @param delimiter Delimiter - * @throws java.io.IOException - */ - public static void saveASCIIFile(String fn, Array a, int colNum, - String format, String delimiter) throws IOException { - BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fn))); - String line = ""; - int j = 0; - for (int i = 0; i < a.getSize(); i++) { - j += 1; - if (format == null) { - line = line + a.getObject(i).toString(); - } else { - line = line + String.format(format, a.getObject(i)); - } - if (j < colNum && i < a.getSize() - 1) { - if (delimiter == null) { - line = line + " "; - } else { - line = line + delimiter; - } - } else { - sw.write(line); - sw.newLine(); - line = ""; - j = 0; - } - } - sw.flush(); - sw.close(); - } - - /** - * Read array from a binary file - * - * @param fn Binary file name - * @param dims Dimensions - * @param dataType Data type string - * @param skip Skip bytes - * @param byteOrder Byte order - * @return Result array - */ - public static Array readBinFile(String fn, List dims, String dataType, int skip, - String byteOrder) { - DataType dt = DataType.DOUBLE; - if (dataType != null) { - if (dataType.contains("%")) { - dataType = dataType.split("%")[1]; - } - dt = ArrayUtil.toDataType(dataType); - } - DataType ndt = dt; - if (dt == DataType.BYTE) { - ndt = DataType.INT; - } - - ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN; - if (byteOrder.equalsIgnoreCase("big_endian")) { - bOrder = ByteOrder.BIG_ENDIAN; - } - - int[] shape = new int[dims.size()]; - for (int i = 0; i < dims.size(); i++) { - shape[i] = dims.get(i); - } - Array r = Array.factory(ndt, shape); - IndexIterator iter = r.getIndexIterator(); - try { - DataInputStream ins = new DataInputStream(new FileInputStream(fn)); - ins.skip(skip); - byte[] bytes; - byte[] db; - int start = 0; - switch (dt) { - case BYTE: - bytes = new byte[(int) r.getSize()]; - ins.read(bytes); - for (int i = 0; i < r.getSize(); i++) { - r.setInt(i, DataConvert.byte2Int(bytes[i])); - } - break; - case SHORT: - bytes = new byte[(int) r.getSize() * 2]; - db = new byte[2]; - ins.read(bytes); - while (iter.hasNext()) { - System.arraycopy(bytes, start, db, 0, 2); - iter.setShortNext(DataConvert.bytes2Short(db, bOrder)); - start += 2; - } - break; - case INT: - bytes = new byte[(int) r.getSize() * 4]; - db = new byte[4]; - ins.read(bytes); - while (iter.hasNext()) { - System.arraycopy(bytes, start, db, 0, 4); - iter.setIntNext(DataConvert.bytes2Int(db, bOrder)); - start += 4; - } - break; - case FLOAT: - bytes = new byte[(int) r.getSize() * 4]; - db = new byte[4]; - ins.read(bytes); - while (iter.hasNext()) { - System.arraycopy(bytes, start, db, 0, 4); - iter.setFloatNext(DataConvert.bytes2Float(db, bOrder)); - start += 4; - } - break; - case DOUBLE: - bytes = new byte[(int) r.getSize() * 8]; - db = new byte[8]; - ins.read(bytes); - while (iter.hasNext()) { - System.arraycopy(bytes, start, db, 0, 8); - iter.setDoubleNext(DataConvert.bytes2Double(db, bOrder)); - start += 8; - } - break; - } - ins.close(); - } catch (FileNotFoundException ex) { - Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex); - } - - return r; - } - - // - // - - /** - * Create an array - * - * @param data Object - * @return Array - */ - public static Array array(Object data) { - if (data instanceof Number) { - DataType dt = ArrayMath.getDataType(data); - Array a = Array.factory(dt, new int[]{1}); - a.setObject(0, data); - return a; - } else if (data instanceof Array) { - return (Array) data; - } else if (data instanceof ArrayList) { - return array((List) data); - } else if (data.getClass().isArray()) { - return Array.factory(data); - } else { - return null; - } - } - - /** - * Create an array - * - * @param data Array like data - * @return - */ - public static Array array(ArrayList data) { - return array((List) data); - } - - /** - * Create an array - * - * @param data Array like data - * @return Array - */ - public static Array array(List data) { - Object d0 = data.get(0); - if (d0 instanceof Number) { - DataType dt = ArrayUtil.objectsToType(data); - Array a = Array.factory(dt, new int[]{data.size()}); - for (int i = 0; i < data.size(); i++) { - a.setObject(i, data.get(i)); - } - return a; - } else if (d0 instanceof String) { - Array a = Array.factory(DataType.STRING, new int[]{data.size()}); - for (int i = 0; i < data.size(); i++) { - a.setObject(i, data.get(i)); - } - return a; - } else if (d0 instanceof Boolean) { - Array a = Array.factory(DataType.BOOLEAN, new int[]{data.size()}); - for (int i = 0; i < data.size(); i++) { - a.setObject(i, data.get(i)); - } - return a; - } else if (d0 instanceof PyComplex) { - Array a = Array.factory(DataType.OBJECT, new int[]{data.size()}); - PyComplex d; - for (int i = 0; i < data.size(); i++) { - d = (PyComplex) data.get(i); - a.setObject(i, new Complex(d.real, d.imag)); - } - return a; - } else if (d0 instanceof List) { - int ndim = data.size(); - int len = ((List) d0).size(); - DataType dt = ArrayUtil.objectsToType((List) d0); - Array a = Array.factory(dt, new int[]{ndim, len}); - for (int i = 0; i < ndim; i++) { - List d = (List) data.get(i); - for (int j = 0; j < len; j++) { - a.setObject(i * len + j, d.get(j)); - } - } - return a; - } else { - Array a = Array.factory(DataType.OBJECT, new int[]{data.size()}); - for (int i = 0; i < data.size(); i++) { - a.setObject(i, data.get(i)); - } - return a; - } - } - - /** - * Array range - * - * @param start Start value - * @param stop Stop value - * @param step Step value - * @return Array - */ - public static Array arrayRange_bak(Number start, Number stop, final Number step) { - if (stop == null) { - stop = start; - start = 0; - } - DataType dataType = ArrayUtil.objectsToType(new Object[]{ - start, - stop, - step}); - double startv = start.doubleValue(); - double stopv = stop.doubleValue(); - double stepv = step.doubleValue(); - List data = new ArrayList<>(); - if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) { - while (startv < stopv) { - data.add(startv); - startv = BigDecimalUtil.add(startv, stepv); - } - } else { - while (startv < stopv) { - data.add(startv); - startv += stepv; - } - } - int length = data.size(); - Array a = Array.factory(dataType, new int[]{length}); - for (int i = 0; i < length; i++) { - a.setObject(i, data.get(i)); - } - return a; - } - - /** - * Array range - * - * @param start Start value - * @param stop Stop value - * @param step Step value - * @return Array - */ - public static Array arrayRange(Number start, Number stop, final Number step) { - if (stop == null) { - stop = start; - start = 0; - } - DataType dataType = ArrayUtil.objectsToType(new Object[]{ - start, - stop, - step}); - double startv = start.doubleValue(); - double stopv = stop.doubleValue(); - double stepv = step.doubleValue(); - final int length = Math.max(0, (int) Math.ceil((stopv - - startv) / stepv)); - Array a = Array.factory(dataType, new int[]{length}); - if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) { - for (int i = 0; i < length; i++) { - a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv)); - } - } else { - for (int i = 0; i < length; i++) { - a.setObject(i, i * stepv + startv); - } - } - return a; - } - - /** - * Array range - * - * @param start Start value - * @param length Length - * @param step Step value - * @return Array - */ - public static Array arrayRange1(Number start, final int length, final Number step) { - DataType dataType = ArrayUtil.objectsToType(new Object[]{ - start, - step}); - double startv = start.doubleValue(); - double stepv = step.doubleValue(); - Array a = Array.factory(dataType, new int[]{length}); - if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) { - for (int i = 0; i < length; i++) { - a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv)); - } - } else { - for (int i = 0; i < length; i++) { - a.setObject(i, i * stepv + startv); - } - } - return a; - } - - /** - * Array line space - * - * @param start Start value - * @param stop Stop value - * @param n Number value - * @param endpoint If stop is included - * @return Array - */ - public static Array lineSpace(Number start, Number stop, final int n, boolean endpoint) { - if (stop == null) { - stop = start; - start = 0; - } - double startv = start.doubleValue(); - double stopv = stop.doubleValue(); - int div = endpoint ? (n - 1) : n; - double stepv = (stopv - startv) / div; - Array a = Array.factory(DataType.DOUBLE, new int[]{n}); - double v = startv; - for (int i = 0; i < n; i++) { - a.setDouble(i, v); - v += stepv; - } - if (endpoint) { - if (a.getDouble(n - 1) != stopv) { - a.setDouble(n - 1, stopv); - } - } - - return a; - } - - /** - * Array line space - * - * @param start Start value - * @param stop Stop value - * @param n Number value - * @param endpoint If stop is included - * @return Array - */ - public static Array lineSpace_bak(Number start, Number stop, final int n, boolean endpoint) { - if (stop == null) { - stop = start; - start = 0; - } - double startv = start.doubleValue(); - double stopv = stop.doubleValue(); - double stepv = (stopv - startv) / (n - 1); - double endv = n * stepv + startv; - int nn = n; - if (endpoint) { - if (endv < stopv) { - nn += 1; - } - } else if (endv >= stopv) { - nn -= 1; - } - Array a = Array.factory(DataType.FLOAT, new int[]{nn}); - for (int i = 0; i < nn; i++) { - a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv)); - } - - return a; - } - - /** - * Get zero array - * - * @param n Number - * @return Array - */ - public static Array zeros(int n) { - Array a = Array.factory(DataType.FLOAT, new int[]{n}); - for (int i = 0; i < n; i++) { - a.setFloat(i, 0); - } - - return a; - } - - /** - * Get zero array - * - * @param shape Shape - * @param dtype Data type - * @return Array Result array - */ - public static Array zeros(List shape, String dtype) { - DataType dt = toDataType(dtype); - return zeros(shape, dt); - } - - /** - * Get zero array - * - * @param shape Shape - * @param dtype Data type - * @return Array Result array - */ - public static Array zeros(List shape, DataType dtype) { - int[] ashape = new int[shape.size()]; - for (int i = 0; i < shape.size(); i++) { - ashape[i] = shape.get(i); - } - Array a = Array.factory(dtype, ashape); - - return a; - } - - /** - * Return a new array of given shape and type, filled with fill value. - * - * @param shape Shape - * @param fillValue Fill value - * @param dtype Data type - * @return Array Result array - */ - public static Array full(List shape, Object fillValue, DataType dtype) { - int[] ashape = new int[shape.size()]; - for (int i = 0; i < shape.size(); i++) { - ashape[i] = shape.get(i); - } - if (dtype == null) { - dtype = ArrayMath.getDataType(fillValue); - } - Array a = Array.factory(dtype, ashape); - - for (int i = 0; i < a.getSize(); i++) { - a.setObject(i, fillValue); - } - - return a; - } - - /** - * Get ones array - * - * @param n Number - * @return Array Result array - */ - public static Array ones(int n) { - Array a = Array.factory(DataType.FLOAT, new int[]{n}); - for (int i = 0; i < n; i++) { - a.setFloat(i, 1); - } - - return a; - } - - /** - * Get ones array - * - * @param shape Shape - * @param dtype Data type - * @return Array Result array - */ - public static Array ones(List shape, String dtype) { - DataType dt = toDataType(dtype); - int[] ashape = new int[shape.size()]; - for (int i = 0; i < shape.size(); i++) { - ashape[i] = shape.get(i); - } - Array a = Array.factory(dt, ashape); - for (int i = 0; i < a.getSize(); i++) { - a.setObject(i, 1); - } - - return a; - } - - /** - * Return the identity array - a square array with ones on the main - * diagonal. - * - * @param n Number of rows (and columns) in n x n output. - * @param dtype Data type - * @return Identity array - */ - public static Array identity(int n, String dtype) { - DataType dt = toDataType(dtype); - int[] shape = new int[]{n, n}; - Array a = Array.factory(dt, shape); - IndexIterator index = a.getIndexIterator(); - int[] current; - while (index.hasNext()) { - index.next(); - current = index.getCurrentCounter(); - if (current[0] == current[1]) { - index.setObjectCurrent(1); - } else { - index.setObjectCurrent(0); - } - } - - return a; - } - - /** - * Return a 2-D array with ones on the diagonal and zeros elsewhere. - * - * @param n Number of rows in the output. - * @param m Number of columns in the output. - * @param k Index of the diagonal: 0 (the default) refers to the main - * diagonal, a positive value refers to an upper diagonal, and a negative - * value to a lower diagonal. - * @param dtype Data type - * @return Created array - */ - public static Array eye(int n, int m, int k, String dtype) { - DataType dt = toDataType(dtype); - int[] shape = new int[]{n, m}; - Array a = Array.factory(dt, shape); - IndexIterator index = a.getIndexIterator(); - int[] current; - int i, j; - while (index.hasNext()) { - index.next(); - current = index.getCurrentCounter(); - i = current[0]; - j = current[1] - k; - if (i == j) { - index.setObjectCurrent(1); - } else { - index.setObjectCurrent(0); - } - } - - return a; - } - - /** - * Extract a diagonal or construct a diagonal array. - * - * @param a If a is a 2-D array, return a copy of its k-th diagonal. If a is - * a 1-D array, return a 2-D array with a on the k-th diagonal. - * @param k Diagonal in question. - * @return Diagonal array - */ - public static Array diag(Array a, int k) { - if (a.getRank() == 2) { - int m = a.getShape()[0]; - int n = a.getShape()[1]; - int len = Math.min(m, n) - Math.abs(k); - Array r = Array.factory(a.getDataType(), new int[]{len}); - IndexIterator index = a.getIndexIterator(); - int[] current; - int idx = 0, i, j; - while (index.hasNext()) { - index.next(); - current = index.getCurrentCounter(); - i = current[0]; - j = current[1] - k; - if (i == j) { - r.setObject(idx, index.getObjectCurrent()); - idx += 1; - if (idx == len) { - break; - } - } - } - return r; - } else { - int m = a.getShape()[0]; - Array r = Array.factory(a.getDataType(), new int[]{m, m}); - for (int i = 0; i < m; i++) { - for (int j = 0; j < m; j++) { - if (i == j - k) { - r.setObject(i * m + j, a.getObject(i)); - } else { - r.setObject(i * m + j, 0); - } - } - } - return r; - } - } - - /** - * Repeat a value n times - * - * @param v The value - * @param n N times - * @return Repeated array - */ - public static Array repeat(Number v, int n) { - DataType dt = ArrayMath.getDataType(v); - Array r = Array.factory(dt, new int[]{n}); - for (int i = 0; i < n; i++) { - r.setObject(i, v); - } - - return r; - } - - /** - * Repeat elements of an array. - * - * @param a The value - * @param repeats The number of repetitions for each element - * @return Repeated array - */ - public static Array repeat(Array a, List repeats) { - Array r; - if (repeats.size() == 1) { - int n = repeats.get(0); - r = Array.factory(a.getDataType(), new int[]{(int) a.getSize() * n}); - for (int i = 0; i < a.getSize(); i++) { - for (int j = 0; j < n; j++) { - r.setObject(i * n + j, a.getObject(i)); - } - } - } else { - int n = 0; - for (int i = 0; i < repeats.size(); i++) { - n += repeats.get(i); - } - r = Array.factory(a.getDataType(), new int[]{n}); - int idx = 0; - for (int i = 0; i < a.getSize(); i++) { - for (int j = 0; j < repeats.get(i); j++) { - r.setObject(idx, a.getObject(i)); - idx += 1; - } - } - } - - return r; - } - - /** - * Repeat elements of an array. - * - * @param a The value - * @param repeats The number of repetitions for each element - * @param axis The axis - * @return Repeated array - */ - public static Array repeat(Array a, List repeats, int axis) { - Array r; - if (repeats.size() == 1) { - int n = repeats.get(0); - int[] shape = a.getShape(); - shape[axis] = shape[axis] * n; - r = Array.factory(a.getDataType(), shape); - Index aindex = a.getIndex(); - Index index = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - current[axis] = current[axis] / n; - aindex.set(current); - r.setObject(index, a.getObject(aindex)); - index.incr(); - } - } else { - int n = 0; - int[] rsum = new int[repeats.size()]; - for (int i = 0; i < repeats.size(); i++) { - rsum[i] = n; - n += repeats.get(i); - } - int[] shape = a.getShape(); - shape[axis] = n; - r = Array.factory(a.getDataType(), shape); - Index aindex = a.getIndex(); - Index index = r.getIndex(); - int[] current; - int idx; - for (int i = 0; i < a.getSize(); i++) { - current = aindex.getCurrentCounter(); - idx = current[axis]; - for (int j = 0; j < repeats.get(idx); j++) { - current[axis] = rsum[idx] + j; - index.set(current); - r.setObject(index, a.getObject(aindex)); - } - aindex.incr(); - } - } - - return r; - } - - /** - * Repeat a value n times - * - * @param v The value - * @param n N times - * @return Repeated array - */ - public static Array tile(Number v, int n) { - DataType dt = ArrayMath.getDataType(v); - Array r = Array.factory(dt, new int[]{n}); - for (int i = 0; i < n; i++) { - r.setObject(i, v); - } - - return r; - } - - /** - * Repeat a value n times - * - * @param v The value - * @param repeats The number of repetitions for each element - * @return Repeated array - */ - public static Array tile(Number v, List repeats) { - int[] shape = new int[repeats.size()]; - for (int i = 0; i < repeats.size(); i++) { - shape[i] = repeats.get(i); - } - DataType dt = ArrayMath.getDataType(v); - Array r = Array.factory(dt, shape); - for (int i = 0; i < r.getSize(); i++) { - r.setObject(i, v); - } - - return r; - } - - /** - * Repeat elements of an array. - * - * @param a The value - * @param repeats The number of repetitions for each element - * @return Repeated array - */ - public static Array tile(Array a, List repeats) { - if (a.getRank() > repeats.size()) { - int n = a.getRank() - repeats.size(); - for (int i = 0; i < n; i++) { - repeats.add(0, 1); - } - } else if (a.getRank() < repeats.size()) { - int[] shape = a.getShape(); - int[] nshape = new int[repeats.size()]; - int n = repeats.size() - shape.length; - for (int i = 0; i < nshape.length; i++) { - if (i < n) { - nshape[i] = 1; - } else { - nshape[i] = shape[i - n]; - } - } - a = a.reshape(nshape); - } - int[] ashape = a.getShape(); - int[] shape = a.getShape(); - for (int i = 0; i < shape.length; i++) { - shape[i] = shape[i] * repeats.get(i); - } - Array r = Array.factory(a.getDataType(), shape); - Index index = r.getIndex(); - Index aindex = a.getIndex(); - int[] current; - int idx; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - for (int j = 0; j < repeats.size(); j++) { - idx = current[j]; - idx = idx % ashape[j]; - current[j] = idx; - } - aindex.set(current); - r.setObject(index, a.getObject(aindex)); - index.incr(); - } - - return r; - } - - /** - * Get random value - * - * @return Random value - */ - public static double rand() { - Random r = new Random(); - return r.nextDouble(); - } - - /** - * Get random array - one dimension - * - * @param n Array length - * @return Result array - */ - public static Array rand(int n) { - Array r = Array.factory(DataType.DOUBLE, new int[]{n}); - Random rd = new Random(); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, rd.nextDouble()); - } - - return r; - } - - /** - * Get random array - * - * @param shape Shape - * @return Array Result array - */ - public static Array rand(List shape) { - int[] ashape = new int[shape.size()]; - for (int i = 0; i < shape.size(); i++) { - ashape[i] = shape.get(i); - } - Array a = Array.factory(DataType.DOUBLE, ashape); - Random rd = new Random(); - for (int i = 0; i < a.getSize(); i++) { - a.setDouble(i, rd.nextDouble()); - } - - return a; - } - - private static DataType objectsToType(final Object[] objects) { - if (objects.length == 0) { - return DataType.INT; - } - short new_sz, sz = -1; - DataType dataType = DataType.INT; - for (final Object o : objects) { - final DataType _type = ArrayMath.getDataType(o); - new_sz = ArrayMath.typeToNBytes(_type); - if (new_sz > sz) { - dataType = _type; - } - } - return dataType; - } - - private static DataType objectsToType(final List objects) { - if (objects.isEmpty()) { - return DataType.INT; - } - short new_sz, sz = -1; - DataType dataType = DataType.INT; - for (final Object o : objects) { - final DataType _type = ArrayMath.getDataType(o); - new_sz = ArrayMath.typeToNBytes(_type); - if (new_sz > sz) { - dataType = _type; - sz = new_sz; - } - } - return dataType; - } - - /** - * Merge data type to one data type - * - * @param dt1 Data type 1 - * @param dt2 Data type 2 - * @return Merged data type - */ - public static DataType mergeDataType(DataType dt1, DataType dt2) { - if (dt1 == DataType.OBJECT || dt2 == DataType.OBJECT) { - return DataType.OBJECT; - } else if (dt1 == DataType.STRING || dt2 == DataType.STRING) { - return DataType.STRING; - } else if (dt1 == DataType.DOUBLE || dt2 == DataType.DOUBLE) { - return DataType.DOUBLE; - } else if (dt1 == DataType.FLOAT || dt2 == DataType.FLOAT) { - return DataType.FLOAT; - } else { - return dt1; - } - } - - // - // - /** - * Array to string - * - * @param a Array a - * @return String - */ - public static String convertToString(Array a) { - StringBuilder sbuff = new StringBuilder(); - sbuff.append("array("); - int ndim = a.getRank(); - if (ndim > 1) { - sbuff.append("["); - } - int i = 0, n = 0; - IndexIterator ii = a.getIndexIterator(); - int shapeIdx = ndim - 1; - if (shapeIdx < 0) { - sbuff.append("["); - sbuff.append(ii.getObjectNext()); - sbuff.append("])"); - return sbuff.toString(); - } - - int len = a.getShape()[shapeIdx]; - Object data; - String dstr; - while (ii.hasNext()) { - if (i == 0) { - if (n > 0) { - sbuff.append("\n "); - } - sbuff.append("["); - } - data = ii.getObjectNext(); - dstr = data.toString(); - if (a.getDataType() == DataType.BOOLEAN) { - dstr = GlobalUtil.capitalize(dstr); - } - sbuff.append(dstr); - i += 1; - if (i == len) { - sbuff.append("]"); - len = a.getShape()[shapeIdx]; - i = 0; - } else { - sbuff.append(", "); - } - n += 1; - if (n > 200) { - sbuff.append("...]"); - break; - } - } - if (ndim > 1) { - sbuff.append("]"); - } - sbuff.append(")"); - return sbuff.toString(); - } - - /** - * Array to string - * - * @param a Array a - * @return String - */ - public static String toString_old(Array a) { - StringBuilder sbuff = new StringBuilder(); - sbuff.append("array("); - int ndim = a.getRank(); - if (ndim > 1) { - sbuff.append("["); - } - int i = 0; - int shapeIdx = ndim - 1; - int len = a.getShape()[shapeIdx]; - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - if (i == 0) { - sbuff.append("["); - } - Object data = ii.getObjectNext(); - sbuff.append(data); - i += 1; - if (i == len) { - sbuff.append("]"); - len = a.getShape()[shapeIdx]; - i = 0; - } else { - sbuff.append(", "); - } - } - if (ndim > 1) { - sbuff.append("]"); - } - return sbuff.toString(); - } - - /** - * Get array list from StationData - * - * @param stdata StationData - * @return Array list - */ - public static List getArraysFromStationData(StationData stdata) { - int n = stdata.getStNum(); - int[] shape = new int[1]; - shape[0] = n; - Array lon = Array.factory(DataType.FLOAT, shape); - Array lat = Array.factory(DataType.FLOAT, shape); - Array value = Array.factory(DataType.FLOAT, shape); - double v; - for (int i = 0; i < n; i++) { - lon.setFloat(i, (float) stdata.getX(i)); - lat.setFloat(i, (float) stdata.getY(i)); - v = stdata.getValue(i); - if (v == stdata.missingValue) { - v = Double.NaN; - } - value.setFloat(i, (float) v); - } - - List r = new ArrayList<>(); - r.add(lon); - r.add(lat); - r.add(value); - return r; - } - - // - // - /** - * Get data type string - * - * @param dt The data type - * @return Data type string - */ - public static String dataTypeString(DataType dt) { - String str = "string"; - switch (dt) { - case BYTE: - str = "byte"; - break; - case SHORT: - str = "short"; - break; - case INT: - str = "int"; - break; - case FLOAT: - str = "float"; - break; - case DOUBLE: - str = "double"; - break; - } - - return str; - } - - /** - * To data type - ucar.ma2 - * - * @param dt Data type string - * @return Data type - */ - public static DataType toDataType(String dt) { - if (dt.contains("%")) { - dt = dt.split("%")[1]; - } - switch (dt.toLowerCase()) { - case "c": - case "s": - case "string": - return DataType.STRING; - case "b": - case "byte": - return DataType.BYTE; - case "short": - return DataType.SHORT; - case "i": - case "int": - return DataType.INT; - case "f": - case "float": - return DataType.FLOAT; - case "d": - case "double": - return DataType.DOUBLE; - case "bool": - case "boolean": - return DataType.BOOLEAN; - default: - return DataType.OBJECT; - } - } - - /** - * Convert array to integer type - * - * @param a Array a - * @return Result array - */ - public static Array toInteger(Array a) { - Array r = Array.factory(DataType.INT, a.getShape()); - if (a.getDataType().isNumeric()) { - for (int i = 0; i < r.getSize(); i++) { - r.setInt(i, a.getInt(i)); - } - } else { - if (a.getDataType() == DataType.BOOLEAN) { - for (int i = 0; i < r.getSize(); i++) { - r.setInt(i, a.getBoolean(i) ? 1 : 0); - } - } else { - for (int i = 0; i < r.getSize(); i++) { - r.setInt(i, Integer.valueOf(a.getObject(i).toString())); - } - } - } - - return r; - } - - /** - * Convert array to float type - * - * @param a Array a - * @return Result array - */ - public static Array toFloat(Array a) { - Array r = Array.factory(DataType.FLOAT, a.getShape()); - if (a.getDataType().isNumeric()) { - for (int i = 0; i < r.getSize(); i++) { - r.setFloat(i, a.getFloat(i)); - } - } else { - for (int i = 0; i < r.getSize(); i++) { - r.setFloat(i, Float.valueOf(a.getObject(i).toString())); - } - } - - return r; - } - - /** - * Convert array to double type - * - * @param a Array a - * @return Result array - */ - public static Array toDouble(Array a) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - if (a.getDataType().isNumeric()) { - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, a.getDouble(i)); - } - } else { - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, Double.valueOf(a.getObject(i).toString())); - } - } - - return r; - } - - /** - * Convert array to boolean type - * - * @param a Array a - * @return Result array - */ - public static Array toBoolean(Array a) { - Array r = Array.factory(DataType.BOOLEAN, a.getShape()); - for (int i = 0; i < r.getSize(); i++) { - r.setBoolean(i, a.getDouble(i) != 0); - } - - return r; - } - - /** - * Concatenate arrays to one array along a axis - * - * @param arrays Array list - * @param axis The axis - * @return Concatenated array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array concatenate(List arrays, Integer axis) throws InvalidRangeException { - int ndim = arrays.get(0).getRank(); - if (axis == -1) { - axis = ndim - 1; - } - int len = 0; - int[] lens = new int[arrays.size()]; - int i = 0; - List indexList = new ArrayList<>(); - for (Array a : arrays) { - len += a.getShape()[axis]; - lens[i] = len; - indexList.add(Index.factory(a.getShape())); - i += 1; - } - int[] shape = arrays.get(0).getShape(); - shape[axis] = len; - Array r = Array.factory(arrays.get(0).getDataType(), shape); - int[] current; - IndexIterator ii = r.getIndexIterator(); - Index index; - int idx = 0; - while (ii.hasNext()) { - ii.next(); - current = ii.getCurrentCounter(); - for (i = 0; i < lens.length; i++) { - if (current[axis] < lens[i]) { - idx = i; - break; - } - } - if (idx > 0) { - current[axis] = current[axis] - lens[idx - 1]; - } - index = indexList.get(idx); - index.set(current); - ii.setObjectCurrent(arrays.get(idx).getObject(index)); - } - - return r; - } - - /** - * Concatenate two arrays to one array along a axis - * - * @param a Array a - * @param b Array b - * @param axis The axis - * @return Concatenated array - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array concatenate(Array a, Array b, Integer axis) throws InvalidRangeException { - int n = a.getRank(); - int[] shape = a.getShape(); - if (axis == -1) { - axis = n - 1; - } - int nn = shape[axis]; - int[] bshape = b.getShape(); - int[] nshape = new int[n]; - for (int i = 0; i < n; i++) { - if (i == axis) { - nshape[i] = shape[i] + bshape[i]; - } else { - nshape[i] = shape[i]; - } - } - Array r = Array.factory(a.getDataType(), nshape); - Index indexr = r.getIndex(); - Index indexa = a.getIndex(); - Index indexb = b.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - if (current[axis] < nn) { - indexa.set(current); - r.setObject(indexr, a.getObject(indexa)); - } else { - current[axis] = current[axis - nn]; - indexb.set(current); - r.setObject(indexr, b.getObject(indexb)); - } - indexr.incr(); - } - - return r; - } - - /** - * Sort array along an axis - * - * @param a Array a - * @param axis The axis - * @return Sorted array - * @throws InvalidRangeException - */ - public static Array sort(Array a, Integer axis) throws InvalidRangeException { - int n = a.getRank(); - int[] shape = a.getShape(); - if (axis == null) { - int[] nshape = new int[1]; - nshape[0] = (int) a.getSize(); - Array r = Array.factory(a.getDataType(), nshape); - List tlist = new ArrayList(); - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - tlist.add(ii.getObjectNext()); - } - Collections.sort(tlist); - for (int i = 0; i < r.getSize(); i++) { - r.setObject(i, tlist.get(i)); - } - - return r; - } else { - if (axis == -1) { - axis = n - 1; - } - int nn = shape[axis]; - Array r = Array.factory(a.getDataType(), shape); - Index indexr = r.getIndex(); - int[] current; - List ranges = new ArrayList<>(); - for (int i = 0; i < n; i++) { - if (i == axis) { - ranges.add(new Range(0, 0, 1)); - } else { - ranges.add(new Range(0, shape[i] - 1, 1)); - } - } - IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator(); - while (rii.hasNext()) { - rii.next(); - current = rii.getCurrentCounter(); - ranges = new ArrayList<>(); - for (int j = 0; j < n; j++) { - if (j == axis) { - ranges.add(new Range(0, shape[j] - 1, 1)); - } else { - ranges.add(new Range(current[j], current[j], 1)); - } - } - List tlist = new ArrayList(); - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - tlist.add(ii.getObjectNext()); - } - Collections.sort(tlist); - for (int j = 0; j < nn; j++) { - indexr.set(current); - r.setObject(indexr, tlist.get(j)); - current[axis] = current[axis] + 1; - } - } - - return r; - } - } - - /** - * Get sorted array index along an axis - * - * @param a Array a - * @param axis The axis - * @return Index of sorted array - * @throws InvalidRangeException - */ - public static Array argSort(Array a, Integer axis) throws InvalidRangeException { - int n = a.getRank(); - int[] shape = a.getShape(); - Object v; - if (axis == null) { - int[] nshape = new int[1]; - nshape[0] = (int) a.getSize(); - Array r = Array.factory(DataType.INT, nshape); - List stlist = new ArrayList(); - IndexIterator ii = a.getIndexIterator(); - while (ii.hasNext()) { - v = ii.getObjectNext(); - stlist.add(v); - } - //Collections.sort(stlist); - ListIndexComparator comparator = new ListIndexComparator(stlist); - Integer[] indexes = comparator.createIndexArray(); - Arrays.sort(indexes, comparator); - for (int i = 0; i < r.getSize(); i++) { - r.setInt(i, indexes[i]); - } - - return r; - } else { - if (axis == -1) { - axis = n - 1; - } - int nn = shape[axis]; - Array r = Array.factory(DataType.INT, shape); - Index indexr = r.getIndex(); - int[] current; - List ranges = new ArrayList<>(); - for (int i = 0; i < n; i++) { - if (i == axis) { - ranges.add(new Range(0, 0, 1)); - } else { - ranges.add(new Range(0, shape[i] - 1, 1)); - } - } - IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator(); - while (rii.hasNext()) { - rii.next(); - current = rii.getCurrentCounter(); - ranges = new ArrayList<>(); - for (int j = 0; j < n; j++) { - if (j == axis) { - ranges.add(new Range(0, shape[j] - 1, 1)); - } else { - ranges.add(new Range(current[j], current[j], 1)); - } - } - List stlist = new ArrayList(); - IndexIterator ii = a.getRangeIterator(ranges); - while (ii.hasNext()) { - v = ii.getObjectNext(); - stlist.add(v); - } - //Collections.sort(stlist); - ListIndexComparator comparator = new ListIndexComparator(stlist); - Integer[] indexes = comparator.createIndexArray(); - Arrays.sort(indexes, comparator); - for (int j = 0; j < nn; j++) { - indexr.set(current); - r.setObject(indexr, indexes[j]); - current[axis] = current[axis] + 1; - } - } - - return r; - } - } - - /** - * Convert array to N-Dimension double Java array - * - * @param a Array a - * @param dtype Data type string - * @return N-D Java array - */ - public static Object copyToNDJavaArray(Array a, String dtype) { - if (dtype == null) { - return copyToNDJavaArray(a); - } - - switch (dtype.toLowerCase()) { - case "double": - return copyToNDJavaArray_Double(a); - case "long": - return copyToNDJavaArray_Long(a); - default: - return copyToNDJavaArray(a); - } - } - - /** - * Convert array to N-Dimension double Java array - * - * @param a Array a - * @return N-D Java array - */ - public static Object copyToNDJavaArray(Array a) { - Object javaArray; - try { - javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape()); - } catch (IllegalArgumentException | NegativeArraySizeException e) { - throw new IllegalArgumentException(e); - } - IndexIterator iter = a.getIndexIterator(); - reflectArrayCopyOut(javaArray, a, iter); - - return javaArray; - } - - /** - * Convert array to N-Dimension double Java array - * - * @param a Array a - * @return N-D Java array - */ - public static Object copyToNDJavaArray_Long(Array a) { - Object javaArray; - try { - javaArray = java.lang.reflect.Array.newInstance(Long.TYPE, a.getShape()); - } catch (IllegalArgumentException | NegativeArraySizeException e) { - throw new IllegalArgumentException(e); - } - IndexIterator iter = a.getIndexIterator(); - reflectArrayCopyOut(javaArray, a, iter); - - return javaArray; - } - - /** - * Convert array to N-Dimension double Java array - * - * @param a Array a - * @return N-D Java array - */ - public static Object copyToNDJavaArray_Double(Array a) { - Object javaArray; - try { - javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape()); - } catch (IllegalArgumentException | NegativeArraySizeException e) { - throw new IllegalArgumentException(e); - } - IndexIterator iter = a.getIndexIterator(); - reflectArrayCopyOut(javaArray, a, iter); - - return javaArray; - } - - private static void reflectArrayCopyOut(Object jArray, Array aa, IndexIterator aaIter) { - Class cType = jArray.getClass().getComponentType(); - - if (!cType.isArray()) { - if (cType == long.class) { - copyTo1DJavaArray_Long(aaIter, jArray); - } else { - copyTo1DJavaArray(aaIter, jArray); - } - } else { - for (int i = 0; i < java.lang.reflect.Array.getLength(jArray); i++) { - reflectArrayCopyOut(java.lang.reflect.Array.get(jArray, i), aa, aaIter); - } - } - } - - protected static void copyTo1DJavaArray(IndexIterator iter, Object javaArray) { - double[] ja = (double[]) javaArray; - for (int i = 0; i < ja.length; i++) { - ja[i] = iter.getDoubleNext(); - } - } - - protected static void copyTo1DJavaArray_Long(IndexIterator iter, Object javaArray) { - long[] ja = (long[]) javaArray; - for (int i = 0; i < ja.length; i++) { - ja[i] = iter.getLongNext(); - } - } - - /** - * Return a new array with sub-arrays along an axis deleted - * - * @param a Input array - * @param idx Index - * @param axis The axis - * @return - */ - public static Array delete(Array a, int idx, int axis) { - int[] shape = a.getShape(); - int n = shape.length; - int[] nshape = new int[n]; - for (int i = 0; i < n; i++) { - if (i == axis) { - nshape[i] = shape[i] - 1; - } else { - nshape[i] = shape[i]; - } - } - Array r = Array.factory(a.getDataType(), nshape); - IndexIterator ii = a.getIndexIterator(); - int[] current; - int i = 0; - while (ii.hasNext()) { - ii.next(); - current = ii.getCurrentCounter(); - if (current[axis] != idx) { - r.setObject(i, ii.getObjectCurrent()); - i += 1; - } - } - - return r; - } - - /** - * Return a new array with sub-arrays along an axis deleted - * - * @param a Input array - * @param idx Index - * @param axis The axis - * @return - */ - public static Array delete(Array a, List idx, int axis) { - int[] shape = a.getShape(); - int n = shape.length; - int[] nshape = new int[n]; - for (int i = 0; i < n; i++) { - if (i == axis) { - nshape[i] = shape[i] - idx.size(); - } else { - nshape[i] = shape[i]; - } - } - Array r = Array.factory(a.getDataType(), nshape); - IndexIterator ii = a.getIndexIterator(); - int[] current; - int i = 0; - while (ii.hasNext()) { - ii.next(); - current = ii.getCurrentCounter(); - if (!idx.contains(current[axis])) { - r.setObject(i, ii.getObjectCurrent()); - i += 1; - } - } - - return r; - } - - // - // - /** - * Histogram x/y array - * - * @param a Data array - * @param nbins bin number - * @return X/Y arrays - */ - public static List histogram(Array a, int nbins) { - double min = ArrayMath.getMinimum(a); - double max = ArrayMath.getMaximum(a); - double interval = BigDecimalUtil.div(BigDecimalUtil.sub(max, min), nbins); - double[] bins = new double[nbins + 1]; - for (int i = 0; i < nbins + 1; i++) { - bins[i] = min; - min = BigDecimalUtil.add(min, interval); - } - Array ba = Array.factory(DataType.DOUBLE, new int[]{bins.length}, bins); - return histogram(a, ba); - } - - /** - * Histogram x/y array - * - * @param a Data array - * @param bins bin edges - * @return X/Y arrays - */ - public static List histogram(Array a, Array bins) { - int n = (int) bins.getSize(); - Array hist = Array.factory(DataType.INT, new int[]{n - 1}); - double v; - for (int i = 0; i < a.getSize(); i++) { - v = a.getDouble(i); - for (int j = 0; j < n - 1; j++) { - if (j == n - 2) { - if (v >= bins.getDouble(j) && v <= bins.getDouble(j + 1)) { - hist.setInt(j, hist.getInt(j) + 1); - break; - } - } else if (v >= bins.getDouble(j) && v < bins.getDouble(j + 1)) { - hist.setInt(j, hist.getInt(j) + 1); - break; - } - } - } - - List r = new ArrayList<>(); - r.add(hist); - r.add(bins); - - return r; - } - - /** - * Histogram x/y array - * - * @param a Data array - * @param bins bin edges - * @return X/Y arrays - */ - public static List histogram(Array a, double[] bins) { - int n = bins.length; - double delta = bins[1] - bins[0]; - int[] count = new int[n + 1]; - double v; - for (int i = 0; i < a.getSize(); i++) { - v = a.getDouble(i); - if (v < bins[0]) { - count[0] += 1; - } else if (v > bins[n - 1]) { - count[n] += 1; - } else { - for (int j = 0; j < n - 1; j++) { - if (v > bins[j] && v < bins[j + 1]) { - count[j + 1] += 1; - break; - } - } - } - } - - Array x = Array.factory(DataType.DOUBLE, new int[]{count.length + 1}); - Array y = Array.factory(DataType.INT, new int[]{count.length}); - for (int i = 0; i < count.length; i++) { - y.setInt(i, count[i]); - if (i == 0) { - x.setDouble(0, bins[0] - delta); - x.setDouble(1, bins[0]); - } else if (i == count.length - 1) { - x.setDouble(i + 1, bins[i - 1] + delta); - } else { - x.setDouble(i + 1, bins[i]); - } - } - List r = new ArrayList<>(); - r.add(y); - r.add(x); - - return r; - } - - // - // - /** - * Broadcast array to a new shape - * - * @param a Array a - * @param shape Shape - * @return Result array - */ - public static Array broadcast(Array a, int[] shape) { - int[] bshape = a.getShape(); - if (bshape.length > shape.length) { - return null; - } - - if (bshape.length < shape.length) { - int miss = shape.length - a.getRank(); - bshape = new int[shape.length]; - for (int i = 0; i < shape.length; i++) { - if (i < miss) { - bshape[i] = 1; - } else { - bshape[i] = a.getShape()[i - miss]; - } - } - a = a.reshape(bshape); - } - - //Check - boolean pass = true; - for (int i = 0; i < shape.length; i++) { - if (shape[i] != bshape[i] && bshape[i] != 1) { - pass = false; - break; - } - } - if (!pass) { - return null; - } - - //Broadcast - Index aindex = a.getIndex(); - Array r = Array.factory(a.getDataType(), shape); - Index index = r.getIndex(); - int[] current; - for (int i = 0; i < r.getSize(); i++) { - current = index.getCurrentCounter(); - for (int j = 0; j < shape.length; j++) { - if (bshape[j] == 1) { - aindex.setDim(j, 0); - } else { - aindex.setDim(j, current[j]); - } - } - r.setObject(index, a.getObject(aindex)); - index.incr(); - } - - return r; - } - - /** - * Broadcast array to a new shape - * - * @param a Array a - * @param shape Shape - * @return Result array - */ - public static Array broadcast(Array a, List shape) { - int[] nshape = new int[shape.size()]; - for (int i = 0; i < shape.size(); i++) { - nshape[i] = shape.get(i); - } - return broadcast(a, nshape); - } - - /** - * Mesh grid - * - * @param x X array - vector - * @param y Y array - vector - * @return Result arrays - matrix - */ - public static Array[] meshgrid(Array x, Array y) { - int xn = (int) x.getSize(); - int yn = (int) y.getSize(); - int[] shape = new int[]{yn, xn}; - Array rx = Array.factory(x.getDataType(), shape); - Array ry = Array.factory(y.getDataType(), shape); - for (int i = 0; i < yn; i++) { - for (int j = 0; j < xn; j++) { - rx.setObject(i * xn + j, x.getObject(j)); - ry.setObject(i * xn + j, y.getObject(i)); - } - } - - return new Array[]{rx, ry}; - } - - /** - * Mesh grid - * - * @param xs X arrays - * @return Result arrays - matrix - */ - public static Array[] meshgrid(Array... xs) { - int n = xs.length; - int[] shape = new int[n]; - int i = 0; - Array x; - for (i = 0; i < n; i++) { - x = xs[i]; - shape[n - i - 1] = (int) x.getSize(); - } - - Array[] rs = new Array[n]; - Array r; - int idx; - for (int s = 0; s < n; s++) { - x = xs[s]; - r = Array.factory(xs[s].getDataType(), shape); - Index index = r.getIndex(); - for (i = 0; i < r.getSize(); i++) { - idx = index.getCurrentCounter()[n - s - 1]; - r.setObject(index, x.getObject(idx)); - index.incr(); - } - rs[s] = r; - } - - return rs; - } - - /** - * Create mesh polygon layer - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param ls Legend scheme - * @param lonlim Longiutde limitation - to avoid the polygon cross -180/180 - * @return Mesh polygon layer - */ - public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls, double lonlim) { - VectorLayer layer = new VectorLayer(ShapeTypes.Polygon); - String fieldName = "Data"; - Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE); - layer.editAddField(aDC); - - int[] shape = x_s.getShape(); - int colNum = shape[1]; - int rowNum = shape[0]; - double x1, x2, x3, x4; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - x1 = x_s.getDouble(i * colNum + j); - x2 = x_s.getDouble(i * colNum + j + 1); - x3 = x_s.getDouble((i + 1) * colNum + j); - x4 = x_s.getDouble((i + 1) * colNum + j + 1); - if (lonlim > 0) { - if (Math.abs(x2 - x4) > lonlim || Math.abs(x1 - x4) > lonlim - || Math.abs(x3 - x4) > lonlim || Math.abs(x1 - x2) > lonlim - || Math.abs(x2 - x3) > lonlim) { - continue; - } - } - - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(x1, y_s.getDouble(i * colNum + j))); - points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j))); - points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1))); - points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1))); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - ps.lowValue = a.getDouble(i * colNum + j); - ps.highValue = ps.lowValue; - int shapeNum = layer.getShapeNum(); - try { - if (layer.editInsertShape(ps, shapeNum)) { - layer.editCellValue(fieldName, shapeNum, ps.lowValue); - } - } catch (Exception ex) { - - } - } - } - layer.setLayerName("Mesh_Layer"); - ls.setFieldName(fieldName); - layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon)); - - return layer; - } - - /** - * Create mesh polygon layer - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param ls Legend scheme - * @return Mesh polygon layer - */ - public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls) { - VectorLayer layer = new VectorLayer(ShapeTypes.Polygon); - String fieldName = "Data"; - Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE); - layer.editAddField(aDC); - - int[] shape = x_s.getShape(); - int colNum = shape[1]; - int rowNum = shape[0]; - double x1, x2, x3, x4; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - x1 = x_s.getDouble(i * colNum + j); - x2 = x_s.getDouble(i * colNum + j + 1); - x3 = x_s.getDouble((i + 1) * colNum + j); - x4 = x_s.getDouble((i + 1) * colNum + j + 1); - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(x1, y_s.getDouble(i * colNum + j))); - points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j))); - points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1))); - points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1))); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - ps.lowValue = a.getDouble(i * colNum + j); - ps.highValue = ps.lowValue; - int shapeNum = layer.getShapeNum(); - try { - if (layer.editInsertShape(ps, shapeNum)) { - layer.editCellValue(fieldName, shapeNum, ps.lowValue); - } - } catch (Exception ex) { - - } - } - } - layer.setLayerName("Mesh_Layer"); - ls.setFieldName(fieldName); - layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon)); - - return layer; - } - - /** - * Smooth with 5 points - * - * @param a Array - * @param rowNum Row number - * @param colNum Column number - * @param unDefData Missing value - * @return Result array - */ - public static Array smooth5(Array a, int rowNum, int colNum, double unDefData) { - Array r = Array.factory(a.getDataType(), a.getShape()); - double s = 0.5; - if (Double.isNaN(unDefData)) { - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) { - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j)); - } else { - if (Double.isNaN(a.getDouble(i * colNum + j)) || Double.isNaN(a.getDouble((i + 1) * colNum + j)) || Double.isNaN(a.getDouble((i - 1) * colNum + j)) - || Double.isNaN(a.getDouble(i * colNum + j + 1)) || Double.isNaN(a.getDouble(i * colNum + j - 1))) { - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j)); - continue; - } - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1) - + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j))); - } - } - } - } else { - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) { - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j)); - } else { - if (a.getDouble(i * colNum + j) == unDefData || a.getDouble((i + 1) * colNum + j) == unDefData || a.getDouble((i - 1) * colNum + j) - == unDefData || a.getDouble(i * colNum + j + 1) == unDefData || a.getDouble(i * colNum + j - 1) == unDefData) { - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j)); - continue; - } - r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1) - + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j))); - } - } - } - } - - return r; - } - - /** - * Smooth with 5 points - * - * @param a Array - * @return Result array - */ - public static Array smooth5(Array a) { - int[] shape = a.getShape(); - int colNum = shape[1]; - int rowNum = shape[0]; - Array r = Array.factory(a.getDataType(), shape); - Index2D index = new Index2D(shape); - double v, w; - double sum, wsum; - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - sum = 0; - wsum = 0; - for (int ii = i - 1; ii <= i + 1; ii++) { - if (ii < 0 || ii >= rowNum) { - continue; - } - for (int jj = j - 1; jj <= j + 1; jj++) { - if (jj < 0 || jj >= colNum) { - continue; - } - if ((ii == i - 1 || ii == i + 1) && jj != j) { - continue; - } - v = a.getDouble(index.set(ii, jj)); - if (!Double.isNaN(v)) { - if (ii == i && jj == j) { - w = 1; - } else { - w = 0.5; - } - sum += v * w; - wsum += w; - } - } - } - index.set(i, j); - if (wsum > 0) { - r.setDouble(index, sum / wsum); - } else { - r.setDouble(index, Double.NaN); - } - } - } - - return r; - } - - /** - * Smooth with 9 points - * - * @param a Array - * @return Result array - */ - public static Array smooth9(Array a) { - int[] shape = a.getShape(); - int colNum = shape[1]; - int rowNum = shape[0]; - Array r = Array.factory(a.getDataType(), shape); - Index2D index = new Index2D(shape); - double v, w; - double sum, wsum; - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - sum = 0; - wsum = 0; - for (int ii = i - 1; ii <= i + 1; ii++) { - if (ii < 0 || ii >= rowNum) { - continue; - } - for (int jj = j - 1; jj <= j + 1; jj++) { - if (jj < 0 || jj >= colNum) { - continue; - } - v = a.getDouble(index.set(ii, jj)); - if (!Double.isNaN(v)) { - if (ii == i && jj == j) { - w = 1; - } else { - if (ii == i || jj == j) { - w = 0.5; - } else { - w = 0.3; - } - } - sum += v * w; - wsum += w; - } - } - } - index.set(i, j); - if (wsum > 0) { - r.setDouble(index, sum / wsum); - } else { - r.setDouble(index, Double.NaN); - } - } - } - - return r; - } - - /** - * Interpolation with IDW radius method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X grid X array - * @param Y grid Y array - * @param neededPointNum needed at least point number - * @param radius search radius - * @return interpolated grid data - */ - public static Array interpolation_IDW_Radius(List x_s, List y_s, Array a, - List X, List Y, int neededPointNum, double radius) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - int i, j; - double w, gx, gy, v; - boolean match; - - //Construct K-D tree - int n = 0; - KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2); - for (i = 0; i < pNum; i++) { - if (!Double.isNaN(a.getDouble(i))) { - kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i)); - n += 1; - } - } - - //---- Do interpolation - for (i = 0; i < rowNum; i++) { - gy = Y.get(i).doubleValue(); - for (j = 0; j < colNum; j++) { - gx = X.get(j).doubleValue(); - List> srs = kdTree.ballSearch_distance(new double[]{gx, gy}, radius * radius); - if (srs == null || srs.size() < neededPointNum) { - r.setDouble(i * colNum + j, Double.NaN); - } else { - double v_sum = 0.0; - double weight_sum = 0.0; - match = false; - for (SearchResult sr : srs) { - v = (double) sr.payload; - if (sr.distance == 0) { - r.setDouble(i * colNum + j, v); - match = true; - break; - } else { - w = 1. / sr.distance; - weight_sum += w; - v_sum += v * w; - } - } - if (!match) { - r.setDouble(i * colNum + j, v_sum / weight_sum); - } - } - } - } - - return r; - } - - /** - * Interpolation with IDW radius method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X grid X array - * @param Y grid Y array - * @param NeededPointNum needed at least point number - * @param radius search radius - * @return interpolated grid data - */ - public static Array interpolation_IDW_Radius_bak(List x_s, List y_s, Array a, - List X, List Y, int NeededPointNum, double radius) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - //double[][] GCoords = new double[rowNum][colNum]; - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - int i, j, p, vNum; - double w, SV, SW; - boolean ifPointGrid; - double x, y, v; - - //---- Do interpolation - for (i = 0; i < rowNum; i++) { - for (j = 0; j < colNum; j++) { - r.setDouble(i * colNum + j, Double.NaN); - ifPointGrid = false; - SV = 0; - SW = 0; - vNum = 0; - for (p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - continue; - } - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < X.get(j).doubleValue() - radius || x > X.get(j).doubleValue() + radius || y < Y.get(i).doubleValue() - radius - || y > Y.get(i).doubleValue() + radius) { - continue; - } - - if (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2) == 0) { - r.setDouble(i * colNum + j, v); - ifPointGrid = true; - break; - } else if (Math.sqrt(Math.pow(X.get(j).doubleValue() - x, 2) - + Math.pow(Y.get(i).doubleValue() - y, 2)) <= radius) { - w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2)); - SW = SW + w; - SV = SV + v * w; - vNum += 1; - } - } - - if (!ifPointGrid) { - if (vNum >= NeededPointNum) { - r.setDouble(i * colNum + j, SV / SW); - } - } - } - } - - //---- Smooth with 5 points - r = smooth5(r, rowNum, colNum, Double.NaN); - - return r; - } - - /** - * Interpolation with IDW neighbor method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X grid X array - * @param Y grid Y array - * @param points Number of points used for interpolation - * @return interpolated grid data - */ - public static Array interpolation_IDW_Neighbor(List x_s, List y_s, Array a, - List X, List Y, Integer points) { - int colNum = X.size(); - int rowNum = Y.size(); - int pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - int i, j; - double w, v, gx, gy; - boolean match; - - //Construct K-D tree - int n = 0; - KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2); - for (i = 0; i < pNum; i++) { - if (!Double.isNaN(a.getDouble(i))) { - kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i)); - n += 1; - } - } - if (points == null) { - points = n; - } - - //---- Do interpolation with IDW method - for (i = 0; i < rowNum; i++) { - gy = Y.get(i).doubleValue(); - for (j = 0; j < colNum; j++) { - gx = X.get(j).doubleValue(); - List> srs = kdTree.nearestNeighbours(new double[]{gx, gy}, points); - double v_sum = 0.0; - double weight_sum = 0.0; - match = false; - for (SearchResult sr : srs) { - v = (double) sr.payload; - if (sr.distance == 0) { - r.setDouble(i * colNum + j, v); - match = true; - break; - } else { - w = 1. / sr.distance; - weight_sum += w; - v_sum += v * w; - } - } - if (!match) { - r.setDouble(i * colNum + j, v_sum / weight_sum); - } - } - } - - return r; - } - - /** - * Interpolation with IDW neighbor method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X grid X array - * @param Y grid Y array - * @param NumberOfNearestNeighbors - * @return interpolated grid data - */ - public static Array interpolation_IDW_Neighbor_bak(List x_s, List y_s, Array a, - List X, List Y, int NumberOfNearestNeighbors) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - int i, j, p, l, aP; - double w, SV, SW, aMin; - int points; - points = NumberOfNearestNeighbors; - double[] AllWeights = new double[pNum]; - double[][] NW = new double[2][points]; - int NWIdx; - double x, y, v; - - //---- Do interpolation with IDW method - for (i = 0; i < rowNum; i++) { - for (j = 0; j < colNum; j++) { - r.setDouble(i * colNum + j, Double.NaN); - SV = 0; - SW = 0; - NWIdx = 0; - for (p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - AllWeights[p] = -1; - continue; - } - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (X.get(j).doubleValue() == x && Y.get(i).doubleValue() == y) { - r.setDouble(i * colNum + j, v); - break; - } else { - w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2)); - AllWeights[p] = w; - if (NWIdx < points) { - NW[0][NWIdx] = w; - NW[1][NWIdx] = p; - } - NWIdx += 1; - } - } - - aMin = NW[0][0]; - aP = 0; - for (l = 1; l < points; l++) { - if (NW[0][l] < aMin) { - aMin = NW[0][l]; - aP = l; - } - } - - if (Double.isNaN(r.getDouble(i * colNum + j))) { - for (p = 0; p < pNum; p++) { - w = AllWeights[p]; - if (w == -1) { - continue; - } - - if (w > aMin) { - NW[0][aP] = w; - NW[1][aP] = p; - aMin = NW[0][0]; - aP = 0; - for (l = 1; l < points; l++) { - if (NW[0][l] < aMin) { - aMin = NW[0][l]; - aP = l; - } - } - } - } - for (p = 0; p < points; p++) { - SV += NW[0][p] * a.getDouble((int) NW[1][p]); - SW += NW[0][p]; - } - r.setDouble(i * colNum + j, SV / SW); - } - } - } - - //---- Smooth with 5 points - r = smooth5(r, rowNum, colNum, Double.NaN); - - return r; - } - - /** - * Interpolate with nearest method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param radius Radius - * @return grid data - */ - public static Array interpolation_Nearest(List x_s, List y_s, Array a, List X, List Y, - double radius) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array rdata = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - double gx, gy; - - //Construct K-D tree - KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2); - for (int i = 0; i < pNum; i++) { - if (!Double.isNaN(a.getDouble(i))) { - kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i)); - } - } - - //Loop - if (radius == Double.POSITIVE_INFINITY) { - for (int i = 0; i < rowNum; i++) { - gy = Y.get(i).doubleValue(); - for (int j = 0; j < colNum; j++) { - gx = X.get(j).doubleValue(); - SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0); - rdata.setDouble(i * colNum + j, ((double) r.payload)); - } - } - } else { - for (int i = 0; i < rowNum; i++) { - gy = Y.get(i).doubleValue(); - for (int j = 0; j < colNum; j++) { - gx = X.get(j).doubleValue(); - SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0); - if (Math.sqrt(r.distance) <= radius) { - rdata.setDouble(i * colNum + j, ((double) r.payload)); - } else { - rdata.setDouble(i * colNum + j, Double.NaN); - } - } - } - } - - return rdata; - } - - /** - * Extend the grid to half cell, so the grid points are the centers of the - * cells - * - * @param x Input x coordinate - * @param y Input y coordinate - * @return Result x and y coordinates - */ - public static Array[] extendHalfCell(Array x, Array y) { - double dX = x.getDouble(1) - x.getDouble(0); - double dY = y.getDouble(1) - y.getDouble(0); - int nx = (int) x.getSize() + 1; - int ny = (int) y.getSize() + 1; - Array rx = Array.factory(DataType.DOUBLE, new int[]{nx}); - Array ry = Array.factory(DataType.DOUBLE, new int[]{ny}); - for (int i = 0; i < rx.getSize(); i++) { - if (i == rx.getSize() - 1) { - rx.setDouble(i, x.getDouble(i - 1) + dX * 0.5); - } else { - rx.setDouble(i, x.getDouble(i) - dX * 0.5); - } - } - - for (int i = 0; i < ry.getSize(); i++) { - if (i == ry.getSize() - 1) { - ry.setDouble(i, y.getDouble(i - 1) + dY * 0.5); - } else { - ry.setDouble(i, y.getDouble(i) - dY * 0.5); - } - } - - return new Array[]{rx, ry}; - } - - /** - * Interpolate with inside method - The grid cell value is the average value - * of the inside points or fill value if no inside point. - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param centerPoint the points locate at center or border or grid - * @return grid data - */ - public static Array interpolation_Inside(List x_s, List y_s, Array a, - List X, List Y, boolean centerPoint) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - double dX = X.get(1).doubleValue() - X.get(0).doubleValue(); - double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - int[][] pNums = new int[rowNum][colNum]; - double x, y, v, sx, sy, ex, ey; - if (centerPoint) { - sx = X.get(0).doubleValue() - dX * 0.5; - sy = Y.get(0).doubleValue() - dY * 0.5; - ex = X.get(colNum - 1).doubleValue() + dX * 0.5; - ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5; - } else { - sx = X.get(0).doubleValue(); - sy = Y.get(0).doubleValue(); - ex = X.get(colNum - 1).doubleValue(); - ey = Y.get(rowNum - 1).doubleValue(); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - pNums[i][j] = 0; - r.setDouble(i * colNum + j, 0.0); - } - } - - for (int p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - continue; - } - - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pNums[i][j] += 1; - r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (pNums[i][j] == 0) { - r.setDouble(i * colNum + j, Double.NaN); - } else { - r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]); - } - } - } - - return r; - } - - /** - * Interpolate with inside method - The grid cell value is the average value - * of the inside points or fill value if no inside point. - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param centerPoint If the grid point is center or border - * @return grid data - */ - public static Array interpolation_Inside(Array x_s, Array y_s, Array a, Array X, Array Y, - boolean centerPoint) { - int rowNum, colNum, pNum; - colNum = (int) X.getSize(); - rowNum = (int) Y.getSize(); - pNum = (int) x_s.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - double dX = X.getDouble(1) - X.getDouble(0); - double dY = Y.getDouble(1) - Y.getDouble(0); - int[][] pNums = new int[rowNum][colNum]; - double x, y, v, sx, sy, ex, ey; - if (centerPoint) { - sx = X.getDouble(0) - dX * 0.5; - sy = Y.getDouble(0) - dY * 0.5; - ex = X.getDouble(colNum - 1) + dX * 0.5; - ey = Y.getDouble(rowNum - 1) + dY * 0.5; - } else { - sx = X.getDouble(0); - sy = Y.getDouble(0); - ex = X.getDouble(colNum - 1); - ey = Y.getDouble(rowNum - 1); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - pNums[i][j] = 0; - r.setDouble(i * colNum + j, 0.0); - } - } - - for (int p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - continue; - } - - x = x_s.getDouble(p); - y = y_s.getDouble(p); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pNums[i][j] += 1; - r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (pNums[i][j] == 0) { - r.setDouble(i * colNum + j, Double.NaN); - } else { - r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]); - } - } - } - - return r; - } - - /** - * Interpolate with inside method - The grid cell value is the maximum value - * of the inside points or fill value if no inside point. - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param centerPoint points locate at center or border of grid - * @return grid data - */ - public static Array interpolation_Inside_Max(List x_s, List y_s, Array a, - List X, List Y, boolean centerPoint) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - double dX = X.get(1).doubleValue() - X.get(0).doubleValue(); - double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - int[][] pNums = new int[rowNum][colNum]; - double x, y, v, sx, sy, ex, ey; - double min = Double.NEGATIVE_INFINITY; - if (centerPoint) { - sx = X.get(0).doubleValue() - dX * 0.5; - sy = Y.get(0).doubleValue() - dY * 0.5; - ex = X.get(colNum - 1).doubleValue() + dX * 0.5; - ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5; - } else { - sx = X.get(0).doubleValue(); - sy = Y.get(0).doubleValue(); - ex = X.get(colNum - 1).doubleValue(); - ey = Y.get(rowNum - 1).doubleValue(); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - pNums[i][j] = 0; - r.setDouble(i * colNum + j, min); - } - } - - for (int p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - continue; - } - - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pNums[i][j] += 1; - r.setDouble(i * colNum + j, Math.max(r.getDouble(i * colNum + j), v)); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (pNums[i][j] == 0 || Double.isInfinite(r.getDouble(i * colNum + j))) { - r.setDouble(i * colNum + j, Double.NaN); - } - } - } - - return r; - } - - /** - * Interpolate with inside method - The grid cell value is the minimum value - * of the inside points or fill value if no inside point. - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param centerPoint points locate at center or border of grid - * @return grid data - */ - public static Array interpolation_Inside_Min(List x_s, List y_s, Array a, - List X, List Y, boolean centerPoint) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum}); - double dX = X.get(1).doubleValue() - X.get(0).doubleValue(); - double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - int[][] pNums = new int[rowNum][colNum]; - double x, y, v, sx, sy, ex, ey; - double max = Double.MAX_VALUE; - if (centerPoint) { - sx = X.get(0).doubleValue() - dX * 0.5; - sy = Y.get(0).doubleValue() - dY * 0.5; - ex = X.get(colNum - 1).doubleValue() + dX * 0.5; - ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5; - } else { - sx = X.get(0).doubleValue(); - sy = Y.get(0).doubleValue(); - ex = X.get(colNum - 1).doubleValue(); - ey = Y.get(rowNum - 1).doubleValue(); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - pNums[i][j] = 0; - r.setDouble(i * colNum + j, max); - } - } - - for (int p = 0; p < pNum; p++) { - v = a.getDouble(p); - if (Double.isNaN(v)) { - continue; - } - - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pNums[i][j] += 1; - r.setDouble(i * colNum + j, Math.min(r.getDouble(i * colNum + j), v)); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - if (pNums[i][j] == 0 || r.getDouble(i * colNum + j) == Double.MAX_VALUE) { - r.setDouble(i * colNum + j, Double.NaN); - } - } - } - - return r; - } - - /** - * Interpolate with inside method - The grid cell value is the count number - * of the inside points or fill value if no inside point. - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param X x coordinate - * @param Y y coordinate - * @param pointDensity If return point density value - * @param centerPoint points locate at center or border of grid - * @return grid data - */ - public static Object interpolation_Inside_Count(List x_s, List y_s, - List X, List Y, boolean pointDensity, boolean centerPoint) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - Array r = Array.factory(DataType.INT, new int[]{rowNum, colNum}); - double dX = X.get(1).doubleValue() - X.get(0).doubleValue(); - double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - int[][] pNums = new int[rowNum][colNum]; - double x, y, sx, sy, ex, ey; - if (centerPoint) { - sx = X.get(0).doubleValue() - dX * 0.5; - sy = Y.get(0).doubleValue() - dY * 0.5; - ex = X.get(colNum - 1).doubleValue() + dX * 0.5; - ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5; - } else { - sx = X.get(0).doubleValue(); - sy = Y.get(0).doubleValue(); - ex = X.get(colNum - 1).doubleValue(); - ey = Y.get(rowNum - 1).doubleValue(); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - pNums[i][j] = 0; - //r.setInt(i * colNum + j, 0); - } - } - - for (int p = 0; p < pNum; p++) { - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pNums[i][j] += 1; - //r.setInt(i * colNum + j, r.getInt(i * colNum + j) + 1); - } - - for (int i = 0; i < rowNum; i++) { - for (int j = 0; j < colNum; j++) { - r.setInt(i * colNum + j, pNums[i][j]); - } - } - - if (pointDensity) { - Array pds = Array.factory(DataType.INT, new int[]{pNum}); - for (int p = 0; p < pNum; p++) { - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < sx || x > ex) { - continue; - } - if (y < sy || y > ey) { - continue; - } - - int j = (int) ((x - sx) / dX); - int i = (int) ((y - sy) / dY); - pds.setInt(p, pNums[i][j]); - } - return new Array[]{r, pds}; - } - - return r; - } - - private static List getPointsIJ(List x_s, List y_s, List X, List Y) { - int rowNum, colNum, pNum; - colNum = X.size(); - rowNum = Y.size(); - pNum = x_s.size(); - double dX = X.get(1).doubleValue() - X.get(0).doubleValue(); - double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - List pIndices = new ArrayList<>(); - double x, y; - int i, j; - for (int p = 0; p < pNum; p++) { - x = x_s.get(p).doubleValue(); - y = y_s.get(p).doubleValue(); - if (x < X.get(0).doubleValue() || x > X.get(colNum - 1).doubleValue()) { - continue; - } - if (y < Y.get(0).doubleValue() || y > Y.get(rowNum - 1).doubleValue()) { - continue; - } - - j = (int) ((x - X.get(0).doubleValue()) / dX); - i = (int) ((y - Y.get(0).doubleValue()) / dY); - pIndices.add(new int[]{i, j}); - } - - return pIndices; - } - - private static List getPointsIdx(List pIJ, int ii, int jj, int radius) { - List pIdx = new ArrayList<>(); - int[] ij; - int i, j; - for (int p = 0; p < pIJ.size(); p++) { - ij = pIJ.get(p); - i = ij[0]; - j = ij[1]; - if (Math.abs(i - ii) <= radius && Math.abs(j - jj) <= radius) { - pIdx.add(p); - } - } - - return pIdx; - } - - /** - * Interpolate with surface method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param unDefData undefine value - * @return grid data - */ - public static Array interpolation_Surface_1(Array x_s, Array y_s, Array a, Array X, Array Y, - double unDefData) { - int rowNum, colNum, xn, yn; - int[] shape = x_s.getShape(); - colNum = shape[1]; - rowNum = shape[0]; - xn = (int) X.getSize(); - yn = (int) Y.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - double x, y; - - PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1]; - PolygonShape ps; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1))); - points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1))); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - polygons[i][j] = ps; - } - } - - for (int i = 0; i < yn; i++) { - for (int j = 0; j < xn; j++) { - r.setDouble(i * xn + j, unDefData); - } - } - - double v; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - ps = polygons[i][j]; - v = a.getDouble(i * colNum + j); - for (int ii = 0; ii < yn; ii++) { - y = Y.getDouble(ii); - for (int jj = 0; jj < xn; jj++) { - x = X.getDouble(jj); - if (Double.isNaN(r.getDouble(ii * xn + jj)) || r.getDouble(ii * xn + jj) == unDefData) { - if (GeoComputation.pointInPolygon(ps, x, y)) { - r.setDouble(ii * xn + jj, v); - } - } - } - } - } - } - - return r; - } - - /** - * Interpolate with surface method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @return grid data - */ - public static Array interpolation_Surface(Array x_s, Array y_s, Array a, Array X, Array Y) { - int rowNum, colNum, xn, yn; - int[] shape = x_s.getShape(); - colNum = shape[1]; - rowNum = shape[0]; - xn = (int) X.getSize(); - yn = (int) Y.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, Double.NaN); - } - - double x, y; - double v, xll, xtl, xtr, xlr, yll, ytl, ytr, ylr; - double dX = X.getDouble(1) - X.getDouble(0); - double dY = Y.getDouble(1) - Y.getDouble(0); - int minxi, maxxi, minyi, maxyi; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - v = a.getDouble(i * colNum + j); - if (Double.isNaN(v)) { - continue; - } - xll = x_s.getDouble(i * colNum + j); - xtl = x_s.getDouble((i + 1) * colNum + j); - xtr = x_s.getDouble((i + 1) * colNum + j + 1); - xlr = x_s.getDouble(i * colNum + j + 1); - yll = y_s.getDouble(i * colNum + j); - ytl = y_s.getDouble((i + 1) * colNum + j); - ytr = y_s.getDouble((i + 1) * colNum + j + 1); - ylr = y_s.getDouble(i * colNum + j + 1); - if (Double.isNaN(xll) || Double.isNaN(xtl) || Double.isNaN(xtr) || Double.isNaN(xlr) - || Double.isNaN(yll) || Double.isNaN(ytl) || Double.isNaN(ytr) || Double.isNaN(ylr)) { - continue; - } - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(xll, yll)); - points.add(new PointD(xtl, ytl)); - points.add(new PointD(xtr, ytr)); - points.add(new PointD(xlr, ylr)); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - minxi = (int) ((ps.getExtent().minX - X.getDouble(0)) / dX); - maxxi = (int) ((ps.getExtent().maxX - X.getDouble(0)) / dX); - minyi = (int) ((ps.getExtent().minY - Y.getDouble(0)) / dY); - maxyi = (int) ((ps.getExtent().maxY - Y.getDouble(0)) / dY); - maxxi += 1; - maxyi += 1; - if (maxxi < 0 || minxi >= xn) { - continue; - } - if (maxyi < 0 || minyi >= yn) { - continue; - } - if (minxi < 0) { - minxi = 0; - } - if (maxxi >= xn) { - maxxi = xn - 1; - } - if (maxyi >= yn) { - maxyi = yn - 1; - } - for (int m = minyi; m <= maxyi; m++) { - y = Y.getDouble(m); - for (int n = minxi; n <= maxxi; n++) { - x = X.getDouble(n); - if (GeoComputation.pointInPolygon(ps, x, y)) { - r.setDouble(m * xn + n, v); - } - } - } - } - } - - return r; - } - - /** - * Interpolate with surface method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @return grid data - */ - public static Array interpolation_Surface_bak(Array x_s, Array y_s, Array a, Array X, Array Y) { - int rowNum, colNum, xn, yn; - int[] shape = x_s.getShape(); - colNum = shape[1]; - rowNum = shape[0]; - xn = (int) X.getSize(); - yn = (int) Y.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - double x, y; - boolean isIn; - - PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1]; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1))); - points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1))); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - polygons[i][j] = ps; - } - } - - for (int i = 0; i < yn; i++) { - y = Y.getDouble(i); - for (int j = 0; j < xn; j++) { - x = X.getDouble(j); - isIn = false; - for (int ii = 0; ii < rowNum - 1; ii++) { - for (int jj = 0; jj < colNum - 1; jj++) { - if (GeoComputation.pointInPolygon(polygons[ii][jj], x, y)) { - r.setDouble(i * xn + j, a.getDouble(ii * colNum + jj)); - isIn = true; - break; - } - } - if (isIn) { - break; - } - } - if (!isIn) { - r.setDouble(i * xn + j, Double.NaN); - } - } - } - - return r; - } - - /** - * Cressman analysis - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param v_s scatter value array - * @param X x array - * @param Y y array - * @param radList radii list - * @return result grid data - */ - public static Array cressman(List x_s, List y_s, Array v_s, List X, List Y, - List radList) { - int xNum = X.size(); - int yNum = Y.size(); - int pNum = x_s.size(); - //double[][] gridData = new double[yNum][xNum]; - Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum}); - int irad = radList.size(); - int i, j; - - //Loop through each stn report and convert stn lat/lon to grid coordinates - double xMin = X.get(0).doubleValue(); - double xMax = X.get(xNum - 1).doubleValue(); - double yMin = Y.get(0).doubleValue(); - double yMax = Y.get(yNum - 1).doubleValue(); - double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue(); - double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - double x, y; - double sum; - int stNum = 0; - double[][] stationData = new double[pNum][3]; - for (i = 0; i < pNum; i++) { - x = x_s.get(i).doubleValue(); - y = y_s.get(i).doubleValue(); - stationData[i][0] = (x - xMin) / xDelt; - stationData[i][1] = (y - yMin) / yDelt; - stationData[i][2] = v_s.getDouble(i); - if (!Double.isNaN(stationData[i][2])) { - //total += stationData[i][2]; - stNum += 1; - } - } - //total = total / stNum; - - double HITOP = -999900000000000000000.0; - double HIBOT = 999900000000000000000.0; - double[][] TOP = new double[yNum][xNum]; - double[][] BOT = new double[yNum][xNum]; - for (i = 0; i < yNum; i++) { - for (j = 0; j < xNum; j++) { - TOP[i][j] = HITOP; - BOT[i][j] = HIBOT; - } - } - - //Initial grid values are average of station reports within the first radius - double val, sx, sy, sxi, syi; - double rad; - if (radList.size() > 0) { - rad = radList.get(0).doubleValue(); - } else { - rad = 4; - } - for (i = 0; i < yNum; i++) { - y = Y.get(i).doubleValue(); - yMin = y - rad; - yMax = y + rad; - for (j = 0; j < xNum; j++) { - x = X.get(j).doubleValue(); - xMin = x - rad; - xMax = x + rad; - stNum = 0; - sum = 0; - for (int s = 0; s < pNum; s++) { - val = stationData[s][2]; - sx = x_s.get(s).doubleValue(); - sy = y_s.get(s).doubleValue(); - sxi = stationData[s][0]; - syi = stationData[s][1]; - if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) { - continue; - } - - double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2)); - if (dis > rad) { - continue; - } - - sum += val; - stNum += 1; - if (TOP[i][j] < val) { - TOP[i][j] = val; - } - if (BOT[i][j] > val) { - BOT[i][j] = val; - } - } - if (stNum == 0) { - r.setDouble(i * xNum + j, Double.NaN); - } else { - r.setDouble(i * xNum + j, sum / stNum); - } - } - } - - //Perform the objective analysis - for (int p = 0; p < irad; p++) { - rad = radList.get(p).doubleValue(); - for (i = 0; i < yNum; i++) { - y = Y.get(i).doubleValue(); - yMin = y - rad; - yMax = y + rad; - for (j = 0; j < xNum; j++) { - if (Double.isNaN(r.getDouble(i * xNum + j))) { - continue; - } - - x = X.get(j).doubleValue(); - xMin = x - rad; - xMax = x + rad; - sum = 0; - double wSum = 0; - for (int s = 0; s < pNum; s++) { - val = stationData[s][2]; - sx = x_s.get(s).doubleValue(); - sy = y_s.get(s).doubleValue(); - sxi = stationData[s][0]; - syi = stationData[s][1]; - if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) { - continue; - } - - double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2)); - if (dis > rad) { - continue; - } - - int i1 = (int) syi; - int j1 = (int) sxi; - int i2 = i1 + 1; - int j2 = j1 + 1; - double a = r.getDouble(i1 * xNum + j1); - double b = r.getDouble(i1 * xNum + j2); - double c = r.getDouble(i2 * xNum + j1); - double d = r.getDouble(i2 * xNum + j2); - List dList = new ArrayList<>(); - if (!Double.isNaN(a)) { - dList.add(a); - } - if (!Double.isNaN(b)) { - dList.add(b); - } - if (!Double.isNaN(c)) { - dList.add(c); - } - if (Double.isNaN(d)) { - dList.add(d); - } - - double calVal; - if (dList.isEmpty()) { - continue; - } else if (dList.size() == 1) { - calVal = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - calVal = aSum / dList.size(); - } else { - double x1val = a + (c - a) * (syi - i1); - double x2val = b + (d - b) * (syi - i1); - calVal = x1val + (x2val - x1val) * (sxi - j1); - } - double eVal = val - calVal; - double w = (rad * rad - dis * dis) / (rad * rad + dis * dis); - sum += eVal * w; - wSum += w; - } -// if (wSum < 0.000001) { -// r.setDouble(i * xNum + j, Double.NaN); -// } else { -// double aData = r.getDouble(i * xNum + j) + sum / wSum; -// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData))); -// } - if (wSum >= 0.000001) { - double aData = r.getDouble(i * xNum + j) + sum / wSum; - r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData))); - } - } - } - } - - //Return - return r; - } - - /** - * Cressman analysis - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param v_s scatter value array - * @param X x array - * @param Y y array - * @param radList radii list - * @return result grid data - */ - public static Array cressman_bak(List x_s, List y_s, Array v_s, List X, List Y, - List radList) { - int xNum = X.size(); - int yNum = Y.size(); - int pNum = x_s.size(); - //double[][] gridData = new double[yNum][xNum]; - Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum}); - int irad = radList.size(); - int i, j; - - //Loop through each stn report and convert stn lat/lon to grid coordinates - double xMin = X.get(0).doubleValue(); - double xMax; - double yMin = Y.get(0).doubleValue(); - double yMax; - double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue(); - double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue(); - double x, y; - double sum; - int stNum = 0; - double[][] stationData = new double[pNum][3]; - for (i = 0; i < pNum; i++) { - x = x_s.get(i).doubleValue(); - y = y_s.get(i).doubleValue(); - stationData[i][0] = (x - xMin) / xDelt; - stationData[i][1] = (y - yMin) / yDelt; - stationData[i][2] = v_s.getDouble(i); - if (!Double.isNaN(stationData[i][2])) { - //total += stationData[i][2]; - stNum += 1; - } - } - //total = total / stNum; - - double HITOP = -999900000000000000000.0; - double HIBOT = 999900000000000000000.0; - double[][] TOP = new double[yNum][xNum]; - double[][] BOT = new double[yNum][xNum]; - for (i = 0; i < yNum; i++) { - for (j = 0; j < xNum; j++) { - TOP[i][j] = HITOP; - BOT[i][j] = HIBOT; - } - } - - //Initial grid values are average of station reports within the first radius - double rad; - if (radList.size() > 0) { - rad = radList.get(0).doubleValue(); - } else { - rad = 4; - } - for (i = 0; i < yNum; i++) { - y = (double) i; - yMin = y - rad; - yMax = y + rad; - for (j = 0; j < xNum; j++) { - x = (double) j; - xMin = x - rad; - xMax = x + rad; - stNum = 0; - sum = 0; - for (int s = 0; s < pNum; s++) { - double val = stationData[s][2]; - double sx = stationData[s][0]; - double sy = stationData[s][1]; - if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) { - continue; - } - - if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) { - continue; - } - - double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2)); - if (dis > rad) { - continue; - } - - sum += val; - stNum += 1; - if (TOP[i][j] < val) { - TOP[i][j] = val; - } - if (BOT[i][j] > val) { - BOT[i][j] = val; - } - } - if (stNum == 0) { - r.setDouble(i * xNum + j, Double.NaN); - } else { - r.setDouble(i * xNum + j, sum / stNum); - } - } - } - - //Perform the objective analysis - for (int p = 0; p < irad; p++) { - rad = radList.get(p).doubleValue(); - for (i = 0; i < yNum; i++) { - y = (double) i; - yMin = y - rad; - yMax = y + rad; - for (j = 0; j < xNum; j++) { - if (Double.isNaN(r.getDouble(i * xNum + j))) { - continue; - } - - x = (double) j; - xMin = x - rad; - xMax = x + rad; - sum = 0; - double wSum = 0; - for (int s = 0; s < pNum; s++) { - double val = stationData[s][2]; - double sx = stationData[s][0]; - double sy = stationData[s][1]; - if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) { - continue; - } - - if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) { - continue; - } - - double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2)); - if (dis > rad) { - continue; - } - - int i1 = (int) sy; - int j1 = (int) sx; - int i2 = i1 + 1; - int j2 = j1 + 1; - double a = r.getDouble(i1 * xNum + j1); - double b = r.getDouble(i1 * xNum + j2); - double c = r.getDouble(i2 * xNum + j1); - double d = r.getDouble(i2 * xNum + j2); - List dList = new ArrayList<>(); - if (!Double.isNaN(a)) { - dList.add(a); - } - if (!Double.isNaN(b)) { - dList.add(b); - } - if (!Double.isNaN(c)) { - dList.add(c); - } - if (Double.isNaN(d)) { - dList.add(d); - } - - double calVal; - if (dList.isEmpty()) { - continue; - } else if (dList.size() == 1) { - calVal = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - calVal = aSum / dList.size(); - } else { - double x1val = a + (c - a) * (sy - i1); - double x2val = b + (d - b) * (sy - i1); - calVal = x1val + (x2val - x1val) * (sx - j1); - } - double eVal = val - calVal; - double w = (rad * rad - dis * dis) / (rad * rad + dis * dis); - sum += eVal * w; - wSum += w; - } - if (wSum < 0.000001) { - r.setDouble(i * xNum + j, Double.NaN); - } else { - double aData = r.getDouble(i * xNum + j) + sum / wSum; - r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData))); - } -// if (wSum >= 0.000001) { -// double aData = r.getDouble(i * xNum + j) + sum / wSum; -// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData))); -// } - } - } - } - - //Return - return r; - } - - /** - * Interpolates from a rectilinear grid to another rectilinear grid using - * bilinear interpolation. - * - * @param a The sample array - * @param X X coordinate of the sample array - * @param Y Y coordinate of the sample array - * @param newX X coordinate of the query points - * @param newY Y coordinate of the query points - * @return Resampled array - */ - public static Array linint2(Array a, Array X, Array Y, Array newX, Array newY) { - int xn = (int) newX.getSize(); - int yn = (int) newY.getSize(); - int[] shape = a.getShape(); - int n = shape.length; - shape[n - 1] = xn; - shape[n - 2] = yn; - double x, y, v; - Array r = Array.factory(DataType.DOUBLE, shape); - - Index index = r.getIndex(); - int[] counter; - int yi, xi; - for (int k = 0; k < r.getSize(); k++) { - counter = index.getCurrentCounter(); - yi = counter[n - 2]; - xi = counter[n - 1]; - y = newY.getDouble(yi); - x = newX.getDouble(xi); - v = bilinear(a, index, X, Y, x, y); - r.setDouble(index, v); - index.incr(); - } - - return r; - } - - /** - * Resample grid array with bilinear method - * - * @param a The sample array - * @param X X coordinate of the sample array - * @param Y Y coordinate of the sample array - * @param newX X coordinate of the query points - * @param newY Y coordinate of the query points - * @return Resampled array - */ - public static Array resample_Bilinear(Array a, List X, List Y, List newX, List newY) { - int i, j; - int xn = newX.size(); - int yn = newY.size(); - double x, y, v; - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - - for (i = 0; i < yn; i++) { - y = newY.get(i).doubleValue(); - for (j = 0; j < xn; j++) { - x = newX.get(j).doubleValue(); - if (x < X.get(0).doubleValue() || x > X.get(X.size() - 1).doubleValue()) { - r.setDouble(i * xn + j, Double.NaN); - } else if (y < Y.get(0).doubleValue() || y > Y.get(Y.size() - 1).doubleValue()) { - r.setDouble(i * xn + j, Double.NaN); - } else { - v = toStation(a, X, Y, x, y); - r.setDouble(i * xn + j, v); - } - } - } - - return r; - } - - /** - * Resample grid array with bilinear method - * - * @param a The sample array - * @param X X coordinate of the sample array - * @param Y Y coordinate of the sample array - * @param newX X coordinate of the query points - * @param newY Y coordinate of the query points - * @return Resampled array - */ - public static Array resample_Bilinear(Array a, Array X, Array Y, Array newX, Array newY) { - int i; - int n = (int) newX.getSize(); - double x, y, v; - Array r = Array.factory(DataType.DOUBLE, newX.getShape()); - - for (i = 0; i < n; i++) { - x = newX.getDouble(i); - y = newY.getDouble(i); - if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) { - r.setDouble(i, Double.NaN); - } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) { - r.setDouble(i, Double.NaN); - } else { - v = toStation(a, X, Y, x, y); - r.setDouble(i, v); - } - } - - return r; - } - - /** - * Resample grid array with neighbor method - * - * @param a The sample array - * @param X X coordinate of the sample array - * @param Y Y coordinate of the sample array - * @param newX X coordinate of the query points - * @param newY Y coordinate of the query points - * @return Resampled array - */ - public static Array resample_Neighbor(Array a, Array X, Array Y, Array newX, Array newY) { - int i; - int n = (int) newX.getSize(); - double x, y, v; - Array r = Array.factory(DataType.DOUBLE, newX.getShape()); - - for (i = 0; i < n; i++) { - x = newX.getDouble(i); - y = newY.getDouble(i); - if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) { - r.setDouble(i, Double.NaN); - } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) { - r.setDouble(i, Double.NaN); - } else { - v = toStation_Neighbor(a, X, Y, x, y); - r.setDouble(i, v); - } - } - - return r; - } - - /** - * Interpolate array data - * - * @param a Array - * @param X X coordinates - * @param Y Y coordinates - * @return Result array data - */ - public Array interpolate(Array a, List X, List Y) { - int nxNum = X.size() * 2 - 1; - int nyNum = Y.size() * 2 - 1; - List newX = new ArrayList<>(); - List newY = new ArrayList<>(); - int i; - - for (i = 0; i < nxNum; i++) { - if (i % 2 == 0) { - newX.add(X.get(i / 2).doubleValue()); - } else { - newX.add((X.get((i - 1) / 2).doubleValue() + X.get((i - 1) / 2 + 1).doubleValue()) / 2); - } - } - for (i = 0; i < nyNum; i++) { - if (i % 2 == 0) { - newY.add(Y.get(i / 2).doubleValue()); - } else { - newY.add((Y.get((i - 1) / 2).doubleValue() + Y.get((i - 1) / 2 + 1).doubleValue()) / 2); - } - } - - return resample_Bilinear(a, X, Y, newX, newY); - } - - /** - * Multidimensional interpolation on regular grids. - * - * @param points The points defining the regular grid in n dimensions. - * @param values The data on the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - * @return Interpolation value - */ - public static double interpn_s(List> points, Array values, List xi) { - Object[] r = findIndices(points, xi); - boolean outBounds = (boolean) r[2]; - if (outBounds) { - return Double.NaN; - } else { - double v, weight; - Index index = values.getIndex(); - int[] indices = (int[]) r[0]; - double[] distances = (double[]) r[1]; - v = 0; - List ii = new ArrayList<>(); - iterIndex(ii, index, indices, 0); - int n = indices.length; - for (Index idx : ii) { - weight = 1; - for (int i = 0; i < n; i++) { - weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i]; - } - v += values.getDouble(idx) * weight; - } - - return v; - } - } - - /** - * Multidimensional interpolation on regular grids. - * - * @param points The points defining the regular grid in n dimensions. - * @param values The data on the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - * @return Interpolation value - */ - public static double interpn_s(List points, Array values, Array xi) { - Object[] r = findIndices(points, xi); - boolean outBounds = (boolean) r[2]; - if (outBounds) { - return Double.NaN; - } else { - double v, weight; - Index index = values.getIndex(); - int[] indices = (int[]) r[0]; - double[] distances = (double[]) r[1]; - v = 0; - List ii = new ArrayList<>(); - iterIndex(ii, index, indices, 0); - int n = indices.length; - for (Index idx : ii) { - weight = 1; - for (int i = 0; i < n; i++) { - weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i]; - } - v += values.getDouble(idx) * weight; - } - - return v; - } - } - - /** - * Multidimensional interpolation on regular grids. - * - * @param points The points defining the regular grid in n dimensions. - * @param values The data on the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - 2D - * @return Interpolation value - */ - public static Array interpn(List points, Array values, List xi) { - int n = xi.size(); - Array r = Array.factory(DataType.DOUBLE, new int[]{n}); - for (int i = 0; i < n; i++) { - Array x = xi.get(i); - r.setDouble(i, interpn_s(points, values, x)); - } - - return r; - } - - /** - * Multidimensional interpolation on regular grids. - * - * @param points The points defining the regular grid in n dimensions. - * @param values The data on the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - 2D - * @return Interpolation value - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Object interpn(List points, Array values, Array xi) throws InvalidRangeException { - if (xi.getRank() == 1) { - return interpn_s(points, values, xi); - } - - int n = xi.getShape()[0]; - int m = xi.getShape()[1]; - Array r = Array.factory(DataType.DOUBLE, new int[]{n}); - for (int i = 0; i < n; i++) { - Array x = xi.section(new int[]{i, 0}, new int[]{1, m}); - r.setDouble(i, interpn_s(points, values, x)); - } - - return r; - } - - private static void iterIndex(List ii, Index index, int[] indices, int idx) { - int n = indices.length; - if (idx < n - 1) { - index.setDim(idx, indices[idx]); - iterIndex(ii, index, indices, idx + 1); - index.setDim(idx, indices[idx] + 1); - iterIndex(ii, index, indices, idx + 1); - } else { - index.setDim(idx, indices[idx]); - ii.add((Index) index.clone()); - //System.out.println(index); - index.setDim(idx, indices[idx] + 1); - ii.add((Index) index.clone()); - //System.out.println(index); - } - } - - /** - * Find indices - * - * @param points The points defining the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - * @return Indices - */ - public static Object[] findIndices(List> points, List xi) { - int n = points.size(); - int[] indices = new int[n]; - double[] distances = new double[n]; - boolean outBounds = false; - double x; - List a; - for (int i = 0; i < n; i++) { - x = xi.get(i).doubleValue(); - a = points.get(i); - int idx = searchSorted(a, x); - if (idx < 0) { - outBounds = true; - idx = 0; - } - indices[i] = idx; - distances[i] = (x - a.get(idx).doubleValue()) / (a.get(idx + 1).doubleValue() - a.get(idx).doubleValue()); - } - - return new Object[]{indices, distances, outBounds}; - } - - /** - * Find indices - * - * @param points The points defining the regular grid in n dimensions. - * @param xi The coordinates to sample the gridded data at - * @return Indices - */ - public static Object[] findIndices(List points, Array xi) { - int n = points.size(); - int[] indices = new int[n]; - double[] distances = new double[n]; - boolean outBounds = false; - double x; - Array a; - for (int i = 0; i < n; i++) { - x = xi.getDouble(i); - a = points.get(i); - int idx = searchSorted(a, x); - if (idx < 0) { - outBounds = true; - idx = 0; - } - indices[i] = idx; - distances[i] = (x - a.getDouble(idx)) / (a.getDouble(idx + 1) - a.getDouble(idx)); - } - - return new Object[]{indices, distances, outBounds}; - } - - /** - * Search sorted list index - * - * @param a Sorted list - * @param v value - * @return Index - */ - public static int searchSorted(List a, double v) { - int idx = -1; - int n = a.size(); - if (a.get(1).doubleValue() > a.get(0).doubleValue()) { - if (v < a.get(0).doubleValue()) { - return idx; - } - - if (v > a.get(n - 1).doubleValue()) { - return idx; - } - - for (int i = 1; i < n; i++) { - if (v < a.get(i).doubleValue()) { - idx = i - 1; - break; - } - } - } else { - if (v > a.get(0).doubleValue()) { - return idx; - } - - if (v < a.get(n - 1).doubleValue()) { - return idx; - } - - for (int i = 1; i < n; i++) { - if (v > a.get(i).doubleValue()) { - idx = i - 1; - break; - } - } - } - - return idx; - } - - /** - * Search sorted list index - * - * @param a Sorted list - * @param v value - * @return Index - */ - public static int searchSorted(Array a, double v) { - int idx = -1; - int n = (int) a.getSize(); - if (a.getDouble(1) > a.getDouble(0)) { - if (v < a.getDouble(0)) { - return idx; - } - - if (v > a.getDouble(n - 1)) { - return idx; - } - - for (int i = 1; i < n; i++) { - if (v < a.getDouble(i)) { - idx = i - 1; - break; - } - } - } else { - if (v > a.getDouble(0)) { - return idx; - } - - if (v < a.getDouble(n - 1)) { - return idx; - } - - for (int i = 1; i < n; i++) { - if (v > a.getDouble(i)) { - idx = i - 1; - break; - } - } - } - - return idx; - } - -// /** -// * Search sorted list index -// * -// * @param a Sorted list -// * @param v value -// * @return Index -// */ -// public static int searchSorted(Array a, double v) { -// if (v < a.getDouble(0) || v > a.getDouble((int)a.getSize() - 1)) { -// return -1; -// } -// -// int idx = Arrays.binarySearch((double[])a.get1DJavaArray(double.class), v); -// if (idx < 0) { -// idx = -idx - 1; -// } -// return idx; -// } - /** - * Interpolates data with any shape over a specified axis. - * - * @param x Desired interpolated value - * @param xp The x-coordinates of the data points. - * @param a The data to be interpolated. - * @param axis The axis to interpolate over. - * @return Interpolated data - * @throws InvalidRangeException - */ - public static Array interpolate_1d(double x, Array xp, Array a, int axis) throws InvalidRangeException { - int[] dataShape = xp.getShape(); - int[] shape = new int[dataShape.length - 1]; - for (int i = 0; i < dataShape.length; i++) { - if (i < axis) { - shape[i] = dataShape[i]; - } else if (i > axis) { - shape[i - 1] = dataShape[i]; - } - } - - Array r = Array.factory(a.getDataType(), shape); - Index indexr = r.getIndex(); - Index indexa = a.getIndex(); - int[] current, dcurrent = new int[dataShape.length]; - int idx; - Array tArray; - double belowp, abovep, belowa, abovea; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(current[idx], current[idx], 1)); - dcurrent[j] = current[idx]; - } - } - tArray = ArrayMath.section(xp, ranges); - idx = searchSorted(tArray, x); - if (idx < 0) { - r.setDouble(i, Double.NaN); - } else if (idx == dataShape[axis] - 1) { - dcurrent[axis] = idx; - r.setObject(i, a.getObject(indexa.set(dcurrent))); - } else { - dcurrent[axis] = idx; - indexa.set(dcurrent); - belowp = xp.getDouble(indexa); - belowa = a.getDouble(indexa); - dcurrent[axis] = idx + 1; - indexa.set(dcurrent); - abovep = xp.getDouble(indexa); - abovea = a.getDouble(indexa); - r.setDouble(i, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa); - } - indexr.incr(); - } - - return r; - } - - /** - * Interpolates data with any shape over a specified axis. - * - * @param xa Desired interpolated values - * @param xp The x-coordinates of the data points. - * @param a The data to be interpolated. - * @param axis The axis to interpolate over. - * @return Interpolated data - * @throws InvalidRangeException - */ - public static Array interpolate_1d(Array xa, Array xp, Array a, int axis) throws InvalidRangeException { - int[] dataShape = xp.getShape(); - int[] shape = new int[dataShape.length]; - int[] tshape = new int[shape.length - 1]; - for (int i = 0; i < dataShape.length; i++) { - if (i == axis) { - shape[i] = xa.getShape()[0]; - } else { - shape[i] = dataShape[i]; - if (i < axis) { - tshape[i] = dataShape[i]; - } else { - tshape[i - 1] = dataShape[i]; - } - } - } - - Array r = Array.factory(a.getDataType(), shape); - Array rr = Array.factory(DataType.BYTE, tshape); - Index indexrr = rr.getIndex(); - Index indexr = r.getIndex(); - Index indexa = a.getIndex(); - int[] currentrr, currenta = new int[dataShape.length], currentr = new int[shape.length]; - int idx; - Array tArray; - double belowp, abovep, belowa, abovea, x; - for (int i = 0; i < rr.getSize(); i++) { - currentrr = indexrr.getCurrentCounter(); - List ranges = new ArrayList<>(); - for (int j = 0; j < dataShape.length; j++) { - if (j == axis) { - ranges.add(new Range(0, dataShape[j] - 1, 1)); - } else { - idx = j; - if (idx > axis) { - idx -= 1; - } - ranges.add(new Range(currentrr[idx], currentrr[idx], 1)); - currenta[j] = currentrr[idx]; - currentr[j] = currentrr[idx]; - } - } - tArray = ArrayMath.section(xp, ranges); - for (int j = 0; j < xa.getSize(); j++) { - x = xa.getDouble(j); - idx = searchSorted(tArray, x); - currentr[axis] = j; - indexr.set(currentr); - if (idx < 0) { - r.setDouble(indexr, Double.NaN); - } else if (idx == dataShape[axis] - 1) { - currenta[axis] = idx; - r.setObject(indexr, a.getObject(indexa.set(currenta))); - } else { - currenta[axis] = idx; - indexa.set(currenta); - belowp = xp.getDouble(indexa); - belowa = a.getDouble(indexa); - currenta[axis] = idx + 1; - indexa.set(currenta); - abovep = xp.getDouble(indexa); - abovea = a.getDouble(indexa); - r.setDouble(indexr, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa); - } - } - indexrr.incr(); - } - - return r; - } - - // - // - /** - * Reproject - * - * @param x X array - * @param y Y array - * @param toProj To projection - * @return Result arrays - */ - public static Array[] reproject(Array x, Array y, ProjectionInfo toProj) { - ProjectionInfo fromProj = KnownCoordinateSystems.geographic.world.WGS1984; - return reproject(x, y, fromProj, toProj); - } - - /** - * Reproject - * - * @param x X array - * @param y Y array - * @param fromProj From projection - * @param toProj To projection - * @return Result arrays - */ - public static Array[] reproject(Array x, Array y, ProjectionInfo fromProj, ProjectionInfo toProj) { - Array rx = Array.factory(DataType.DOUBLE, x.getShape()); - Array ry = Array.factory(DataType.DOUBLE, x.getShape()); - int n = (int) x.getSize(); - double[][] points = new double[n][]; - for (int i = 0; i < n; i++) { - points[i] = new double[]{x.getDouble(i), y.getDouble(i)}; - } - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - for (int i = 0; i < n; i++) { - rx.setDouble(i, points[i][0]); - ry.setDouble(i, points[i][1]); - } - - return new Array[]{rx, ry}; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @param missingValue Missing value - * @return Interpolated value - */ - public static double toStation(Array data, List xArray, List yArray, double x, double y, - double missingValue) { - double iValue = Double.NaN; - int nx = xArray.size(); - int ny = yArray.size(); - if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue() - || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) { - return iValue; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.get(i).doubleValue()) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.get(i).doubleValue()) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); - if (!Double.isNaN(a) && !MIMath.doubleEquals(a, missingValue)) { - dList.add(a); - } - if (!Double.isNaN(b) && !MIMath.doubleEquals(b, missingValue)) { - dList.add(b); - } - if (!Double.isNaN(c) && !MIMath.doubleEquals(c, missingValue)) { - dList.add(c); - } - if (!Double.isNaN(d) && !MIMath.doubleEquals(d, missingValue)) { - dList.add(d); - } - - if (dList.isEmpty()) { - return iValue; - } else if (dList.size() == 1) { - iValue = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - iValue = aSum / dList.size(); - } else { - double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue(); - double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue(); - double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy; - double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy; - iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx; - } - - return iValue; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @return Interpolated value - */ - public static double toStation(Array data, List xArray, List yArray, double x, double y) { - double iValue = Double.NaN; - int nx = xArray.size(); - int ny = yArray.size(); - if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue() - || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) { - return iValue; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.get(i).doubleValue()) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.get(i).doubleValue()) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); - if (!Double.isNaN(a)) { - dList.add(a); - } - if (!Double.isNaN(b)) { - dList.add(b); - } - if (!Double.isNaN(c)) { - dList.add(c); - } - if (!Double.isNaN(d)) { - dList.add(d); - } - - if (dList.isEmpty()) { - return iValue; - } else if (dList.size() == 1) { - iValue = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - iValue = aSum / dList.size(); - } else { - double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue(); - double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue(); - double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy; - double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy; - iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx; - } - - return iValue; - } - - /** - * Get value index in a dimension array - * - * @param dim Dimension array - * @param v The value - * @return value index - */ - public static int getDimIndex(Array dim, double v) { - int n = (int) dim.getSize(); - if (v < dim.getDouble(0) || v > dim.getDouble(n - 1)) { - return -1; - } - - int idx = n - 1; - for (int i = 1; i < n; i++) { - if (v < dim.getDouble(i)) { - idx = i - 1; - break; - } - } - return idx; - } - - private static int[] gridIndex(Array xdim, Array ydim, double x, double y) { - int xn = (int) xdim.getSize(); - int yn = (int) ydim.getSize(); - int xIdx = getDimIndex(xdim, x); - if (xIdx < 0) { - return null; - } - - int yIdx = getDimIndex(ydim, y); - if (yIdx < 0) { - return null; - } - - if (xIdx == xn - 1) { - xIdx = xn - 2; - } - if (yIdx == yn - 1) { - yIdx = yn - 2; - } - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - - return new int[]{i1, j1, i2, j2}; - } - - private static double bilinear(Array data, Index dindex, Array xdim, Array ydim, double x, double y) { - double iValue = Double.NaN; - int[] xyIdx = gridIndex(xdim, ydim, x, y); - if (xyIdx == null) { - return iValue; - } - - int i1 = xyIdx[0]; - int j1 = xyIdx[1]; - int i2 = xyIdx[2]; - int j2 = xyIdx[3]; - Index index = Index.factory(data.getShape()); - int n = index.getRank(); - for (int i = 0; i < n - 2; i++) { - index.setDim(i, dindex.getCurrentCounter()[i]); - } - index.setDim(n - 2, i1); - index.setDim(n - 1, j1); - double a = data.getDouble(index); - index.setDim(n - 1, j2); - double b = data.getDouble(index); - index.setDim(n - 2, i2); - index.setDim(n - 1, j1); - double c = data.getDouble(index); - index.setDim(n - 2, i2); - index.setDim(n - 1, j2); - double d = data.getDouble(index); - List dList = new ArrayList<>(); - if (!Double.isNaN(a)) { - dList.add(a); - } - if (!Double.isNaN(b)) { - dList.add(b); - } - if (!Double.isNaN(c)) { - dList.add(c); - } - if (!Double.isNaN(d)) { - dList.add(d); - } - - if (dList.isEmpty()) { - return iValue; - } else if (dList.size() == 1) { - iValue = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - iValue = aSum / dList.size(); - } else { - double dx = xdim.getDouble(j1 + 1) - xdim.getDouble(j1); - double dy = ydim.getDouble(i1 + 1) - ydim.getDouble(i1); - double x1val = a + (c - a) * (y - ydim.getDouble(i1)) / dy; - double x2val = b + (d - b) * (y - ydim.getDouble(i1)) / dy; - iValue = x1val + (x2val - x1val) * (x - xdim.getDouble(j1)) / dx; - } - - return iValue; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @return Interpolated value - */ - public static double toStation(Array data, Array xArray, Array yArray, double x, double y) { - double iValue = Double.NaN; - int nx = (int) xArray.getSize(); - int ny = (int) yArray.getSize(); - if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1) - || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) { - return iValue; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.getDouble(i)) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.getDouble(i)) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); - if (!Double.isNaN(a)) { - dList.add(a); - } - if (!Double.isNaN(b)) { - dList.add(b); - } - if (!Double.isNaN(c)) { - dList.add(c); - } - if (!Double.isNaN(d)) { - dList.add(d); - } - - if (dList.isEmpty()) { - return iValue; - } else if (dList.size() == 1) { - iValue = dList.get(0); - } else if (dList.size() <= 3) { - double aSum = 0; - for (double dd : dList) { - aSum += dd; - } - iValue = aSum / dList.size(); - } else { - double dx = xArray.getDouble(xIdx + 1) - xArray.getDouble(xIdx); - double dy = yArray.getDouble(yIdx + 1) - yArray.getDouble(yIdx); - double x1val = a + (c - a) * (y - yArray.getDouble(i1)) / dy; - double x2val = b + (d - b) * (y - yArray.getDouble(i1)) / dy; - iValue = x1val + (x2val - x1val) * (x - xArray.getDouble(j1)) / dx; - } - - return iValue; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @param missingValue Missing value - * @return Interpolated value - */ - public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y, - double missingValue) { - double iValue = Double.NaN; - int nx = xArray.size(); - int ny = yArray.size(); - if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue() - || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) { - return iValue; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.get(i).doubleValue()) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.get(i).doubleValue()) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - - if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) { - if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) { - iValue = a; - } else { - iValue = c; - } - } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) { - iValue = b; - } else { - iValue = d; - } - - return iValue; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @return Interpolated value - */ - public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y) { - //ouble iValue = Double.NaN; - int nx = xArray.size(); - int ny = yArray.size(); - if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue() - || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) { - return Double.NaN; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.get(i).doubleValue()) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.get(i).doubleValue()) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - - double iValue; - if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) { - if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) { - iValue = a; - } else { - iValue = c; - } - } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) { - iValue = b; - } else { - iValue = d; - } - - return iValue; - } - - /** - * Interpolate data to a station point - * - * @param data Data array - * @param xArray X array - * @param yArray Y array - * @param x X coordinate of the station - * @param y Y coordinate of the station - * @return Interpolated value - */ - public static double toStation_Neighbor(Array data, Array xArray, Array yArray, double x, double y) { - //ouble iValue = Double.NaN; - int nx = (int) xArray.getSize(); - int ny = (int) yArray.getSize(); - if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1) - || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) { - return Double.NaN; - } - - //Get x/y index - int xIdx = 0, yIdx = 0; - int i; - boolean isIn = false; - for (i = 1; i < nx; i++) { - if (x < xArray.getDouble(i)) { - xIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - xIdx = nx - 2; - } - isIn = false; - for (i = 1; i < ny; i++) { - if (y < yArray.getDouble(i)) { - yIdx = i - 1; - isIn = true; - break; - } - } - if (!isIn) { - yIdx = ny - 2; - } - - int i1 = yIdx; - int j1 = xIdx; - int i2 = i1 + 1; - int j2 = j1 + 1; - Index index = data.getIndex(); - double a = data.getDouble(index.set(i1, j1)); - double b = data.getDouble(index.set(i1, j2)); - double c = data.getDouble(index.set(i2, j1)); - double d = data.getDouble(index.set(i2, j2)); - - double iValue; - if (Math.abs(x - xArray.getDouble(j1)) < Math.abs(xArray.getDouble(j2) - x)) { - if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) { - iValue = a; - } else { - iValue = c; - } - } else if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) { - iValue = b; - } else { - iValue = d; - } - - return iValue; - } - - /** - * Project grid data - * - * @param data Data array - * @param xx X array - * @param yy Y array - * @param fromProj From projection - * @param toProj To projection - * @return Porjected grid data - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Object[] reproject_back(Array data, List xx, List yy, ProjectionInfo fromProj, ProjectionInfo toProj) throws InvalidRangeException { - Extent aExtent; - int xnum = xx.size(); - int ynum = yy.size(); - double xdelta = xx.get(1).doubleValue() - xx.get(0).doubleValue(); - double ydelta = yy.get(1).doubleValue() - yy.get(0).doubleValue(); - aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy); - - double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1); - double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1); - Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum}); - Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum}); - int i, j, xIdx, yIdx; - for (i = 0; i < xnum; i++) { - rx.setDouble(i, aExtent.minX + i * xDelt); - } - - for (i = 0; i < ynum; i++) { - ry.setDouble(i, aExtent.minY + i * yDelt); - } - - double x, y; - Array r = Array.factory(data.getDataType(), data.getShape()); - double[][] points = new double[1][]; - Object fill_value = Double.NaN; - switch (data.getDataType()) { - case INT: - fill_value = Integer.MIN_VALUE; - break; - case FLOAT: - fill_value = Float.NaN; - break; - } - for (i = 0; i < ynum; i++) { - for (j = 0; j < xnum; j++) { - points[0] = new double[]{rx.getDouble(j), ry.getDouble(i)}; - try { - Reproject.reprojectPoints(points, toProj, fromProj, 0, 1); - x = points[0][0]; - y = points[0][1]; - - if (x < xx.get(0).doubleValue() || x > xx.get(xx.size() - 1).doubleValue()) { - r.setObject(i * xnum + j, fill_value); - } else if (y < yy.get(0).doubleValue() || y > yy.get(yy.size() - 1).doubleValue()) { - r.setObject(i * xnum + j, fill_value); - } else { - xIdx = (int) ((x - xx.get(0).doubleValue()) / xdelta); - yIdx = (int) ((y - yy.get(0).doubleValue()) / ydelta); - r.setObject(i * xnum + j, data.getObject(yIdx * xnum + xIdx)); - } - } catch (Exception e) { - r.setObject(i * xnum + j, fill_value); - j++; - } - } - } - - return new Object[]{r, rx, ry}; - } - - /** - * Project grid data - * - * @param data Data array - * @param xx X array - * @param yy Y array - * @param fromProj From projection - * @param toProj To projection - * @param method Resample method - * @return Porjected grid data - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj, - ProjectionInfo toProj, ResampleMethods method) throws InvalidRangeException { - Extent aExtent; - int xnum = xx.size(); - int ynum = yy.size(); - aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy); - - double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1); - double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1); - int i; - Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum}); - Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum}); - for (i = 0; i < xnum; i++) { - rx.setDouble(i, aExtent.minX + i * xDelt); - } - - for (i = 0; i < ynum; i++) { - ry.setDouble(i, aExtent.minY + i * yDelt); - } - - Array[] rr = ArrayUtil.meshgrid(rx, ry); - - Array r = ArrayUtil.reproject(data, xx, yy, rr[0], rr[1], fromProj, toProj, method); - - return new Object[]{r, rx, ry}; - } - - /** - * Project grid data - * - * @param data Data array - * @param xx X array - * @param yy Y array - * @param fromProj From projection - * @param toProj To projection - * @return Porjected grid data - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj, - ProjectionInfo toProj) throws InvalidRangeException { - return reproject(data, xx, yy, fromProj, toProj, ResampleMethods.NearestNeighbor); - } - - /** - * Reproject - * - * @param data Data array - * @param x X array - * @param y Y array - * @param rx Result x array - * @param ry Result y array - * @param fromProj From projection - * @param toProj To projection - * @param fill_value Fill value - * @param resampleMethod Resample method - * @return Result arrays - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array reproject(Array data, List x, List y, Array rx, Array ry, - ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) throws InvalidRangeException { - int n = (int) rx.getSize(); - int[] dshape = data.getShape(); - int[] shape; - if (rx.getRank() == 1) { - shape = new int[1]; - shape[0] = rx.getShape()[0]; - } else { - shape = new int[data.getRank()]; - for (int i = 0; i < shape.length; i++) { - if (i == shape.length - 2) { - shape[i] = rx.getShape()[0]; - } else if (i == shape.length - 1) { - shape[i] = rx.getShape()[1]; - } else { - shape[i] = data.getShape()[i]; - } - } - } - Array r = Array.factory(data.getDataType(), shape); - - double[][] points = new double[n][]; - for (int i = 0; i < n; i++) { - points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)}; - } - if (!fromProj.equals(toProj)) { - Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length); - } - double xx, yy; - if (resampleMethod == ResampleMethods.Bilinear) { - if (shape.length <= 2) { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - if (Double.isNaN(xx) || Double.isNaN(yy)) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, toStation(data, x, y, xx, yy, fill_value)); - } - } - } else { - Index indexr = r.getIndex(); - int[] current, cc = null; - boolean isNew; - Array ndata = null; - int k; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - isNew = true; - if (i > 0) { - for (int j = 0; j < shape.length - 2; j++) { - if (cc[j] != current[j]) { - isNew = false; - break; - } - } - } - cc = Arrays.copyOf(current, current.length); - if (isNew) { - List ranges = new ArrayList<>(); - for (int j = 0; j < shape.length - 2; j++) { - ranges.add(new Range(current[j], current[j], 1)); - } - ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1)); - ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1)); - ndata = data.section(ranges).reduce(); - } - k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1]; - xx = points[k][0]; - yy = points[k][1]; - if (Double.isNaN(xx) || Double.isNaN(yy)) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, toStation(ndata, x, y, xx, yy, fill_value)); - } - indexr.incr(); - } - } - } else if (shape.length <= 2) { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - if (Double.isNaN(xx) || Double.isNaN(yy)) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value)); - } - } - } else { - Index indexr = r.getIndex(); - int[] current, cc = null; - boolean isNew; - Array ndata = null; - int k; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - isNew = true; - if (i > 0) { - for (int j = 0; j < shape.length - 2; j++) { - if (cc[j] != current[j]) { - isNew = false; - break; - } - } - } - cc = Arrays.copyOf(current, current.length); - if (isNew) { - List ranges = new ArrayList<>(); - for (int j = 0; j < shape.length - 2; j++) { - ranges.add(new Range(current[j], current[j], 1)); - } - ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1)); - ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1)); - ndata = data.section(ranges).reduce(); - } - k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1]; - xx = points[k][0]; - yy = points[k][1]; - if (Double.isNaN(xx) || Double.isNaN(yy)) { - r.setObject(i, Double.NaN); - } else { - r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy, fill_value)); - } - indexr.incr(); - } - } - - return r; - } - - /** - * Reproject - * - * @param data Data array - * @param x X array - * @param y Y array - * @param rx Result x array - * @param ry Result y array - * @param fromProj From projection - * @param toProj To projection - * @param resampleMethod Resample method - * @return Result arrays - * @throws org.meteoinfo.ndarray.InvalidRangeException - */ - public static Array reproject(Array data, List x, List y, Array rx, Array ry, - ProjectionInfo fromProj, ProjectionInfo toProj, ResampleMethods resampleMethod) throws InvalidRangeException { - int n = (int) rx.getSize(); - int[] dshape = data.getShape(); - int[] shape; - if (rx.getRank() == 1) { - shape = new int[1]; - shape[0] = rx.getShape()[0]; - } else { - shape = new int[data.getRank()]; - for (int i = 0; i < shape.length; i++) { - if (i == shape.length - 2) { - shape[i] = rx.getShape()[0]; - } else if (i == shape.length - 1) { - shape[i] = rx.getShape()[1]; - } else { - shape[i] = data.getShape()[i]; - } - } - } - Array r = Array.factory(data.getDataType(), shape); - - double[][] points = new double[n][]; - for (int i = 0; i < n; i++) { - points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)}; - } - if (!fromProj.equals(toProj)) { - Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length); - } - double xx, yy; - if (resampleMethod == ResampleMethods.Bilinear) { - if (shape.length <= 2) { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - r.setObject(i, toStation(data, x, y, xx, yy)); - } - } else { - Index indexr = r.getIndex(); - int[] current, cc = null; - boolean isNew; - Array ndata = null; - int k; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - isNew = true; - if (i > 0) { - for (int j = 0; j < shape.length - 2; j++) { - if (cc[j] != current[j]) { - isNew = false; - break; - } - } - } - cc = Arrays.copyOf(current, current.length); - if (isNew) { - List ranges = new ArrayList<>(); - for (int j = 0; j < shape.length - 2; j++) { - ranges.add(new Range(current[j], current[j], 1)); - } - ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1)); - ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1)); - ndata = data.section(ranges).reduce(); - } - k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1]; - xx = points[k][0]; - yy = points[k][1]; - r.setObject(i, toStation(ndata, x, y, xx, yy)); - indexr.incr(); - } - } - } else if (shape.length == 2) { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - r.setObject(i, toStation_Neighbor(data, x, y, xx, yy)); - } - } else { - Index indexr = r.getIndex(); - int[] current, cc = null; - boolean isNew; - Array ndata = null; - int k; - for (int i = 0; i < r.getSize(); i++) { - current = indexr.getCurrentCounter(); - isNew = true; - if (i > 0) { - for (int j = 0; j < shape.length - 2; j++) { - if (cc[j] != current[j]) { - isNew = false; - break; - } - } - } - cc = Arrays.copyOf(current, current.length); - if (isNew) { - List ranges = new ArrayList<>(); - for (int j = 0; j < shape.length - 2; j++) { - ranges.add(new Range(current[j], current[j], 1)); - } - ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1)); - ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1)); - ndata = data.section(ranges).reduce(); - } - k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1]; - xx = points[k][0]; - yy = points[k][1]; - r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy)); - indexr.incr(); - } - } - - return r; - } - - /** - * Reproject - * - * @param data Data array - * @param x X array - * @param y Y array - * @param rx Result x array - * @param ry Result y array - * @param fromProj From projection - * @param toProj To projection - * @param fill_value Fill value - * @param resampleMethod Resample method - * @return Result arrays - */ - public static Array reproject(Array data, List x, List y, List rx, List ry, - ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) { - int n = rx.size() * ry.size(); - int[] shape = new int[]{ry.size(), rx.size()}; - Array r = Array.factory(data.getDataType(), shape); - - double[][] points = new double[n][]; - for (int i = 0; i < ry.size(); i++) { - for (int j = 0; j < rx.size(); j++) { - points[i * rx.size() + j] = new double[]{rx.get(j).doubleValue(), ry.get(i).doubleValue()}; - } - } - if (!fromProj.equals(toProj)) { - Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length); - } - double xx, yy; - if (resampleMethod == ResampleMethods.Bilinear) { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - r.setObject(i, toStation(data, x, y, xx, yy, fill_value)); - } - } else { - for (int i = 0; i < n; i++) { - xx = points[i][0]; - yy = points[i][1]; - r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value)); - } - } - - return r; - } - - /** - * Computes the smallest convex Polygon that contains all the - * points - * - * @param x X array - * @param y Y array - * @return PolygonShape - */ - public static PolygonShape convexHull(Array x, Array y) { - int n = (int) x.getSize(); - Geometry[] geos = new Geometry[n]; - GeometryFactory factory = new GeometryFactory(); - for (int i = 0; i < n; i++) { - Coordinate c = new Coordinate(x.getDouble(i), y.getDouble(i)); - geos[i] = factory.createPoint(c); - } - Geometry gs = factory.createGeometryCollection(geos); - Geometry ch = gs.convexHull(); - return new PolygonShape(ch); - } - - // - // - // -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/Chart.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/Chart.java index 46d418b2..1b99e49c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/Chart.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/Chart.java @@ -1,902 +1,902 @@ -/* This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.chart; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.chart.plot.MapPlot; -import org.meteoinfo.chart.plot.Plot; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.PointF; - -/** - * - * @author Yaqiang Wang - * yaqiang.wang@gmail.com - */ -public class Chart { - - // - private List plots; - private int currentPlot; - private int rowNum; - private int columnNum; - private ChartText title; - private ChartText subTitle; - private List texts; - private ChartLegend legend; - private Color background; - //private boolean drawBackground; - private boolean drawLegend; - private Rectangle2D plotArea; - private boolean antiAlias; - private boolean symbolAntialias; - private ChartPanel parent; - - // - // - /** - * Constructor - */ - public Chart() { - this.drawLegend = false; - this.background = Color.white; - //this.drawBackground = true; - this.antiAlias = false; - this.symbolAntialias = true; - this.rowNum = 1; - this.columnNum = 1; - this.plots = new ArrayList<>(); - this.currentPlot = -1; - this.texts = new ArrayList<>(); - } - - /** - * Constructor - * - * @param parent ChartPanel parent - */ - public Chart(ChartPanel parent) { - this(); - this.parent = parent; - } - - /** - * Constructor - * - * @param plot Plot - * @param parent ChartPanel - */ - public Chart(Plot plot, ChartPanel parent) { - this(parent); - this.plots.add(plot); - } - - /** - * Constructor - * - * @param plot Plot - */ - public Chart(Plot plot) { - this(plot, null); - } - - /** - * Constructor - * - * @param title Title - * @param plot Plot - * @param parent ChartPanel - */ - public Chart(String title, Plot plot, ChartPanel parent) { - this(plot, parent); - if (title == null) { - this.title = null; - } else { - this.title = new ChartText(title); - } - } - - /** - * Constructor - * - * @param title Title - * @param plot Plot - */ - public Chart(String title, Plot plot) { - this(title, plot, null); - } - - // - // - /** - * Set ChartPanel parent - * - * @param value ChartPanel - */ - public void setParent(ChartPanel value) { - this.parent = value; - for (Plot plot : this.plots) { - if (plot instanceof MapPlot) { - ((MapPlot) plot).setParent(value); - } - } - } - - /** - * Get plot - * - * @return Plot - */ - public List getPlots() { - return plots; - } - - /** - * Get current plot - * - * @return Current plot - */ - public Plot getCurrentPlot() { - if (this.plots.isEmpty()) { - return null; - } - - if (this.currentPlot < 0 || this.currentPlot >= this.plots.size()) { - this.currentPlot = this.plots.size() - 1; - } - return this.plots.get(this.currentPlot); - } - - /** - * Set current plot - * - * @param value Current plot - */ - public void setCurrentPlot(Plot value) { - if (this.plots.isEmpty()) { - this.addPlot(value); - //this.currentPlot = 0; - } else if (this.currentPlot == -1) { - this.plots.add(value); - } else { - if (this.currentPlot >= this.plots.size()) { - this.currentPlot = this.plots.size() - 1; - } - Plot plot = this.plots.get(this.currentPlot); - value.isSubPlot = plot.isSubPlot; - value.columnIndex = plot.columnIndex; - value.rowIndex = plot.rowIndex; - this.plots.set(this.currentPlot, value); - } - } - - /** - * Set current plot index - * - * @param value Current plot index - */ - public void setCurrentPlot(int value) { - this.currentPlot = value; - } - - /** - * Get the first plot - * - * @return Plot - */ - public Plot getPlot() { - if (this.plots.isEmpty()) { - return null; - } - - return this.plots.get(0); - } - - /** - * Get row number of sub plots - * - * @return Row number of sub plots - */ - public int getRowNum() { - return this.rowNum; - } - - /** - * Set row number of sub plots - * - * @param value Row number of sub plots - */ - public void setRowNum(int value) { - this.rowNum = value; - } - - /** - * Get column number of sub plots - * - * @return Column number of sub plots - */ - public int getColumnNum() { - return this.columnNum; - } - - /** - * Set column number of sub plots - * - * @param value Column number of sub plots - */ - public void setColumnNum(int value) { - this.columnNum = value; - } - - /** - * Get title - * - * @return Title - */ - public ChartText getTitle() { - return title; - } - - /** - * Set title - * - * @param value Title - */ - public void setTitle(ChartText value) { - title = value; - } - - /** - * Get sub title - * - * @return Sub title - */ - public ChartText getSubTitle() { - return subTitle; - } - - /** - * Set sub title - * - * @param value Sub title - */ - public void setSubTitle(ChartText value) { - subTitle = value; - } - - /** - * Get background - * - * @return Background - */ - public Color getBackground() { - return this.background; - } - - /** - * Set background - * - * @param value Background - */ - public void setBackground(Color value) { - this.background = value; - } - -// /** -// * Get if draw background -// * -// * @return Boolean -// */ -// public boolean isDrawBackground() { -// return this.drawBackground; -// } - -// /** -// * Set if draw background -// * -// * @param value Boolean -// */ -// public void setDrawBackground(boolean value) { -// this.drawBackground = value; -// } - - /** - * Get chart legend - * - * @return Chart legend - */ - public ChartLegend getLegend() { - return this.legend; - } - - /** - * Get if draw legend - * - * @return If draw legend - */ - public boolean isDrawLegend() { - return this.drawLegend; - } - - /** - * Set if draw legend - * - * @param value Boolean - */ - public void setDrawLegend(boolean value) { - this.drawLegend = value; - } - - /** - * Get plot area - * - * @return Plot area - */ - public Rectangle2D getPlotArea() { - return this.plotArea; - } - - /** - * Get if is anti-alias - * - * @return Boolean - */ - public boolean isAntiAlias() { - return this.antiAlias; - } - - /** - * Set if is anti-alias - * - * @param value Boolean - */ - public void setAntiAlias(boolean value) { - this.antiAlias = value; - } - - /** - * Get symbol antialias - * @return Boolean - */ - public boolean isSymbolAntialias() { - return this.symbolAntialias; - } - - /** - * Set symbol antialias - * @param value Boolean - */ - public void setSymbolAntialias(boolean value) { - this.symbolAntialias = value; - } - - // - // - /** - * Draw plot - * - * @param g Graphics2D - * @param area Drawing area - */ - public void draw(Graphics2D g, Rectangle2D area) { - g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); - if (antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - //g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); - g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT); - //g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); - } - - AffineTransform oldMatrix = g.getTransform(); - Rectangle oldRegion = g.getClipBounds(); - g.setClip(area); - g.translate(area.getX(), area.getY()); - - //Draw background - if (this.background != null) { - g.setColor(background); - g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); - } - - //Draw title - float y = 5; - if (title != null) { - g.setColor(title.getColor()); - g.setFont(title.getFont()); - float x = (float) area.getWidth() / 2; - //y -= this.title.getHeight(g) - 5; - //FontMetrics metrics = g.getFontMetrics(title.getFont()); - //x -= metrics.stringWidth(title.getText()) / 2; - //y += metrics.getHeight(); - int i = 0; - for (String text : title.getTexts()) { - Dimension dim = Draw.getStringDimension(text, g); - if (i == 0) { - y += dim.getHeight(); - } - Draw.drawString(g, text, x - dim.width / 2, y); - g.setFont(title.getFont()); - y += dim.height + title.getLineSpace(); - i += 1; - } - y += 5; - } - - //Draw plot - plotArea = this.getPlotArea(g, area); - //plotArea = area; - if (plotArea.getWidth() < 20 || plotArea.getHeight() < 20) { - g.setTransform(oldMatrix); - g.setClip(oldRegion); - return; - } - - if (this.plots.size() > 0) { - //double zoom = this.getPositionAreaZoom(g, plotArea); - //Margin tightInset = this.getPlotsTightInset(g, plotArea); - Margin shrink = this.getPlotsShrink(g, plotArea); - for (int i = 0; i < this.plots.size(); i++) { - Plot plot = this.plots.get(i); - plot.setSymbolAntialias(this.symbolAntialias); - if (plot.isOuterPosActive()){ - if (plot.isSubPlot || plot.isSameShrink()) { - plot.setPlotShrink(shrink); - } else { - //plot.setPlotShrink(this.getPlotShrink(g, area, plot)); - plot.setPlotShrink(this.getPlotShrink(g, plotArea, plot)); - } - } - if (plot instanceof MapPlot) { - ((MapPlot) plot).setAntialias(this.antiAlias); - } - plot.draw(g, plotArea); - } - } - - //Draw text - drawText(g, area); - - //Draw legend - if (this.drawLegend) { - Dimension dim = this.legend.getLegendDimension(g, new Dimension((int) area.getWidth(), (int) area.getHeight())); - float x = 0; - switch (this.legend.getPosition()) { - case UPPER_CENTER_OUTSIDE: - x = (float) area.getWidth() / 2 - dim.width / 2; - y += 5; - break; - case LOWER_CENTER_OUTSIDE: - x = (float) area.getWidth() / 2 - dim.width / 2; - y += plotArea.getHeight() + 5; - break; - case LEFT_OUTSIDE: - x = 10; - y = (float) area.getHeight() / 2 - dim.height / 2; - break; - case RIGHT_OUTSIDE: - x = (float) plotArea.getWidth() + 10; - y = (float) area.getHeight() / 2 - dim.height / 2; - break; - } - this.legend.draw(g, new PointF(x, y)); - } - - g.setTransform(oldMatrix); - g.setClip(oldRegion); - } - - void drawText(Graphics2D g, Rectangle2D area) { - float x, y; - for (ChartText text : this.texts) { - x = (float) (area.getWidth() * text.getX()); - y = (float) (area.getHeight() * (1 - text.getY())); - Dimension dim = Draw.getStringDimension(text.getText(), g); - Rectangle.Double rect = new Rectangle.Double(x, y, dim.getWidth(), dim.getHeight()); - if (text.isFill()) { - g.setColor(text.getBackground()); - g.fill(rect); - } - if (text.isDrawNeatline()) { - g.setColor(text.getNeatlineColor()); - Stroke oldStroke = g.getStroke(); - g.setStroke(new BasicStroke(text.getNeatlineSize())); - g.draw(rect); - g.setStroke(oldStroke); - } - g.setFont(text.getFont()); - g.setColor(text.getColor()); - Draw.drawString(g, text.getText(), x, y); - } - } - - private Rectangle2D getPlotArea(Graphics2D g, Rectangle2D area) { - Rectangle2D pArea = new Rectangle2D.Double(); - int edge = 0; - int top = edge; - int left = edge; - int right = edge; - int bottom = edge; - if (this.title != null) { - top += this.title.getTrueDimension(g).height + 12; - } - pArea.setRect(left, top, area.getWidth() - left - right, area.getHeight() - top - bottom); - - return pArea; - } - - private Rectangle2D getPlotArea_bak(Graphics2D g, Rectangle2D area) { - Rectangle2D pArea = new Rectangle2D.Double(); - int edge = 2; - int top = edge; - int left = edge; - int right = edge; - int bottom = edge; - if (this.title != null) { - top += this.title.getTrueDimension(g).height + 10; - } - if (this.drawLegend) { - Dimension dim = this.legend.getLegendDimension(g, new Dimension((int) area.getWidth(), (int) area.getHeight())); - switch (this.legend.getPosition()) { - case UPPER_CENTER_OUTSIDE: - top += dim.height + 10; - break; - case LOWER_CENTER_OUTSIDE: - bottom += dim.height + 10; - break; - case LEFT_OUTSIDE: - left += dim.width + 10; - break; - case RIGHT_OUTSIDE: - right += dim.width + 10; - break; - } - } - pArea.setRect(left, top, area.getWidth() - left - right, area.getHeight() - top - bottom); - - return pArea; - } - - private Margin getPlotShrink(Graphics2D g, Rectangle2D area, Plot plot) { - Margin shrink; - if (plot.isSubPlot) { - double rowHeight = area.getHeight() / this.rowNum; - double colWidth = area.getWidth() / this.columnNum; - double x = area.getX() + plot.columnIndex * colWidth; - double y = area.getY() + plot.rowIndex * rowHeight; - Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); - plot.setOuterPositionArea(subPlotArea); - plot.updatePosition(area, subPlotArea); - Rectangle2D positionArea = plot.getPositionArea(area); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - shrink = plot.getPlotShrink(); - } else { - plot.setOuterPositionArea(area); - Rectangle2D positionArea = plot.getPositionArea(area); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - shrink = plot.getPlotShrink(); - //shrink = tightInset; - } - - return shrink; - } - - private Margin getPlotsShrink(Graphics2D g, Rectangle2D area) { - Margin pshrink = null, shrink; - for (int i = 0; i < this.plots.size(); i++) { - Plot plot = this.plots.get(i); - plot.setOuterPositionArea(plot.getOuterPositionArea(area)); - Rectangle2D positionArea = plot.getPositionArea(area); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - shrink = plot.getPlotShrink(); - if (i == 0) { - pshrink = shrink; - } else if (pshrink != null) { - pshrink = pshrink.extend(shrink); - } - } - - return pshrink; - } - - private Margin getPlotsShrink_bak(Graphics2D g, Rectangle2D area) { - Margin pshrink = null, shrink; - for (int i = 0; i < this.plots.size(); i++) { - Plot plot = this.plots.get(i); - if (plot.isSubPlot) { - double rowHeight = area.getHeight() / this.rowNum; - double colWidth = area.getWidth() / this.columnNum; - double x = area.getX() + plot.columnIndex * colWidth; - double y = area.getY() + plot.rowIndex * rowHeight; - Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); - plot.setOuterPositionArea(subPlotArea); - plot.updatePosition(area, subPlotArea); - Rectangle2D positionArea = plot.getPositionArea(area); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - shrink = plot.getPlotShrink(); - } else { - plot.setOuterPositionArea(area); - Rectangle2D positionArea = plot.getPositionArea(area); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - shrink = plot.getPlotShrink(); - } - if (i == 0) { - pshrink = shrink; - } else if (pshrink != null) { - pshrink = pshrink.extend(shrink); - } - } - - return pshrink; - } - - private Margin getPlotsTightInset(Graphics2D g, Rectangle2D area) { - int i = 0; - Margin pti = null, tightInset; - for (Plot plot : this.plots) { - if (plot.isSubPlot) { - double rowHeight = area.getHeight() / this.rowNum; - double colWidth = area.getWidth() / this.columnNum; - double x = area.getX() + plot.columnIndex * colWidth; - double y = area.getY() + plot.rowIndex * rowHeight; - Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); - plot.setOuterPositionArea(subPlotArea); - plot.updatePosition(area, subPlotArea); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - tightInset = plot.getTightInset(g, positionArea); - } else { - plot.setOuterPositionArea(area); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - tightInset = plot.getTightInset(g, positionArea); - } - if (i == 0) { - pti = tightInset; - } else if (pti != null) { - pti = pti.extend(tightInset); - } - i += 1; - } - - return pti; - } - - private double getPositionAreaZoom(Graphics2D g, Rectangle2D area) { - double zoom = 1.0; - for (Plot plot : this.plots) { - if (plot.isSubPlot) { - double rowHeight = area.getHeight() / this.rowNum; - double colWidth = area.getWidth() / this.columnNum; - double x = area.getX() + plot.columnIndex * colWidth; - double y = area.getY() + plot.rowIndex * rowHeight; - Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); - plot.setOuterPositionArea(subPlotArea); - plot.updatePosition(area, subPlotArea); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - double zoom1 = plot.updatePostionAreaZoom(); - if (zoom1 < zoom) { - zoom = zoom1; - } - } else { - plot.setOuterPositionArea(area); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - double zoom1 = plot.updatePostionAreaZoom(); - if (zoom1 < zoom) { - zoom = zoom1; - } - } - } - - return zoom; - } - - private Rectangle2D getSubPlotArea(Graphics2D g, Plot plot, Rectangle2D area) { - if (plot.isSubPlot) { - double rowHeight = area.getHeight() / this.rowNum; - double colWidth = area.getWidth() / this.columnNum; - double x = area.getX() + plot.columnIndex * colWidth; - double y = area.getY() + plot.rowIndex * rowHeight; - Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); - plot.setOuterPositionArea(subPlotArea); - plot.updatePosition(area, subPlotArea); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - double zoom = plot.updatePostionAreaZoom(); - plot.setPositionAreaZoom(zoom); - return subPlotArea; - } else { - plot.setOuterPositionArea(area); - Rectangle2D positionArea = plot.getPositionArea(); - plot.setPositionArea(positionArea); - Margin tightInset = plot.getTightInset(g, positionArea); - plot.setTightInset(tightInset); - double zoom = plot.updatePostionAreaZoom(); - plot.setPositionAreaZoom(zoom); - //return tightInset.getArea(positionArea); - return area; - } - } - - /** - * Get graph area - * - * @return Get graph area - */ - public Rectangle2D getGraphArea() { - Rectangle2D rect = this.plots.get(0).getPositionArea(); - double left = rect.getX() + this.plotArea.getX(); - double top = rect.getY() + this.plotArea.getY(); - return new Rectangle2D.Double(left, top, rect.getWidth(), rect.getHeight()); - } - - /** - * Find a plot by point - * - * @param x X - * @param y Y - * @return Plot - */ - public Plot findPlot(int x, int y) { - for (Plot plot : this.plots) { - Rectangle2D area = plot.getPositionArea(); - if (area.contains(x, y)) { - return plot; - } - } - - return null; - } - - /** - * Clear plots - */ - public void clearPlots() { - this.plots.clear(); - } - - /** - * Clear texts - */ - public void clearTexts() { - this.texts.clear(); - } - - /** - * Remove a plot - * - * @param plot The plot - */ - public void removePlot(Plot plot) { - this.plots.remove(plot); - } - - /** - * Add a plot - * - * @param plot Plot - */ - public void addPlot(Plot plot) { - if (plot instanceof MapPlot) { - ((MapPlot) plot).setParent(parent); - } - this.plots.add(plot); - } - - /** - * Set plot - * - * @param plot Plot - */ - public void setPlot(Plot plot) { - if (plot instanceof MapPlot) { - ((MapPlot) plot).setParent(parent); - } - this.plots.clear(); - this.plots.add(plot); - } - - /** - * Get plot by plot index - * - * @param plotIdx Plot index - begin with 1 - * @return Plot index - */ - public Plot getPlot(int plotIdx) { - for (Plot plot : this.plots) { - int pIdx = plot.rowIndex * this.columnNum + plot.columnIndex + 1; - if (pIdx == plotIdx) { - return plot; - } - } - - if (plotIdx > 0 && plotIdx <= this.plots.size()) - return this.plots.get(plotIdx - 1); - else - return null; - } - - /** - * Get plot index - * @param plot The plot - * @return Plot index - */ - public int getPlotIndex(Plot plot){ - return this.plots.indexOf(plot); - } - - /** - * Check if has web map layer - * - * @return Boolean - */ - public boolean hasWebMap() { - for (Plot plot : this.plots) { - if (plot instanceof MapPlot) { - MapPlot mp = (MapPlot) plot; - if (mp.hasWebMapLayer()) { - return true; - } - } - } - - return false; - } - - /** - * Add text - * - * @param text Text - */ - public void addText(ChartText text) { - this.texts.add(text); - } - // - -} +/* This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.chart; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.chart.plot.MapPlot; +import org.meteoinfo.chart.plot.Plot; +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; + +/** + * + * @author Yaqiang Wang + * yaqiang.wang@gmail.com + */ +public class Chart { + + // + private List plots; + private int currentPlot; + private int rowNum; + private int columnNum; + private ChartText title; + private ChartText subTitle; + private List texts; + private ChartLegend legend; + private Color background; + //private boolean drawBackground; + private boolean drawLegend; + private Rectangle2D plotArea; + private boolean antiAlias; + private boolean symbolAntialias; + private ChartPanel parent; + + // + // + /** + * Constructor + */ + public Chart() { + this.drawLegend = false; + this.background = Color.white; + //this.drawBackground = true; + this.antiAlias = false; + this.symbolAntialias = true; + this.rowNum = 1; + this.columnNum = 1; + this.plots = new ArrayList<>(); + this.currentPlot = -1; + this.texts = new ArrayList<>(); + } + + /** + * Constructor + * + * @param parent ChartPanel parent + */ + public Chart(ChartPanel parent) { + this(); + this.parent = parent; + } + + /** + * Constructor + * + * @param plot Plot + * @param parent ChartPanel + */ + public Chart(Plot plot, ChartPanel parent) { + this(parent); + this.plots.add(plot); + } + + /** + * Constructor + * + * @param plot Plot + */ + public Chart(Plot plot) { + this(plot, null); + } + + /** + * Constructor + * + * @param title Title + * @param plot Plot + * @param parent ChartPanel + */ + public Chart(String title, Plot plot, ChartPanel parent) { + this(plot, parent); + if (title == null) { + this.title = null; + } else { + this.title = new ChartText(title); + } + } + + /** + * Constructor + * + * @param title Title + * @param plot Plot + */ + public Chart(String title, Plot plot) { + this(title, plot, null); + } + + // + // + /** + * Set ChartPanel parent + * + * @param value ChartPanel + */ + public void setParent(ChartPanel value) { + this.parent = value; + for (Plot plot : this.plots) { + if (plot instanceof MapPlot) { + ((MapPlot) plot).setParent(value); + } + } + } + + /** + * Get plot + * + * @return Plot + */ + public List getPlots() { + return plots; + } + + /** + * Get current plot + * + * @return Current plot + */ + public Plot getCurrentPlot() { + if (this.plots.isEmpty()) { + return null; + } + + if (this.currentPlot < 0 || this.currentPlot >= this.plots.size()) { + this.currentPlot = this.plots.size() - 1; + } + return this.plots.get(this.currentPlot); + } + + /** + * Set current plot + * + * @param value Current plot + */ + public void setCurrentPlot(Plot value) { + if (this.plots.isEmpty()) { + this.addPlot(value); + //this.currentPlot = 0; + } else if (this.currentPlot == -1) { + this.plots.add(value); + } else { + if (this.currentPlot >= this.plots.size()) { + this.currentPlot = this.plots.size() - 1; + } + Plot plot = this.plots.get(this.currentPlot); + value.isSubPlot = plot.isSubPlot; + value.columnIndex = plot.columnIndex; + value.rowIndex = plot.rowIndex; + this.plots.set(this.currentPlot, value); + } + } + + /** + * Set current plot index + * + * @param value Current plot index + */ + public void setCurrentPlot(int value) { + this.currentPlot = value; + } + + /** + * Get the first plot + * + * @return Plot + */ + public Plot getPlot() { + if (this.plots.isEmpty()) { + return null; + } + + return this.plots.get(0); + } + + /** + * Get row number of sub plots + * + * @return Row number of sub plots + */ + public int getRowNum() { + return this.rowNum; + } + + /** + * Set row number of sub plots + * + * @param value Row number of sub plots + */ + public void setRowNum(int value) { + this.rowNum = value; + } + + /** + * Get column number of sub plots + * + * @return Column number of sub plots + */ + public int getColumnNum() { + return this.columnNum; + } + + /** + * Set column number of sub plots + * + * @param value Column number of sub plots + */ + public void setColumnNum(int value) { + this.columnNum = value; + } + + /** + * Get title + * + * @return Title + */ + public ChartText getTitle() { + return title; + } + + /** + * Set title + * + * @param value Title + */ + public void setTitle(ChartText value) { + title = value; + } + + /** + * Get sub title + * + * @return Sub title + */ + public ChartText getSubTitle() { + return subTitle; + } + + /** + * Set sub title + * + * @param value Sub title + */ + public void setSubTitle(ChartText value) { + subTitle = value; + } + + /** + * Get background + * + * @return Background + */ + public Color getBackground() { + return this.background; + } + + /** + * Set background + * + * @param value Background + */ + public void setBackground(Color value) { + this.background = value; + } + +// /** +// * Get if draw background +// * +// * @return Boolean +// */ +// public boolean isDrawBackground() { +// return this.drawBackground; +// } + +// /** +// * Set if draw background +// * +// * @param value Boolean +// */ +// public void setDrawBackground(boolean value) { +// this.drawBackground = value; +// } + + /** + * Get chart legend + * + * @return Chart legend + */ + public ChartLegend getLegend() { + return this.legend; + } + + /** + * Get if draw legend + * + * @return If draw legend + */ + public boolean isDrawLegend() { + return this.drawLegend; + } + + /** + * Set if draw legend + * + * @param value Boolean + */ + public void setDrawLegend(boolean value) { + this.drawLegend = value; + } + + /** + * Get plot area + * + * @return Plot area + */ + public Rectangle2D getPlotArea() { + return this.plotArea; + } + + /** + * Get if is anti-alias + * + * @return Boolean + */ + public boolean isAntiAlias() { + return this.antiAlias; + } + + /** + * Set if is anti-alias + * + * @param value Boolean + */ + public void setAntiAlias(boolean value) { + this.antiAlias = value; + } + + /** + * Get symbol antialias + * @return Boolean + */ + public boolean isSymbolAntialias() { + return this.symbolAntialias; + } + + /** + * Set symbol antialias + * @param value Boolean + */ + public void setSymbolAntialias(boolean value) { + this.symbolAntialias = value; + } + + // + // + /** + * Draw plot + * + * @param g Graphics2D + * @param area Drawing area + */ + public void draw(Graphics2D g, Rectangle2D area) { + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + if (antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + //g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT); + //g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); + } + + AffineTransform oldMatrix = g.getTransform(); + Rectangle oldRegion = g.getClipBounds(); + g.setClip(area); + g.translate(area.getX(), area.getY()); + + //Draw background + if (this.background != null) { + g.setColor(background); + g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); + } + + //Draw title + float y = 5; + if (title != null) { + g.setColor(title.getColor()); + g.setFont(title.getFont()); + float x = (float) area.getWidth() / 2; + //y -= this.title.getHeight(g) - 5; + //FontMetrics metrics = g.getFontMetrics(title.getFont()); + //x -= metrics.stringWidth(title.getText()) / 2; + //y += metrics.getHeight(); + int i = 0; + for (String text : title.getTexts()) { + Dimension dim = Draw.getStringDimension(text, g); + if (i == 0) { + y += dim.getHeight(); + } + Draw.drawString(g, text, x - dim.width / 2, y); + g.setFont(title.getFont()); + y += dim.height + title.getLineSpace(); + i += 1; + } + y += 5; + } + + //Draw plot + plotArea = this.getPlotArea(g, area); + //plotArea = area; + if (plotArea.getWidth() < 20 || plotArea.getHeight() < 20) { + g.setTransform(oldMatrix); + g.setClip(oldRegion); + return; + } + + if (this.plots.size() > 0) { + //double zoom = this.getPositionAreaZoom(g, plotArea); + //Margin tightInset = this.getPlotsTightInset(g, plotArea); + Margin shrink = this.getPlotsShrink(g, plotArea); + for (int i = 0; i < this.plots.size(); i++) { + Plot plot = this.plots.get(i); + plot.setSymbolAntialias(this.symbolAntialias); + if (plot.isOuterPosActive()){ + if (plot.isSubPlot || plot.isSameShrink()) { + plot.setPlotShrink(shrink); + } else { + //plot.setPlotShrink(this.getPlotShrink(g, area, plot)); + plot.setPlotShrink(this.getPlotShrink(g, plotArea, plot)); + } + } + if (plot instanceof MapPlot) { + ((MapPlot) plot).setAntialias(this.antiAlias); + } + plot.draw(g, plotArea); + } + } + + //Draw text + drawText(g, area); + + //Draw legend + if (this.drawLegend) { + Dimension dim = this.legend.getLegendDimension(g, new Dimension((int) area.getWidth(), (int) area.getHeight())); + float x = 0; + switch (this.legend.getPosition()) { + case UPPER_CENTER_OUTSIDE: + x = (float) area.getWidth() / 2 - dim.width / 2; + y += 5; + break; + case LOWER_CENTER_OUTSIDE: + x = (float) area.getWidth() / 2 - dim.width / 2; + y += plotArea.getHeight() + 5; + break; + case LEFT_OUTSIDE: + x = 10; + y = (float) area.getHeight() / 2 - dim.height / 2; + break; + case RIGHT_OUTSIDE: + x = (float) plotArea.getWidth() + 10; + y = (float) area.getHeight() / 2 - dim.height / 2; + break; + } + this.legend.draw(g, new PointF(x, y)); + } + + g.setTransform(oldMatrix); + g.setClip(oldRegion); + } + + void drawText(Graphics2D g, Rectangle2D area) { + float x, y; + for (ChartText text : this.texts) { + x = (float) (area.getWidth() * text.getX()); + y = (float) (area.getHeight() * (1 - text.getY())); + Dimension dim = Draw.getStringDimension(text.getText(), g); + Rectangle.Double rect = new Rectangle.Double(x, y, dim.getWidth(), dim.getHeight()); + if (text.isFill()) { + g.setColor(text.getBackground()); + g.fill(rect); + } + if (text.isDrawNeatline()) { + g.setColor(text.getNeatlineColor()); + Stroke oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(text.getNeatlineSize())); + g.draw(rect); + g.setStroke(oldStroke); + } + g.setFont(text.getFont()); + g.setColor(text.getColor()); + Draw.drawString(g, text.getText(), x, y); + } + } + + private Rectangle2D getPlotArea(Graphics2D g, Rectangle2D area) { + Rectangle2D pArea = new Rectangle2D.Double(); + int edge = 0; + int top = edge; + int left = edge; + int right = edge; + int bottom = edge; + if (this.title != null) { + top += this.title.getTrueDimension(g).height + 12; + } + pArea.setRect(left, top, area.getWidth() - left - right, area.getHeight() - top - bottom); + + return pArea; + } + + private Rectangle2D getPlotArea_bak(Graphics2D g, Rectangle2D area) { + Rectangle2D pArea = new Rectangle2D.Double(); + int edge = 2; + int top = edge; + int left = edge; + int right = edge; + int bottom = edge; + if (this.title != null) { + top += this.title.getTrueDimension(g).height + 10; + } + if (this.drawLegend) { + Dimension dim = this.legend.getLegendDimension(g, new Dimension((int) area.getWidth(), (int) area.getHeight())); + switch (this.legend.getPosition()) { + case UPPER_CENTER_OUTSIDE: + top += dim.height + 10; + break; + case LOWER_CENTER_OUTSIDE: + bottom += dim.height + 10; + break; + case LEFT_OUTSIDE: + left += dim.width + 10; + break; + case RIGHT_OUTSIDE: + right += dim.width + 10; + break; + } + } + pArea.setRect(left, top, area.getWidth() - left - right, area.getHeight() - top - bottom); + + return pArea; + } + + private Margin getPlotShrink(Graphics2D g, Rectangle2D area, Plot plot) { + Margin shrink; + if (plot.isSubPlot) { + double rowHeight = area.getHeight() / this.rowNum; + double colWidth = area.getWidth() / this.columnNum; + double x = area.getX() + plot.columnIndex * colWidth; + double y = area.getY() + plot.rowIndex * rowHeight; + Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); + plot.setOuterPositionArea(subPlotArea); + plot.updatePosition(area, subPlotArea); + Rectangle2D positionArea = plot.getPositionArea(area); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + shrink = plot.getPlotShrink(); + } else { + plot.setOuterPositionArea(area); + Rectangle2D positionArea = plot.getPositionArea(area); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + shrink = plot.getPlotShrink(); + //shrink = tightInset; + } + + return shrink; + } + + private Margin getPlotsShrink(Graphics2D g, Rectangle2D area) { + Margin pshrink = null, shrink; + for (int i = 0; i < this.plots.size(); i++) { + Plot plot = this.plots.get(i); + plot.setOuterPositionArea(plot.getOuterPositionArea(area)); + Rectangle2D positionArea = plot.getPositionArea(area); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + shrink = plot.getPlotShrink(); + if (i == 0) { + pshrink = shrink; + } else if (pshrink != null) { + pshrink = pshrink.extend(shrink); + } + } + + return pshrink; + } + + private Margin getPlotsShrink_bak(Graphics2D g, Rectangle2D area) { + Margin pshrink = null, shrink; + for (int i = 0; i < this.plots.size(); i++) { + Plot plot = this.plots.get(i); + if (plot.isSubPlot) { + double rowHeight = area.getHeight() / this.rowNum; + double colWidth = area.getWidth() / this.columnNum; + double x = area.getX() + plot.columnIndex * colWidth; + double y = area.getY() + plot.rowIndex * rowHeight; + Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); + plot.setOuterPositionArea(subPlotArea); + plot.updatePosition(area, subPlotArea); + Rectangle2D positionArea = plot.getPositionArea(area); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + shrink = plot.getPlotShrink(); + } else { + plot.setOuterPositionArea(area); + Rectangle2D positionArea = plot.getPositionArea(area); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + shrink = plot.getPlotShrink(); + } + if (i == 0) { + pshrink = shrink; + } else if (pshrink != null) { + pshrink = pshrink.extend(shrink); + } + } + + return pshrink; + } + + private Margin getPlotsTightInset(Graphics2D g, Rectangle2D area) { + int i = 0; + Margin pti = null, tightInset; + for (Plot plot : this.plots) { + if (plot.isSubPlot) { + double rowHeight = area.getHeight() / this.rowNum; + double colWidth = area.getWidth() / this.columnNum; + double x = area.getX() + plot.columnIndex * colWidth; + double y = area.getY() + plot.rowIndex * rowHeight; + Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); + plot.setOuterPositionArea(subPlotArea); + plot.updatePosition(area, subPlotArea); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + tightInset = plot.getTightInset(g, positionArea); + } else { + plot.setOuterPositionArea(area); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + tightInset = plot.getTightInset(g, positionArea); + } + if (i == 0) { + pti = tightInset; + } else if (pti != null) { + pti = pti.extend(tightInset); + } + i += 1; + } + + return pti; + } + + private double getPositionAreaZoom(Graphics2D g, Rectangle2D area) { + double zoom = 1.0; + for (Plot plot : this.plots) { + if (plot.isSubPlot) { + double rowHeight = area.getHeight() / this.rowNum; + double colWidth = area.getWidth() / this.columnNum; + double x = area.getX() + plot.columnIndex * colWidth; + double y = area.getY() + plot.rowIndex * rowHeight; + Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); + plot.setOuterPositionArea(subPlotArea); + plot.updatePosition(area, subPlotArea); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + double zoom1 = plot.updatePostionAreaZoom(); + if (zoom1 < zoom) { + zoom = zoom1; + } + } else { + plot.setOuterPositionArea(area); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + double zoom1 = plot.updatePostionAreaZoom(); + if (zoom1 < zoom) { + zoom = zoom1; + } + } + } + + return zoom; + } + + private Rectangle2D getSubPlotArea(Graphics2D g, Plot plot, Rectangle2D area) { + if (plot.isSubPlot) { + double rowHeight = area.getHeight() / this.rowNum; + double colWidth = area.getWidth() / this.columnNum; + double x = area.getX() + plot.columnIndex * colWidth; + double y = area.getY() + plot.rowIndex * rowHeight; + Rectangle2D subPlotArea = new Rectangle2D.Double(x, y, colWidth, rowHeight); + plot.setOuterPositionArea(subPlotArea); + plot.updatePosition(area, subPlotArea); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + double zoom = plot.updatePostionAreaZoom(); + plot.setPositionAreaZoom(zoom); + return subPlotArea; + } else { + plot.setOuterPositionArea(area); + Rectangle2D positionArea = plot.getPositionArea(); + plot.setPositionArea(positionArea); + Margin tightInset = plot.getTightInset(g, positionArea); + plot.setTightInset(tightInset); + double zoom = plot.updatePostionAreaZoom(); + plot.setPositionAreaZoom(zoom); + //return tightInset.getArea(positionArea); + return area; + } + } + + /** + * Get graph area + * + * @return Get graph area + */ + public Rectangle2D getGraphArea() { + Rectangle2D rect = this.plots.get(0).getPositionArea(); + double left = rect.getX() + this.plotArea.getX(); + double top = rect.getY() + this.plotArea.getY(); + return new Rectangle2D.Double(left, top, rect.getWidth(), rect.getHeight()); + } + + /** + * Find a plot by point + * + * @param x X + * @param y Y + * @return Plot + */ + public Plot findPlot(int x, int y) { + for (Plot plot : this.plots) { + Rectangle2D area = plot.getPositionArea(); + if (area.contains(x, y)) { + return plot; + } + } + + return null; + } + + /** + * Clear plots + */ + public void clearPlots() { + this.plots.clear(); + } + + /** + * Clear texts + */ + public void clearTexts() { + this.texts.clear(); + } + + /** + * Remove a plot + * + * @param plot The plot + */ + public void removePlot(Plot plot) { + this.plots.remove(plot); + } + + /** + * Add a plot + * + * @param plot Plot + */ + public void addPlot(Plot plot) { + if (plot instanceof MapPlot) { + ((MapPlot) plot).setParent(parent); + } + this.plots.add(plot); + } + + /** + * Set plot + * + * @param plot Plot + */ + public void setPlot(Plot plot) { + if (plot instanceof MapPlot) { + ((MapPlot) plot).setParent(parent); + } + this.plots.clear(); + this.plots.add(plot); + } + + /** + * Get plot by plot index + * + * @param plotIdx Plot index - begin with 1 + * @return Plot index + */ + public Plot getPlot(int plotIdx) { + for (Plot plot : this.plots) { + int pIdx = plot.rowIndex * this.columnNum + plot.columnIndex + 1; + if (pIdx == plotIdx) { + return plot; + } + } + + if (plotIdx > 0 && plotIdx <= this.plots.size()) + return this.plots.get(plotIdx - 1); + else + return null; + } + + /** + * Get plot index + * @param plot The plot + * @return Plot index + */ + public int getPlotIndex(Plot plot){ + return this.plots.indexOf(plot); + } + + /** + * Check if has web map layer + * + * @return Boolean + */ + public boolean hasWebMap() { + for (Plot plot : this.plots) { + if (plot instanceof MapPlot) { + MapPlot mp = (MapPlot) plot; + if (mp.hasWebMapLayer()) { + return true; + } + } + } + + return false; + } + + /** + * Add text + * + * @param text Text + */ + public void addText(ChartText text) { + this.texts.add(text); + } + // + +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartColorBar.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartColorBar.java index 3453e2a3..306f84ac 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartColorBar.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartColorBar.java @@ -17,10 +17,10 @@ import java.util.ArrayList; import java.util.List; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.drawing.Draw; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.legend.ColorBreak; import org.meteoinfo.legend.LegendScheme; import org.meteoinfo.legend.LegendType; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartElement.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartElement.java index bac04ca9..9c72883e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartElement.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartElement.java @@ -1,335 +1,336 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.chart; - -import org.meteoinfo.global.event.ILocationChangedListener; -import org.meteoinfo.global.event.ISizeChangedListener; -import org.meteoinfo.global.event.LocationChangedEvent; -import org.meteoinfo.global.event.SizeChangedEvent; -import org.meteoinfo.global.PointF; -import java.awt.Color; -import java.awt.Rectangle; -import javax.swing.event.EventListenerList; -import org.meteoinfo.layout.ResizeAbility; - -/** - * - * @author yaqiang - */ -public abstract class ChartElement { - // - - public void addLocationChangedListener(ILocationChangedListener listener) { - this._listeners.add(ILocationChangedListener.class, listener); - } - - public void removeLocationChangedListener(ILocationChangedListener listener) { - this._listeners.remove(ILocationChangedListener.class, listener); - } - - public void fireLocationChangedEvent() { - fireLocationChangedEvent(new LocationChangedEvent(this)); - } - - private void fireLocationChangedEvent(LocationChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ILocationChangedListener.class) { - ((ILocationChangedListener) listeners[i + 1]).locationChangedEvent(event); - } - } - } - - public void addSizeChangedListener(ISizeChangedListener listener) { - this._listeners.add(ISizeChangedListener.class, listener); - } - - public void removeSizeChangedListener(ISizeChangedListener listener) { - this._listeners.remove(ISizeChangedListener.class, listener); - } - - public void fireSizeChangedEvent() { - fireSizeChangedEvent(new SizeChangedEvent(this)); - } - - private void fireSizeChangedEvent(SizeChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ISizeChangedListener.class) { - ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); - } - } - } - // - // - private final EventListenerList _listeners = new EventListenerList(); - protected float x; - protected float y; - protected float width; - protected float height; - protected Color _foreColor; - protected Color _backColor; - private boolean _selected; - private ResizeAbility _resizeAbility; - private boolean _visible = true; - private boolean drawBackColor = false; - // - // - - public ChartElement() { - _foreColor = Color.black; - _backColor = Color.white; - _selected = false; - _resizeAbility = ResizeAbility.None; - } - // - // - - /** - * Get if visible - * - * @return Boolean - */ - public boolean isVisible() { - return _visible; - } - - /** - * Set if visible - * - * @param istrue Boolean - */ - public void setVisible(boolean istrue) { - _visible = istrue; - } - - /** - * Get x - * - * @return x - */ - public float getX() { - return x; - } - - /** - * Set left - * - * @param left - */ - public void setX(float left) { - x = left; - this.fireLocationChangedEvent(); - } - - /** - * Get y - * - * @return Y - */ - public float getY() { - return y; - } - - /** - * Set y - * - * @param top Y - */ - public void setY(float top) { - y = top; - this.fireLocationChangedEvent(); - } - - /** - * Get width - * - * @return Width - */ - public float getWidth() { - return width; - } - - /** - * Set width - * - * @param width Width - */ - public void setWidth(float width) { - this.width = width; - this.fireSizeChangedEvent(); - } - - /** - * Get height - * - * @return Height - */ - public float getHeight() { - return height; - } - - /** - * Set height - * - * @param height Height - */ - public void setHeight(float height) { - this.height = height; - this.fireSizeChangedEvent(); - } - - /** - * Get right - * - * @return Right - */ - public float getRight() { - return x + width; - } - - /** - * Get bottom - * - * @return Bottom - */ - public float getBottom() { - return y + height; - } - - /** - * Get bounds rectangle - * - * @return Bounds rectangle - */ - public Rectangle.Float getBounds() { - return new Rectangle.Float(x, y, width, height); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeground() { - return _foreColor; - } - - /** - * Set foreground color - * - * @param color Foreground color - */ - public void setForeground(Color color) { - _foreColor = color; - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackground() { - return _backColor; - } - - /** - * Set background color - * - * @param color Background color - */ - public void setBackground(Color color) { - _backColor = color; - } - - /** - * Get if is selected - * - * @return Boolean - */ - public boolean isSelected() { - return _selected; - } - - /** - * Set if is selected - * - * @param istrue Boolean - */ - public void setSelected(boolean istrue) { - _selected = istrue; - } - - /** - * Get resize ability - * - * @return Resize ability - */ - public ResizeAbility getResizeAbility() { - return _resizeAbility; - } - - /** - * Set resize ability - * - * @param ra Resize ability - */ - public void setResizeAbility(ResizeAbility ra) { - _resizeAbility = ra; - } - - /** - * Get is draw backcolor - * @return Boolean - */ - public boolean isDrawBackColor(){ - return drawBackColor; - } - - /** - * Set is draw backcolor - * @param value Boolean - */ - public void setDrawBackColor(boolean value){ - drawBackColor = value; - } - // - // - - /** - * Move update method - */ - public abstract void moveUpdate(); - - /** - * Resize update method - */ - public abstract void resizeUpdate(); - - /** - * Page to screen - * - * @param pageX Page X - * @param pageY Page Y - * @param pageLocation Page location - * @param zoom Zoom - * @return Screen point - */ - public PointF pageToScreen(float pageX, float pageY, PointF pageLocation, float zoom) { - float x = pageX * zoom + pageLocation.X; - float y = pageY * zoom + pageLocation.Y; - return (new PointF(x, y)); - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.chart; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.global.event.ILocationChangedListener; +import org.meteoinfo.global.event.ISizeChangedListener; +import org.meteoinfo.global.event.LocationChangedEvent; +import org.meteoinfo.global.event.SizeChangedEvent; + +import java.awt.Color; +import java.awt.Rectangle; +import javax.swing.event.EventListenerList; +import org.meteoinfo.layout.ResizeAbility; + +/** + * + * @author yaqiang + */ +public abstract class ChartElement { + // + + public void addLocationChangedListener(ILocationChangedListener listener) { + this._listeners.add(ILocationChangedListener.class, listener); + } + + public void removeLocationChangedListener(ILocationChangedListener listener) { + this._listeners.remove(ILocationChangedListener.class, listener); + } + + public void fireLocationChangedEvent() { + fireLocationChangedEvent(new LocationChangedEvent(this)); + } + + private void fireLocationChangedEvent(LocationChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ILocationChangedListener.class) { + ((ILocationChangedListener) listeners[i + 1]).locationChangedEvent(event); + } + } + } + + public void addSizeChangedListener(ISizeChangedListener listener) { + this._listeners.add(ISizeChangedListener.class, listener); + } + + public void removeSizeChangedListener(ISizeChangedListener listener) { + this._listeners.remove(ISizeChangedListener.class, listener); + } + + public void fireSizeChangedEvent() { + fireSizeChangedEvent(new SizeChangedEvent(this)); + } + + private void fireSizeChangedEvent(SizeChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ISizeChangedListener.class) { + ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); + } + } + } + // + // + private final EventListenerList _listeners = new EventListenerList(); + protected float x; + protected float y; + protected float width; + protected float height; + protected Color _foreColor; + protected Color _backColor; + private boolean _selected; + private ResizeAbility _resizeAbility; + private boolean _visible = true; + private boolean drawBackColor = false; + // + // + + public ChartElement() { + _foreColor = Color.black; + _backColor = Color.white; + _selected = false; + _resizeAbility = ResizeAbility.None; + } + // + // + + /** + * Get if visible + * + * @return Boolean + */ + public boolean isVisible() { + return _visible; + } + + /** + * Set if visible + * + * @param istrue Boolean + */ + public void setVisible(boolean istrue) { + _visible = istrue; + } + + /** + * Get x + * + * @return x + */ + public float getX() { + return x; + } + + /** + * Set left + * + * @param left + */ + public void setX(float left) { + x = left; + this.fireLocationChangedEvent(); + } + + /** + * Get y + * + * @return Y + */ + public float getY() { + return y; + } + + /** + * Set y + * + * @param top Y + */ + public void setY(float top) { + y = top; + this.fireLocationChangedEvent(); + } + + /** + * Get width + * + * @return Width + */ + public float getWidth() { + return width; + } + + /** + * Set width + * + * @param width Width + */ + public void setWidth(float width) { + this.width = width; + this.fireSizeChangedEvent(); + } + + /** + * Get height + * + * @return Height + */ + public float getHeight() { + return height; + } + + /** + * Set height + * + * @param height Height + */ + public void setHeight(float height) { + this.height = height; + this.fireSizeChangedEvent(); + } + + /** + * Get right + * + * @return Right + */ + public float getRight() { + return x + width; + } + + /** + * Get bottom + * + * @return Bottom + */ + public float getBottom() { + return y + height; + } + + /** + * Get bounds rectangle + * + * @return Bounds rectangle + */ + public Rectangle.Float getBounds() { + return new Rectangle.Float(x, y, width, height); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeground() { + return _foreColor; + } + + /** + * Set foreground color + * + * @param color Foreground color + */ + public void setForeground(Color color) { + _foreColor = color; + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackground() { + return _backColor; + } + + /** + * Set background color + * + * @param color Background color + */ + public void setBackground(Color color) { + _backColor = color; + } + + /** + * Get if is selected + * + * @return Boolean + */ + public boolean isSelected() { + return _selected; + } + + /** + * Set if is selected + * + * @param istrue Boolean + */ + public void setSelected(boolean istrue) { + _selected = istrue; + } + + /** + * Get resize ability + * + * @return Resize ability + */ + public ResizeAbility getResizeAbility() { + return _resizeAbility; + } + + /** + * Set resize ability + * + * @param ra Resize ability + */ + public void setResizeAbility(ResizeAbility ra) { + _resizeAbility = ra; + } + + /** + * Get is draw backcolor + * @return Boolean + */ + public boolean isDrawBackColor(){ + return drawBackColor; + } + + /** + * Set is draw backcolor + * @param value Boolean + */ + public void setDrawBackColor(boolean value){ + drawBackColor = value; + } + // + // + + /** + * Move update method + */ + public abstract void moveUpdate(); + + /** + * Resize update method + */ + public abstract void resizeUpdate(); + + /** + * Page to screen + * + * @param pageX Page X + * @param pageY Page Y + * @param pageLocation Page location + * @param zoom Zoom + * @return Screen point + */ + public PointF pageToScreen(float pageX, float pageY, PointF pageLocation, float zoom) { + float x = pageX * zoom + pageLocation.X; + float y = pageY * zoom + pageLocation.Y; + return (new PointF(x, y)); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartLegend.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartLegend.java index 0053c6bf..0e66c9f5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartLegend.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartLegend.java @@ -1,1441 +1,1441 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.chart; - -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.PointF; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.LegendScheme; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.util.List; -import org.meteoinfo.chart.plot.PlotOrientation; -import org.meteoinfo.chart.plot.XAlign; -import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.legend.LegendType; - -/** - * - * @author Yaqiang Wang - */ -public class ChartLegend { - // - - //private final XY1DPlot plot; - protected LegendScheme legendScheme; - private LegendPosition position; - protected float shrink; - protected int aspect; - private boolean colorBar; - protected float x; - protected float y; - protected PlotOrientation orientation; - protected Color background; - protected boolean drawBackground; - protected int width; - protected int height; - protected int legendWidth; - protected int legendHeight; - protected ChartText label; - protected String labelLocation; - protected Font tickLabelFont; - protected Color tickLabelColor; - protected float tickLabelAngle; - protected boolean drawNeatLine; - protected Color neatLineColor; - protected float neatLineSize; - private float breakSpace; - private float topSpace; - private float leftSpace; - protected double _vBarWidth; - protected double _hBarHeight; - private int rowColNum = 1; - private boolean autoRowColNum = true; - private Dimension symbolDimension; - protected boolean extendRect; - protected boolean autoExtendFrac; - protected float xshift; - protected float yshift; - // - // - - /** - * Constructor - * - * @param ls LegendScheme - */ - public ChartLegend(LegendScheme ls) { - //this.plot = plot; - this.legendScheme = ls; - this.colorBar = false; - this.position = LegendPosition.LOWER_CENTER_OUTSIDE; - this.orientation = PlotOrientation.HORIZONTAL; - this.shrink = 1.0f; - this.aspect = 20; - this.background = Color.white; - this.drawBackground = false; - drawNeatLine = true; - neatLineColor = Color.black; - neatLineSize = 1; - breakSpace = 3; - topSpace = 5; - leftSpace = 5; - _vBarWidth = 10; - _hBarHeight = 10; - this.labelLocation = "out"; - tickLabelFont = new Font("Arial", Font.PLAIN, 14); - this.tickLabelColor = Color.black; - this.tickLabelAngle = 0; - this.symbolDimension = new Dimension(16, 10); - this.extendRect = true; - this.autoExtendFrac = false; - this.xshift = 0; - this.yshift = 0; - } - - // - // - // - // - /** - * Get legend scheme - * - * @return Legend scheme - */ - public LegendScheme getLegendScheme() { - return this.legendScheme; - } - - /** - * Set legend scheme - * - * @param value Legend scheme - */ - public void setLegendScheme(LegendScheme value) { - this.legendScheme = value; - } - - /** - * Get if is color bar - * - * @return Boolean - */ - public boolean isColorbar() { - return this.colorBar; - } - - /** - * Set if is color bar - * - * @param value Boolean - */ - public void setColorbar(boolean value) { - this.colorBar = value; - } - - /** - * Get legend position - * - * @return Legend position - */ - public LegendPosition getPosition() { - return this.position; - } - - /** - * Set legend position - * - * @param value Legend position - */ - public void setPosition(LegendPosition value) { - this.position = value; - } - - /** - * Get shrink - * - * @return Shrink - */ - public float getShrink() { - return this.shrink; - } - - /** - * Set shrink - * - * @param value Shrink - */ - public void setShrink(float value) { - this.shrink = value; - } - - /** - * Get aspect - * - * @return Aspect - */ - public int getAspect() { - return this.aspect; - } - - /** - * Set aspect - * - * @param value Aspect - */ - public void setAspect(int value) { - this.aspect = value; - } - - /** - * Get X - * - * @return X value - */ - public float getX() { - return this.x; - } - - /** - * Set X - * - * @param value X value - */ - public void setX(float value) { - x = value; - } - - /** - * Get Y - * - * @return Y value - */ - public float getY() { - return this.y; - } - - /** - * Set Y - * - * @param value Y value - */ - public void setY(float value) { - y = value; - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return this.width; - } - - /** - * Set width - * - * @param value Width - */ - public void setWidth(int value) { - this.width = value; - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return this.height; - } - - /** - * Set height - * - * @param value Height - */ - public void setHeight(int value) { - this.height = value; - } - - /** - * Get legend width - * - * @return Legend width - */ - public int getLegendWidth() { - return this.legendWidth; - } - - /** - * Set legend width - * - * @param value Legend width - */ - public void setLegendWidth(int value) { - this.legendWidth = value; - } - - /** - * Get legend height - * - * @return Legend height - */ - public int getLegendHeight() { - return this.legendHeight; - } - - /** - * Set legend height - * - * @param value Legend height - */ - public void setLegendHeight(int value) { - this.legendHeight = value; - } - - /** - * Get plot orientation - * - * @return Plot orientation - */ - public PlotOrientation getPlotOrientation() { - return this.orientation; - } - - /** - * Set plot orientation - * - * @param value Plot orientation - */ - public void setPlotOrientation(PlotOrientation value) { - this.orientation = value; - } - - /** - * Get background - * - * @return Background - */ - public Color getBackground() { - return this.background; - } - - /** - * Set background - * - * @param value Background - */ - public void setBackground(Color value) { - this.background = value; - } - - /** - * Get if draw background - * - * @return Boolean - */ - public boolean isDrawBackground() { - return this.drawBackground; - } - - /** - * Set if draw background - * - * @param value Boolean - */ - public void setDrawBackground(boolean value) { - this.drawBackground = value; - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - neatLineSize = size; - } - - /** - * Get break space - * @return Break space - */ - public float getBreakSpace() { - return this.breakSpace; - } - - /** - * Set break space - * @param value Break space - */ - public void setBreakSpace(float value) { - this.breakSpace = value; - } - - /** - * Get label - * - * @return Label - */ - public ChartText getLabel() { - return this.label; - } - - /** - * Set label - * - * @param value Label - */ - public void setLabel(ChartText value) { - this.label = value; - } - - /** - * Get label font - * - * @return Label font - */ - public Font getLabelFont() { - return this.label.getFont(); - } - - /** - * Set label font - * - * @param value Label font - */ - public void setLabelFont(Font value) { - this.label.setFont(value); - } - - /** - * Get label color - * - * @return Label color - */ - public Color getLabelColor() { - return this.label.getColor(); - } - - /** - * Set label color - * - * @param value Label color - */ - public void setLabelColor(Color value) { - this.label.setColor(value); - } - - /** - * Get label location (in, out, top, bottom, left, right) - * - * @return Label location - */ - public String getLabelLocation() { - return this.labelLocation; - } - - /** - * Set label location - * - * @param value Label location - */ - public void setLabelLocation(String value) { - this.labelLocation = value; - } - - /** - * Get Tick label font - * - * @return The Tick label font - */ - public Font getTickLabelFont() { - return tickLabelFont; - } - - /** - * Set Tick label font - * - * @param font The Tick label font - */ - public void setTickLabelFont(Font font) { - tickLabelFont = font; - } - - /** - * Get tick label color - * - * @return Tick label color - */ - public Color getTickLabelColor() { - return this.tickLabelColor; - } - - /** - * Set tick label color - * - * @param value Tick label color - */ - public void setTickLabelColor(Color value) { - this.tickLabelColor = value; - } - - /** - * Get tick lable angle - * - * @return Tick label angle - */ - public float getTickLabelAngle() { - return this.tickLabelAngle; - } - - /** - * Set tick label angle - * - * @param value Tick label angle - */ - public void setTickLabelAngle(float value) { - this.tickLabelAngle = value; - } - - /** - * Get column number - * - * @return Column number - */ - public int getColumnNumber() { - return rowColNum; - } - - /** - * Set column number - * - * @param value Column number - */ - public void setColumnNumber(int value) { - rowColNum = value; - } - - /** - * Get if automatic set row/col number - * - * @return Boolean - */ - public boolean isAutoRowColNum() { - return this.autoRowColNum; - } - - /** - * Set if automatic set row/col number - * - * @param value Boolean - */ - public void setAutoRowColNum(boolean value) { - this.autoRowColNum = value; - } - - /** - * Get symbol dimension - * - * @return Symbol dimension - */ - public Dimension getSymbolDimension() { - return this.symbolDimension; - } - - /** - * Set symbol dimension - * - * @param value Symbol dimension - */ - public void setSymbolDimension(Dimension value) { - this.symbolDimension = value; - } - - /** - * Set symbol width - * - * @param value Width - */ - public void setSymbolWidth(int value) { - this.symbolDimension.width = value; - } - - /** - * Set symbol height - * - * @param value height - */ - public void setSymbolHeight(int value) { - this.symbolDimension.height = value; - } - - /** - * Set symbol scale - * - * @param value Symble scale - */ - public void setSymbolScale(float value) { - double w = this.symbolDimension.getWidth() * value; - double h = this.symbolDimension.getHeight() * value; - this.symbolDimension.setSize(w, h); - } - - /** - * Get if extend rectangle - or triangle - * - * @return Boolean - */ - public boolean isExtendRect() { - return this.extendRect; - } - - /** - * Set if extend rectangle - or triangle - * - * @param value Boolean - */ - public void setExtendRect(boolean value) { - this.extendRect = value; - } - - /** - * Get if auto set extend fraction - extend has save width and height Only - * valid for colorbar - * - * @return Boolean - */ - public boolean isAutoExtendFrac() { - return this.autoExtendFrac; - } - - /** - * Set if auto set extend fraction - extend has save width and height Only - * valid for colorbar - * - * @param value - */ - public void setAutoExtendFrac(boolean value) { - this.autoExtendFrac = value; - } - - /** - * Set tick labels - * - * @param value Tick labels - */ - public void setTickCaptions(List value) { - for (int i = 0; i < this.legendScheme.getBreakNum(); i++) { - if (i < value.size()) { - this.legendScheme.getLegendBreaks().get(i).setCaption(value.get(i)); - } else { - break; - } - } - } - - /** - * Get x shift - pixel unit - * - * @return X shift - */ - public float getXShift() { - return this.xshift; - } - - /** - * Set x shift - * - * @param value X shift - */ - public void setXShift(float value) { - this.xshift = value; - } - - /** - * Get y shift - pixel unit - * - * @return Y shift - */ - public float getYShift() { - return this.yshift; - } - - /** - * Set y shift - * - * @param value Y shift - */ - public void setYShift(float value) { - this.yshift = value; - } - - // - // - /** - * Draw legend - * - * @param g Graphics2D - * @param point Start point - */ - public void draw(Graphics2D g, PointF point) { - - AffineTransform oldMatrix = g.getTransform(); - g.translate(point.X + this.xshift, point.Y + this.yshift); - - //Draw background color - if (this.drawBackground) { - g.setColor(this.background); - g.fill(new Rectangle.Float(0, 0, this.width, this.height)); - } - - //Draw legend - g.setStroke(new BasicStroke(1)); - switch (this.orientation) { - case HORIZONTAL: - drawHorizontalLegend(g, legendScheme); - break; - case VERTICAL: - this.drawVerticalLegend(g, legendScheme); - break; - } - - //Draw neatline - if (drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(0, 0, this.width, this.height); - g.setColor(neatLineColor); - g.setStroke(new BasicStroke(neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawVerticalLegend(Graphics2D g, LegendScheme aLS) { - String caption; - float breakHeight = this.getBreakHeight(g); - float symbolHeight = this.symbolDimension.height; - float symbolWidth = this.symbolDimension.width; - float colWidth = symbolWidth + getMaxLabelWidth(g) + 10; - - //Set columns - int[] rowNums = new int[rowColNum]; - int ave = aLS.getVisibleBreakNum() / rowColNum; - if (ave * rowColNum < aLS.getBreakNum()) { - ave += 1; - } - int num = 0; - int i; - for (i = 1; i < rowColNum; i++) { - rowNums[i] = ave; - num += ave; - } - rowNums[0] = aLS.getVisibleBreakNum() - num; - - //Draw title - float y0 = 0; - if (this.label != null) { - float x0 = (float) (this.width / 2.); - y0 += this.breakSpace * 2; - this.label.draw(g, x0, y0); - y0 += this.label.getDimension(g).height + this.breakSpace * 2; - } - - //Draw legend - float x, y; - i = 0; - for (int col = 0; col < rowColNum; col++) { - x = symbolWidth / 2 + leftSpace + col * colWidth; - y = y0 + breakHeight / 2 + breakSpace * 2; - for (int row = 0; row < rowNums[col]; row++) { - if (!aLS.getLegendBreaks().get(i).isDrawShape()) { - continue; - } - - //y += breakHeight + breakSpace; - ColorBreak cb = aLS.getLegendBreaks().get(i); - if (!cb.isDrawShape()) { - continue; - } - caption = aLS.getLegendBreaks().get(i).getCaption(); - if (cb instanceof PointBreak) { - PointBreak aPB = (PointBreak) cb.clone(); - ((PointBreak) aPB).setSize(((PointBreak) cb).getSize() * (symbolHeight / 10.f)); - Draw.drawPoint(new PointF(x, y), aPB, g); - } else if (cb instanceof PolylineBreak) { - PolylineBreak aPLB = (PolylineBreak) cb; - Draw.drawPolylineSymbol_S(new PointF(x, y), symbolWidth, symbolHeight, aPLB, g); - } else if (cb instanceof PolygonBreak) { - Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, (PolygonBreak) cb, g); - } else { - PolygonBreak pgb = new PolygonBreak(); - pgb.setColor(cb.getColor()); - pgb.setOutlineColor(Color.black); - Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, pgb, g); - } - - PointF sP = new PointF(0, 0); - sP.X = x + symbolWidth / 2; - sP.Y = y; - g.setColor(this.tickLabelColor); - g.setFont(this.tickLabelFont); - Draw.drawString(g, sP.X + 5, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, true); - y += breakHeight + breakSpace; - - i += 1; - } - } - } - - private void drawHorizontalLegend(Graphics2D g, LegendScheme aLS) { - String caption; - float breakHeight = this.getBreakHeight(g); - float symbolHeight = this.symbolDimension.height; - float symbolWidth = this.symbolDimension.width; - - //Set columns - int[] colNums = new int[rowColNum]; - int ave = aLS.getVisibleBreakNum() / rowColNum; - if (ave * rowColNum < aLS.getBreakNum()) { - ave += 1; - } - int num = 0; - int i; - for (i = 0; i < rowColNum - 1; i++) { - colNums[i] = ave; - num += ave; - } - colNums[rowColNum - 1] = aLS.getVisibleBreakNum() - num; - - //Draw legend - float x, y; - y = this.breakSpace + breakHeight / 2; - i = 0; - for (int row = 0; row < rowColNum; row++) { - x = this.symbolDimension.width / 2 + 5; - for (int col = 0; col < colNums[row]; col++) { - if (i >= aLS.getBreakNum()) { - break; - } - - ColorBreak cb = aLS.getLegendBreaks().get(i); - if (!cb.isDrawShape()) { - continue; - } - caption = aLS.getLegendBreaks().get(i).getCaption(); - if (cb instanceof PointBreak) { - PointBreak aPB = (PointBreak) cb; - Draw.drawPoint(new PointF(x, y), aPB, g); - } else if (cb instanceof PolylineBreak) { - PolylineBreak aPLB = (PolylineBreak) cb; - Draw.drawPolylineSymbol_S(new PointF(x, y), symbolWidth, symbolHeight, aPLB, g); - } else if (cb instanceof PolygonBreak) { - Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, (PolygonBreak) cb, g); - } - - PointF sP = new PointF(0, 0); - sP.X = x + symbolWidth / 2; - sP.Y = y; - g.setColor(this.tickLabelColor); - g.setFont(this.tickLabelFont); - Draw.drawString(g, sP.X + 5, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, true); - Dimension dim = Draw.getStringDimension(caption, g); - x += this.symbolDimension.width + dim.width + 15; - i += 1; - } - y += breakHeight + this.breakSpace * 2; - } - } - - private int getMaxLabelWidth(Graphics2D g) { - String caption; - Dimension aSF; - int bNum = legendScheme.getBreakNum(); - int labWidth = 0; - g.setFont(this.tickLabelFont); - for (int i = 0; i < bNum; i++) { - caption = legendScheme.getLegendBreaks().get(i).getCaption(); - boolean isValid = true; - if (isValid) { - aSF = Draw.getStringDimension(caption, this.tickLabelAngle, g); - int labwidth = aSF.width; - if (labWidth < labwidth) { - labWidth = labwidth; - } - } - } - - return labWidth; - } - - private int getBreakHeight(Graphics2D g) { - g.setFont(tickLabelFont); - Dimension dim = Draw.getStringDimension(this.legendScheme.getLegendBreak(0).getCaption(), g); - return Math.max(dim.height, this.symbolDimension.height); - } - - /** - * Get legend dimension - * - * @param g Graphics2D - * @param limitDim Limit dimension - * @return Legend dimension - */ - public Dimension getLegendDimension(Graphics2D g, Dimension limitDim) { - if (legendScheme != null) { - if (this.colorBar) { - switch (this.orientation) { - case VERTICAL: - this.width = (int) (this.getTickWidth(g) + limitDim.height * this.shrink / this.aspect + 5); - if (this.label != null) { - g.setFont(this.label.getFont()); - this.width += (int) Draw.getStringDimension(label.getText(), g).height + 5; - } - break; - default: - g.setFont(this.tickLabelFont); - this.height = (int) (Draw.getStringDimension("test", g).height + limitDim.width * this.shrink / this.aspect + 5); - if (this.label != null) { - g.setFont(this.label.getFont()); - Dimension dim = Draw.getStringDimension(label.getText(), g); - switch (this.labelLocation) { - case "top": - case "right": - this.width += dim.width + 10; - break; - default: - this.height += (int) Draw.getStringDimension(label.getText(), g).height + 5; - break; - } - } - } - } else { - int breakHeight = getBreakHeight(g); - int titleHeight = 0; - int titleWidth = 0; - if (this.label != null) { - Dimension dim = this.label.getDimension(g); - titleHeight = dim.height + (int) (this.breakSpace * 4); - titleWidth = dim.width; - } - switch (this.orientation) { - case VERTICAL: - //Get column number - if (this.autoRowColNum) { - int tHeight = (int) (legendScheme.getBreakNum() * (breakHeight + breakSpace) - + breakSpace * 2 + breakHeight / 2 + 5); - rowColNum = 1; - if (tHeight > limitDim.height * 10 / 8) { - rowColNum = tHeight / (limitDim.height * 10 / 8) + 1; - if (rowColNum == 1) { - rowColNum = 2; - } else { - int n = legendScheme.getBreakNum() / rowColNum; - int m = legendScheme.getBreakNum() % rowColNum; - if (m != 0) { - if (m <= n) { - rowColNum += 1; - } else { - rowColNum += 2; - } - } else if (rowColNum * (limitDim.width * 8 / 10) < tHeight) { - rowColNum += 1; - } - } - } - } - - //Get width - int colWidth = this.symbolDimension.width + getMaxLabelWidth(g) + 15; - this.width = colWidth * rowColNum; - - //Get height - int[] rowNums = new int[rowColNum]; - int ave = legendScheme.getBreakNum() / rowColNum; - if (ave * rowColNum < legendScheme.getBreakNum()) { - ave += 1; - } - int num = 0; - int i; - for (i = 0; i < rowColNum - 1; i++) { - rowNums[i] = ave; - num += ave; - } - rowNums[rowColNum - 1] = legendScheme.getBreakNum() - num; - -// this.height = (int) (rowNums[0] * (breakHeight + _breakSpace) -// + _breakSpace * 2 + breakHeight / 2 + 5); - this.height = (int) (rowNums[0] * (breakHeight + breakSpace) - + breakSpace * 3); - break; - case HORIZONTAL: - //Get row number - if (this.autoRowColNum) { - int breakWidth = this.symbolDimension.width + this.getMaxLabelWidth(g) + 15; - int tWidth = breakWidth * legendScheme.getBreakNum(); - rowColNum = 1; - if (tWidth > limitDim.width * 8 / 10) { - rowColNum = tWidth / (limitDim.width * 8 / 10); - if (rowColNum == 1) { - rowColNum = 2; - } else { - int n = legendScheme.getBreakNum() / rowColNum; - int m = legendScheme.getBreakNum() % rowColNum; - if (m != 0) { - if (m <= n) { - rowColNum += 1; - } else { - rowColNum += 2; - } - } else if (rowColNum * (limitDim.width * 8 / 10) < tWidth) { - rowColNum += 1; - } - } - } - } - - //Get height - this.height = (int) (breakHeight + this.breakSpace * 2) * this.rowColNum; - - //Get width - //FontMetrics metrics = g.getFontMetrics(tickFont); - ave = legendScheme.getBreakNum() / rowColNum; - if (ave * rowColNum < legendScheme.getBreakNum()) { - ave += 1; - } - num = 0; - int maxWidth = 0; - int tempWidth = 0; - for (i = 0; i < legendScheme.getBreakNum(); i++) { - if (num < ave) { - //tempWidth += this.symbolDimension.width + 15 - // + metrics.stringWidth(legendScheme.getLegendBreaks().get(i).getCaption()); - tempWidth += this.symbolDimension.width + 15 - + Draw.getStringDimension(legendScheme.getLegendBreaks().get(i).getCaption(), g).width; - num += 1; - } else { - if (maxWidth < tempWidth) { - maxWidth = tempWidth; - } - //tempWidth = metrics.stringWidth(legendScheme.getLegendBreaks().get(i).getCaption()) + 15; - tempWidth = Draw.getStringDimension(legendScheme.getLegendBreaks().get(i).getCaption(), g).width; - num = 1; - } - } - if (maxWidth < tempWidth) { - maxWidth = tempWidth; - } - if (maxWidth > limitDim.width) { - maxWidth = limitDim.width * 8 / 10; - } - this.width = maxWidth; - break; - } - this.height += titleHeight; - this.width = Math.max(this.width, titleWidth); - } - } - - return new Dimension(this.width, this.height); - } - - protected int getTickWidth(Graphics2D g) { - float rwidth = 0; - String caption = ""; - int bNum = this.legendScheme.getBreakNum(); - //FontMetrics metrics = g.getFontMetrics(this.tickFont); - g.setFont(this.tickLabelFont); - if (this.legendScheme.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - for (int i = 0; i < bNum; i++) { - switch (this.legendScheme.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); - } else { - caption = aPB.getCaption(); - } - break; - case Polyline: - PolylineBreak aPLB = (PolylineBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); - } else { - caption = aPLB.getCaption(); - } - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); - } else { - caption = aPGB.getCaption(); - } - break; - case Image: - ColorBreak aCB = legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); - } else { - caption = aCB.getCaption(); - } - break; - } - - boolean isValid = true; - switch (legendScheme.getLegendType()) { - case GraduatedColor: - if (i == bNum - 1) { - isValid = false; - } - break; - } - if (isValid) { - //float labwidth = metrics.stringWidth(caption); - float labwidth = (float) Draw.getStringDimension(caption, this.tickLabelAngle, g).getWidth(); - if (rwidth < labwidth) { - rwidth = labwidth; - } - } - } - - return (int) rwidth; - } - - protected int getTickHeight(Graphics2D g) { - float rheight = 0; - String caption = ""; - int bNum = this.legendScheme.getBreakNum(); - //FontMetrics metrics = g.getFontMetrics(this.tickFont); - g.setFont(this.tickLabelFont); - if (this.legendScheme.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - for (int i = 0; i < bNum; i++) { - switch (this.legendScheme.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); - } else { - caption = aPB.getCaption(); - } - break; - case Polyline: - PolylineBreak aPLB = (PolylineBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); - } else { - caption = aPLB.getCaption(); - } - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); - } else { - caption = aPGB.getCaption(); - } - break; - case Image: - ColorBreak aCB = legendScheme.getLegendBreaks().get(i); - if (legendScheme.getLegendType() == LegendType.GraduatedColor) { - caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); - } else { - caption = aCB.getCaption(); - } - break; - } - - boolean isValid = true; - switch (legendScheme.getLegendType()) { - case GraduatedColor: - if (i == bNum - 1) { - isValid = false; - } - break; - } - if (isValid) { - float labheight = (float) Draw.getStringDimension(caption, 90 - Math.abs(this.tickLabelAngle), g).getWidth(); - if (rheight < labheight) { - rheight = labheight; - } - } - } - - return (int) rheight; - } - - /** - * Update tick gap - * - * @param g Graphics2D - * @return Ticks gap - */ - protected int getTickGap(Graphics2D g) { - if (this.tickLabelAngle != 0) { - return 1; - } - - double len; - int n = this.legendScheme.getBreakNum(); - int nn; - if (this.orientation == PlotOrientation.HORIZONTAL) { - len = this.width; - int labLen = this.getTickWidth(g); - nn = (int) ((len * 0.8) / labLen); - } else { - len = this.height; - FontMetrics metrics = g.getFontMetrics(tickLabelFont); - nn = (int) (len / metrics.getHeight()); - } - if (nn == 0) { - nn = 1; - } - return n / nn + 1; - } - - // - // - public class LayoutLegendBean { - - LayoutLegendBean() { - } - - // - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - neatLineSize = size; - } - - /** - * Get tick label font - * - * @return The tick label font - */ - public Font getTickLabelFont() { - return tickLabelFont; - } - - /** - * Set tick label font - * - * @param font The tick label font - */ - public void setTickLabelFont(Font font) { - tickLabelFont = font; - } - - /** - * Get column number - * - * @return Column number - */ - public int getColumnNumber() { - return rowColNum; - } - - /** - * Set column number - * - * @param value Column number - */ - public void setColumnNumber(int value) { - rowColNum = value; - } - - /** - * Get is draw background - * - * @return Boolean - */ - public boolean isDrawBackground() { - return drawBackground; - } - - /** - * Set is draw background - * - * @param value Boolean - */ - public void setDrawBackground(boolean value) { - drawBackground = value; - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackground() { - return background; - } - - /** - * Set background color - * - * @param c Background color - */ - public void setBackground(Color c) { - background = c; - } - - // - } - - public static class LayoutLegendBeanBeanInfo extends BaseBeanInfo { - - public LayoutLegendBeanBeanInfo() { - super(LayoutLegendBean.class); - ExtendedPropertyDescriptor e = addProperty("plotOrientation"); - e.setCategory("General").setDisplayName("Plot orientation"); - e.setPropertyEditorClass(PlotOrientationEditor.class); - addProperty("tickFont").setCategory("General").setDisplayName("Tick Font"); - addProperty("drawBackground").setCategory("General").setDisplayName("Draw Background"); - addProperty("background").setCategory("General").setDisplayName("Background"); - addProperty("columnNumber").setCategory("General").setDisplayName("Column Number"); - addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); - addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); - addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); - } - } - - public static class PlotOrientationEditor extends ComboBoxPropertyEditor { - - public PlotOrientationEditor() { - super(); - PlotOrientation[] orientations = PlotOrientation.values(); - String[] types = new String[orientations.length]; - int i = 0; - for (PlotOrientation type : orientations) { - types[i] = type.toString(); - i += 1; - } - setAvailableValues(types); - } - } - - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.chart; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.LegendScheme; +import org.meteoinfo.legend.PointBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.legend.PolylineBreak; +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.util.List; +import org.meteoinfo.chart.plot.PlotOrientation; +import org.meteoinfo.chart.plot.XAlign; +import org.meteoinfo.chart.plot.YAlign; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.legend.LegendType; + +/** + * + * @author Yaqiang Wang + */ +public class ChartLegend { + // + + //private final XY1DPlot plot; + protected LegendScheme legendScheme; + private LegendPosition position; + protected float shrink; + protected int aspect; + private boolean colorBar; + protected float x; + protected float y; + protected PlotOrientation orientation; + protected Color background; + protected boolean drawBackground; + protected int width; + protected int height; + protected int legendWidth; + protected int legendHeight; + protected ChartText label; + protected String labelLocation; + protected Font tickLabelFont; + protected Color tickLabelColor; + protected float tickLabelAngle; + protected boolean drawNeatLine; + protected Color neatLineColor; + protected float neatLineSize; + private float breakSpace; + private float topSpace; + private float leftSpace; + protected double _vBarWidth; + protected double _hBarHeight; + private int rowColNum = 1; + private boolean autoRowColNum = true; + private Dimension symbolDimension; + protected boolean extendRect; + protected boolean autoExtendFrac; + protected float xshift; + protected float yshift; + // + // + + /** + * Constructor + * + * @param ls LegendScheme + */ + public ChartLegend(LegendScheme ls) { + //this.plot = plot; + this.legendScheme = ls; + this.colorBar = false; + this.position = LegendPosition.LOWER_CENTER_OUTSIDE; + this.orientation = PlotOrientation.HORIZONTAL; + this.shrink = 1.0f; + this.aspect = 20; + this.background = Color.white; + this.drawBackground = false; + drawNeatLine = true; + neatLineColor = Color.black; + neatLineSize = 1; + breakSpace = 3; + topSpace = 5; + leftSpace = 5; + _vBarWidth = 10; + _hBarHeight = 10; + this.labelLocation = "out"; + tickLabelFont = new Font("Arial", Font.PLAIN, 14); + this.tickLabelColor = Color.black; + this.tickLabelAngle = 0; + this.symbolDimension = new Dimension(16, 10); + this.extendRect = true; + this.autoExtendFrac = false; + this.xshift = 0; + this.yshift = 0; + } + + // + // + // + // + /** + * Get legend scheme + * + * @return Legend scheme + */ + public LegendScheme getLegendScheme() { + return this.legendScheme; + } + + /** + * Set legend scheme + * + * @param value Legend scheme + */ + public void setLegendScheme(LegendScheme value) { + this.legendScheme = value; + } + + /** + * Get if is color bar + * + * @return Boolean + */ + public boolean isColorbar() { + return this.colorBar; + } + + /** + * Set if is color bar + * + * @param value Boolean + */ + public void setColorbar(boolean value) { + this.colorBar = value; + } + + /** + * Get legend position + * + * @return Legend position + */ + public LegendPosition getPosition() { + return this.position; + } + + /** + * Set legend position + * + * @param value Legend position + */ + public void setPosition(LegendPosition value) { + this.position = value; + } + + /** + * Get shrink + * + * @return Shrink + */ + public float getShrink() { + return this.shrink; + } + + /** + * Set shrink + * + * @param value Shrink + */ + public void setShrink(float value) { + this.shrink = value; + } + + /** + * Get aspect + * + * @return Aspect + */ + public int getAspect() { + return this.aspect; + } + + /** + * Set aspect + * + * @param value Aspect + */ + public void setAspect(int value) { + this.aspect = value; + } + + /** + * Get X + * + * @return X value + */ + public float getX() { + return this.x; + } + + /** + * Set X + * + * @param value X value + */ + public void setX(float value) { + x = value; + } + + /** + * Get Y + * + * @return Y value + */ + public float getY() { + return this.y; + } + + /** + * Set Y + * + * @param value Y value + */ + public void setY(float value) { + y = value; + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return this.width; + } + + /** + * Set width + * + * @param value Width + */ + public void setWidth(int value) { + this.width = value; + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return this.height; + } + + /** + * Set height + * + * @param value Height + */ + public void setHeight(int value) { + this.height = value; + } + + /** + * Get legend width + * + * @return Legend width + */ + public int getLegendWidth() { + return this.legendWidth; + } + + /** + * Set legend width + * + * @param value Legend width + */ + public void setLegendWidth(int value) { + this.legendWidth = value; + } + + /** + * Get legend height + * + * @return Legend height + */ + public int getLegendHeight() { + return this.legendHeight; + } + + /** + * Set legend height + * + * @param value Legend height + */ + public void setLegendHeight(int value) { + this.legendHeight = value; + } + + /** + * Get plot orientation + * + * @return Plot orientation + */ + public PlotOrientation getPlotOrientation() { + return this.orientation; + } + + /** + * Set plot orientation + * + * @param value Plot orientation + */ + public void setPlotOrientation(PlotOrientation value) { + this.orientation = value; + } + + /** + * Get background + * + * @return Background + */ + public Color getBackground() { + return this.background; + } + + /** + * Set background + * + * @param value Background + */ + public void setBackground(Color value) { + this.background = value; + } + + /** + * Get if draw background + * + * @return Boolean + */ + public boolean isDrawBackground() { + return this.drawBackground; + } + + /** + * Set if draw background + * + * @param value Boolean + */ + public void setDrawBackground(boolean value) { + this.drawBackground = value; + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + neatLineSize = size; + } + + /** + * Get break space + * @return Break space + */ + public float getBreakSpace() { + return this.breakSpace; + } + + /** + * Set break space + * @param value Break space + */ + public void setBreakSpace(float value) { + this.breakSpace = value; + } + + /** + * Get label + * + * @return Label + */ + public ChartText getLabel() { + return this.label; + } + + /** + * Set label + * + * @param value Label + */ + public void setLabel(ChartText value) { + this.label = value; + } + + /** + * Get label font + * + * @return Label font + */ + public Font getLabelFont() { + return this.label.getFont(); + } + + /** + * Set label font + * + * @param value Label font + */ + public void setLabelFont(Font value) { + this.label.setFont(value); + } + + /** + * Get label color + * + * @return Label color + */ + public Color getLabelColor() { + return this.label.getColor(); + } + + /** + * Set label color + * + * @param value Label color + */ + public void setLabelColor(Color value) { + this.label.setColor(value); + } + + /** + * Get label location (in, out, top, bottom, left, right) + * + * @return Label location + */ + public String getLabelLocation() { + return this.labelLocation; + } + + /** + * Set label location + * + * @param value Label location + */ + public void setLabelLocation(String value) { + this.labelLocation = value; + } + + /** + * Get Tick label font + * + * @return The Tick label font + */ + public Font getTickLabelFont() { + return tickLabelFont; + } + + /** + * Set Tick label font + * + * @param font The Tick label font + */ + public void setTickLabelFont(Font font) { + tickLabelFont = font; + } + + /** + * Get tick label color + * + * @return Tick label color + */ + public Color getTickLabelColor() { + return this.tickLabelColor; + } + + /** + * Set tick label color + * + * @param value Tick label color + */ + public void setTickLabelColor(Color value) { + this.tickLabelColor = value; + } + + /** + * Get tick lable angle + * + * @return Tick label angle + */ + public float getTickLabelAngle() { + return this.tickLabelAngle; + } + + /** + * Set tick label angle + * + * @param value Tick label angle + */ + public void setTickLabelAngle(float value) { + this.tickLabelAngle = value; + } + + /** + * Get column number + * + * @return Column number + */ + public int getColumnNumber() { + return rowColNum; + } + + /** + * Set column number + * + * @param value Column number + */ + public void setColumnNumber(int value) { + rowColNum = value; + } + + /** + * Get if automatic set row/col number + * + * @return Boolean + */ + public boolean isAutoRowColNum() { + return this.autoRowColNum; + } + + /** + * Set if automatic set row/col number + * + * @param value Boolean + */ + public void setAutoRowColNum(boolean value) { + this.autoRowColNum = value; + } + + /** + * Get symbol dimension + * + * @return Symbol dimension + */ + public Dimension getSymbolDimension() { + return this.symbolDimension; + } + + /** + * Set symbol dimension + * + * @param value Symbol dimension + */ + public void setSymbolDimension(Dimension value) { + this.symbolDimension = value; + } + + /** + * Set symbol width + * + * @param value Width + */ + public void setSymbolWidth(int value) { + this.symbolDimension.width = value; + } + + /** + * Set symbol height + * + * @param value height + */ + public void setSymbolHeight(int value) { + this.symbolDimension.height = value; + } + + /** + * Set symbol scale + * + * @param value Symble scale + */ + public void setSymbolScale(float value) { + double w = this.symbolDimension.getWidth() * value; + double h = this.symbolDimension.getHeight() * value; + this.symbolDimension.setSize(w, h); + } + + /** + * Get if extend rectangle - or triangle + * + * @return Boolean + */ + public boolean isExtendRect() { + return this.extendRect; + } + + /** + * Set if extend rectangle - or triangle + * + * @param value Boolean + */ + public void setExtendRect(boolean value) { + this.extendRect = value; + } + + /** + * Get if auto set extend fraction - extend has save width and height Only + * valid for colorbar + * + * @return Boolean + */ + public boolean isAutoExtendFrac() { + return this.autoExtendFrac; + } + + /** + * Set if auto set extend fraction - extend has save width and height Only + * valid for colorbar + * + * @param value + */ + public void setAutoExtendFrac(boolean value) { + this.autoExtendFrac = value; + } + + /** + * Set tick labels + * + * @param value Tick labels + */ + public void setTickCaptions(List value) { + for (int i = 0; i < this.legendScheme.getBreakNum(); i++) { + if (i < value.size()) { + this.legendScheme.getLegendBreaks().get(i).setCaption(value.get(i)); + } else { + break; + } + } + } + + /** + * Get x shift - pixel unit + * + * @return X shift + */ + public float getXShift() { + return this.xshift; + } + + /** + * Set x shift + * + * @param value X shift + */ + public void setXShift(float value) { + this.xshift = value; + } + + /** + * Get y shift - pixel unit + * + * @return Y shift + */ + public float getYShift() { + return this.yshift; + } + + /** + * Set y shift + * + * @param value Y shift + */ + public void setYShift(float value) { + this.yshift = value; + } + + // + // + /** + * Draw legend + * + * @param g Graphics2D + * @param point Start point + */ + public void draw(Graphics2D g, PointF point) { + + AffineTransform oldMatrix = g.getTransform(); + g.translate(point.X + this.xshift, point.Y + this.yshift); + + //Draw background color + if (this.drawBackground) { + g.setColor(this.background); + g.fill(new Rectangle.Float(0, 0, this.width, this.height)); + } + + //Draw legend + g.setStroke(new BasicStroke(1)); + switch (this.orientation) { + case HORIZONTAL: + drawHorizontalLegend(g, legendScheme); + break; + case VERTICAL: + this.drawVerticalLegend(g, legendScheme); + break; + } + + //Draw neatline + if (drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(0, 0, this.width, this.height); + g.setColor(neatLineColor); + g.setStroke(new BasicStroke(neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawVerticalLegend(Graphics2D g, LegendScheme aLS) { + String caption; + float breakHeight = this.getBreakHeight(g); + float symbolHeight = this.symbolDimension.height; + float symbolWidth = this.symbolDimension.width; + float colWidth = symbolWidth + getMaxLabelWidth(g) + 10; + + //Set columns + int[] rowNums = new int[rowColNum]; + int ave = aLS.getVisibleBreakNum() / rowColNum; + if (ave * rowColNum < aLS.getBreakNum()) { + ave += 1; + } + int num = 0; + int i; + for (i = 1; i < rowColNum; i++) { + rowNums[i] = ave; + num += ave; + } + rowNums[0] = aLS.getVisibleBreakNum() - num; + + //Draw title + float y0 = 0; + if (this.label != null) { + float x0 = (float) (this.width / 2.); + y0 += this.breakSpace * 2; + this.label.draw(g, x0, y0); + y0 += this.label.getDimension(g).height + this.breakSpace * 2; + } + + //Draw legend + float x, y; + i = 0; + for (int col = 0; col < rowColNum; col++) { + x = symbolWidth / 2 + leftSpace + col * colWidth; + y = y0 + breakHeight / 2 + breakSpace * 2; + for (int row = 0; row < rowNums[col]; row++) { + if (!aLS.getLegendBreaks().get(i).isDrawShape()) { + continue; + } + + //y += breakHeight + breakSpace; + ColorBreak cb = aLS.getLegendBreaks().get(i); + if (!cb.isDrawShape()) { + continue; + } + caption = aLS.getLegendBreaks().get(i).getCaption(); + if (cb instanceof PointBreak) { + PointBreak aPB = (PointBreak) cb.clone(); + ((PointBreak) aPB).setSize(((PointBreak) cb).getSize() * (symbolHeight / 10.f)); + Draw.drawPoint(new PointF(x, y), aPB, g); + } else if (cb instanceof PolylineBreak) { + PolylineBreak aPLB = (PolylineBreak) cb; + Draw.drawPolylineSymbol_S(new PointF(x, y), symbolWidth, symbolHeight, aPLB, g); + } else if (cb instanceof PolygonBreak) { + Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, (PolygonBreak) cb, g); + } else { + PolygonBreak pgb = new PolygonBreak(); + pgb.setColor(cb.getColor()); + pgb.setOutlineColor(Color.black); + Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, pgb, g); + } + + PointF sP = new PointF(0, 0); + sP.X = x + symbolWidth / 2; + sP.Y = y; + g.setColor(this.tickLabelColor); + g.setFont(this.tickLabelFont); + Draw.drawString(g, sP.X + 5, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, true); + y += breakHeight + breakSpace; + + i += 1; + } + } + } + + private void drawHorizontalLegend(Graphics2D g, LegendScheme aLS) { + String caption; + float breakHeight = this.getBreakHeight(g); + float symbolHeight = this.symbolDimension.height; + float symbolWidth = this.symbolDimension.width; + + //Set columns + int[] colNums = new int[rowColNum]; + int ave = aLS.getVisibleBreakNum() / rowColNum; + if (ave * rowColNum < aLS.getBreakNum()) { + ave += 1; + } + int num = 0; + int i; + for (i = 0; i < rowColNum - 1; i++) { + colNums[i] = ave; + num += ave; + } + colNums[rowColNum - 1] = aLS.getVisibleBreakNum() - num; + + //Draw legend + float x, y; + y = this.breakSpace + breakHeight / 2; + i = 0; + for (int row = 0; row < rowColNum; row++) { + x = this.symbolDimension.width / 2 + 5; + for (int col = 0; col < colNums[row]; col++) { + if (i >= aLS.getBreakNum()) { + break; + } + + ColorBreak cb = aLS.getLegendBreaks().get(i); + if (!cb.isDrawShape()) { + continue; + } + caption = aLS.getLegendBreaks().get(i).getCaption(); + if (cb instanceof PointBreak) { + PointBreak aPB = (PointBreak) cb; + Draw.drawPoint(new PointF(x, y), aPB, g); + } else if (cb instanceof PolylineBreak) { + PolylineBreak aPLB = (PolylineBreak) cb; + Draw.drawPolylineSymbol_S(new PointF(x, y), symbolWidth, symbolHeight, aPLB, g); + } else if (cb instanceof PolygonBreak) { + Draw.drawPolygonSymbol(new PointF(x, y), symbolWidth, symbolHeight, (PolygonBreak) cb, g); + } + + PointF sP = new PointF(0, 0); + sP.X = x + symbolWidth / 2; + sP.Y = y; + g.setColor(this.tickLabelColor); + g.setFont(this.tickLabelFont); + Draw.drawString(g, sP.X + 5, sP.Y, caption, XAlign.LEFT, YAlign.CENTER, true); + Dimension dim = Draw.getStringDimension(caption, g); + x += this.symbolDimension.width + dim.width + 15; + i += 1; + } + y += breakHeight + this.breakSpace * 2; + } + } + + private int getMaxLabelWidth(Graphics2D g) { + String caption; + Dimension aSF; + int bNum = legendScheme.getBreakNum(); + int labWidth = 0; + g.setFont(this.tickLabelFont); + for (int i = 0; i < bNum; i++) { + caption = legendScheme.getLegendBreaks().get(i).getCaption(); + boolean isValid = true; + if (isValid) { + aSF = Draw.getStringDimension(caption, this.tickLabelAngle, g); + int labwidth = aSF.width; + if (labWidth < labwidth) { + labWidth = labwidth; + } + } + } + + return labWidth; + } + + private int getBreakHeight(Graphics2D g) { + g.setFont(tickLabelFont); + Dimension dim = Draw.getStringDimension(this.legendScheme.getLegendBreak(0).getCaption(), g); + return Math.max(dim.height, this.symbolDimension.height); + } + + /** + * Get legend dimension + * + * @param g Graphics2D + * @param limitDim Limit dimension + * @return Legend dimension + */ + public Dimension getLegendDimension(Graphics2D g, Dimension limitDim) { + if (legendScheme != null) { + if (this.colorBar) { + switch (this.orientation) { + case VERTICAL: + this.width = (int) (this.getTickWidth(g) + limitDim.height * this.shrink / this.aspect + 5); + if (this.label != null) { + g.setFont(this.label.getFont()); + this.width += (int) Draw.getStringDimension(label.getText(), g).height + 5; + } + break; + default: + g.setFont(this.tickLabelFont); + this.height = (int) (Draw.getStringDimension("test", g).height + limitDim.width * this.shrink / this.aspect + 5); + if (this.label != null) { + g.setFont(this.label.getFont()); + Dimension dim = Draw.getStringDimension(label.getText(), g); + switch (this.labelLocation) { + case "top": + case "right": + this.width += dim.width + 10; + break; + default: + this.height += (int) Draw.getStringDimension(label.getText(), g).height + 5; + break; + } + } + } + } else { + int breakHeight = getBreakHeight(g); + int titleHeight = 0; + int titleWidth = 0; + if (this.label != null) { + Dimension dim = this.label.getDimension(g); + titleHeight = dim.height + (int) (this.breakSpace * 4); + titleWidth = dim.width; + } + switch (this.orientation) { + case VERTICAL: + //Get column number + if (this.autoRowColNum) { + int tHeight = (int) (legendScheme.getBreakNum() * (breakHeight + breakSpace) + + breakSpace * 2 + breakHeight / 2 + 5); + rowColNum = 1; + if (tHeight > limitDim.height * 10 / 8) { + rowColNum = tHeight / (limitDim.height * 10 / 8) + 1; + if (rowColNum == 1) { + rowColNum = 2; + } else { + int n = legendScheme.getBreakNum() / rowColNum; + int m = legendScheme.getBreakNum() % rowColNum; + if (m != 0) { + if (m <= n) { + rowColNum += 1; + } else { + rowColNum += 2; + } + } else if (rowColNum * (limitDim.width * 8 / 10) < tHeight) { + rowColNum += 1; + } + } + } + } + + //Get width + int colWidth = this.symbolDimension.width + getMaxLabelWidth(g) + 15; + this.width = colWidth * rowColNum; + + //Get height + int[] rowNums = new int[rowColNum]; + int ave = legendScheme.getBreakNum() / rowColNum; + if (ave * rowColNum < legendScheme.getBreakNum()) { + ave += 1; + } + int num = 0; + int i; + for (i = 0; i < rowColNum - 1; i++) { + rowNums[i] = ave; + num += ave; + } + rowNums[rowColNum - 1] = legendScheme.getBreakNum() - num; + +// this.height = (int) (rowNums[0] * (breakHeight + _breakSpace) +// + _breakSpace * 2 + breakHeight / 2 + 5); + this.height = (int) (rowNums[0] * (breakHeight + breakSpace) + + breakSpace * 3); + break; + case HORIZONTAL: + //Get row number + if (this.autoRowColNum) { + int breakWidth = this.symbolDimension.width + this.getMaxLabelWidth(g) + 15; + int tWidth = breakWidth * legendScheme.getBreakNum(); + rowColNum = 1; + if (tWidth > limitDim.width * 8 / 10) { + rowColNum = tWidth / (limitDim.width * 8 / 10); + if (rowColNum == 1) { + rowColNum = 2; + } else { + int n = legendScheme.getBreakNum() / rowColNum; + int m = legendScheme.getBreakNum() % rowColNum; + if (m != 0) { + if (m <= n) { + rowColNum += 1; + } else { + rowColNum += 2; + } + } else if (rowColNum * (limitDim.width * 8 / 10) < tWidth) { + rowColNum += 1; + } + } + } + } + + //Get height + this.height = (int) (breakHeight + this.breakSpace * 2) * this.rowColNum; + + //Get width + //FontMetrics metrics = g.getFontMetrics(tickFont); + ave = legendScheme.getBreakNum() / rowColNum; + if (ave * rowColNum < legendScheme.getBreakNum()) { + ave += 1; + } + num = 0; + int maxWidth = 0; + int tempWidth = 0; + for (i = 0; i < legendScheme.getBreakNum(); i++) { + if (num < ave) { + //tempWidth += this.symbolDimension.width + 15 + // + metrics.stringWidth(legendScheme.getLegendBreaks().get(i).getCaption()); + tempWidth += this.symbolDimension.width + 15 + + Draw.getStringDimension(legendScheme.getLegendBreaks().get(i).getCaption(), g).width; + num += 1; + } else { + if (maxWidth < tempWidth) { + maxWidth = tempWidth; + } + //tempWidth = metrics.stringWidth(legendScheme.getLegendBreaks().get(i).getCaption()) + 15; + tempWidth = Draw.getStringDimension(legendScheme.getLegendBreaks().get(i).getCaption(), g).width; + num = 1; + } + } + if (maxWidth < tempWidth) { + maxWidth = tempWidth; + } + if (maxWidth > limitDim.width) { + maxWidth = limitDim.width * 8 / 10; + } + this.width = maxWidth; + break; + } + this.height += titleHeight; + this.width = Math.max(this.width, titleWidth); + } + } + + return new Dimension(this.width, this.height); + } + + protected int getTickWidth(Graphics2D g) { + float rwidth = 0; + String caption = ""; + int bNum = this.legendScheme.getBreakNum(); + //FontMetrics metrics = g.getFontMetrics(this.tickFont); + g.setFont(this.tickLabelFont); + if (this.legendScheme.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + for (int i = 0; i < bNum; i++) { + switch (this.legendScheme.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); + } else { + caption = aPB.getCaption(); + } + break; + case Polyline: + PolylineBreak aPLB = (PolylineBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); + } else { + caption = aPLB.getCaption(); + } + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); + } else { + caption = aPGB.getCaption(); + } + break; + case Image: + ColorBreak aCB = legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); + } else { + caption = aCB.getCaption(); + } + break; + } + + boolean isValid = true; + switch (legendScheme.getLegendType()) { + case GraduatedColor: + if (i == bNum - 1) { + isValid = false; + } + break; + } + if (isValid) { + //float labwidth = metrics.stringWidth(caption); + float labwidth = (float) Draw.getStringDimension(caption, this.tickLabelAngle, g).getWidth(); + if (rwidth < labwidth) { + rwidth = labwidth; + } + } + } + + return (int) rwidth; + } + + protected int getTickHeight(Graphics2D g) { + float rheight = 0; + String caption = ""; + int bNum = this.legendScheme.getBreakNum(); + //FontMetrics metrics = g.getFontMetrics(this.tickFont); + g.setFont(this.tickLabelFont); + if (this.legendScheme.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + for (int i = 0; i < bNum; i++) { + switch (this.legendScheme.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); + } else { + caption = aPB.getCaption(); + } + break; + case Polyline: + PolylineBreak aPLB = (PolylineBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); + } else { + caption = aPLB.getCaption(); + } + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); + } else { + caption = aPGB.getCaption(); + } + break; + case Image: + ColorBreak aCB = legendScheme.getLegendBreaks().get(i); + if (legendScheme.getLegendType() == LegendType.GraduatedColor) { + caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); + } else { + caption = aCB.getCaption(); + } + break; + } + + boolean isValid = true; + switch (legendScheme.getLegendType()) { + case GraduatedColor: + if (i == bNum - 1) { + isValid = false; + } + break; + } + if (isValid) { + float labheight = (float) Draw.getStringDimension(caption, 90 - Math.abs(this.tickLabelAngle), g).getWidth(); + if (rheight < labheight) { + rheight = labheight; + } + } + } + + return (int) rheight; + } + + /** + * Update tick gap + * + * @param g Graphics2D + * @return Ticks gap + */ + protected int getTickGap(Graphics2D g) { + if (this.tickLabelAngle != 0) { + return 1; + } + + double len; + int n = this.legendScheme.getBreakNum(); + int nn; + if (this.orientation == PlotOrientation.HORIZONTAL) { + len = this.width; + int labLen = this.getTickWidth(g); + nn = (int) ((len * 0.8) / labLen); + } else { + len = this.height; + FontMetrics metrics = g.getFontMetrics(tickLabelFont); + nn = (int) (len / metrics.getHeight()); + } + if (nn == 0) { + nn = 1; + } + return n / nn + 1; + } + + // + // + public class LayoutLegendBean { + + LayoutLegendBean() { + } + + // + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + neatLineSize = size; + } + + /** + * Get tick label font + * + * @return The tick label font + */ + public Font getTickLabelFont() { + return tickLabelFont; + } + + /** + * Set tick label font + * + * @param font The tick label font + */ + public void setTickLabelFont(Font font) { + tickLabelFont = font; + } + + /** + * Get column number + * + * @return Column number + */ + public int getColumnNumber() { + return rowColNum; + } + + /** + * Set column number + * + * @param value Column number + */ + public void setColumnNumber(int value) { + rowColNum = value; + } + + /** + * Get is draw background + * + * @return Boolean + */ + public boolean isDrawBackground() { + return drawBackground; + } + + /** + * Set is draw background + * + * @param value Boolean + */ + public void setDrawBackground(boolean value) { + drawBackground = value; + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackground() { + return background; + } + + /** + * Set background color + * + * @param c Background color + */ + public void setBackground(Color c) { + background = c; + } + + // + } + + public static class LayoutLegendBeanBeanInfo extends BaseBeanInfo { + + public LayoutLegendBeanBeanInfo() { + super(LayoutLegendBean.class); + ExtendedPropertyDescriptor e = addProperty("plotOrientation"); + e.setCategory("General").setDisplayName("Plot orientation"); + e.setPropertyEditorClass(PlotOrientationEditor.class); + addProperty("tickFont").setCategory("General").setDisplayName("Tick Font"); + addProperty("drawBackground").setCategory("General").setDisplayName("Draw Background"); + addProperty("background").setCategory("General").setDisplayName("Background"); + addProperty("columnNumber").setCategory("General").setDisplayName("Column Number"); + addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); + addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); + addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); + } + } + + public static class PlotOrientationEditor extends ComboBoxPropertyEditor { + + public PlotOrientationEditor() { + super(); + PlotOrientation[] orientations = PlotOrientation.values(); + String[] types = new String[orientations.length]; + int i = 0; + for (PlotOrientation type : orientations) { + types[i] = type.toString(); + i += 1; + } + setAvailableValues(types); + } + } + + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartNorthArrow.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartNorthArrow.java index a2ebf0eb..a6e9813f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartNorthArrow.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartNorthArrow.java @@ -1,298 +1,298 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.chart; - -import com.l2fprod.common.beans.BaseBeanInfo; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.PointF; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import org.meteoinfo.chart.plot.MapPlot; -import org.meteoinfo.layout.NorthArrowType; - -/** - * - * @author Yaqiang Wang - */ -public class ChartNorthArrow extends ChartElement { -// - - private MapPlot mapPlot; - private boolean _antiAlias; - private float lineWidth; - private boolean _drawNeatLine; - private Color _neatLineColor; - private float _neatLineSize; - private NorthArrowType _northArrowType; - private float _angle; - // - // - - /** - * Constructor - * - * @param mapPlot The map plot - */ - public ChartNorthArrow(MapPlot mapPlot) { - super(); - - this.setWidth(50); - this.setHeight(50); - - this.mapPlot = mapPlot; - this.lineWidth = 1; - _antiAlias = true; - _drawNeatLine = false; - _neatLineColor = Color.black; - _neatLineSize = 1; - _northArrowType = NorthArrowType.NORTHARROW_1; - _angle = 0; - } - // - // - - /** - * Get map plot - * - * @return The map plot - */ - public MapPlot getMapPlot() { - return this.mapPlot; - } - - /** - * Get line widht - * @return Line width - */ - public float getLineWidth() { - return this.lineWidth; - } - - /** - * Set line width - * @param value Line width - */ - public void setLineWidth(float value) { - this.lineWidth = value; - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get angle - * - * @return Angle - */ - public float getAngle() { - return _angle; - } - - /** - * Set angle - * - * @param angle The angle - */ - public void setAngle(float angle) { - _angle = angle; - } - - // - // - /** - * Draw text - * - * @param g Graphics2D - * @param x X - * @param y Y - */ - public void draw(Graphics2D g, float x, float y) { - AffineTransform oldMatrix = g.getTransform(); - g.translate(x, y); - if (_angle != 0) { - g.rotate(_angle); - } - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackground()); - g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); - } - - drawNorthArrow(g); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - /** - * Paint graphics - * - * @param g Graphics - * @param pageLocation Page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { - AffineTransform oldMatrix = g.getTransform(); - PointF aP = pageToScreen(this.getX(), this.getY(), pageLocation, zoom); - g.translate(aP.X, aP.Y); - g.scale(zoom, zoom); - if (_angle != 0) { - g.rotate(_angle); - } - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackground()); - g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); - } - - drawNorthArrow(g); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawNorthArrow(Graphics2D g) { - switch (_northArrowType) { - case NORTHARROW_1: - drawNorthArrow1(g); - break; - } - } - - private void drawNorthArrow1(Graphics2D g) { - g.setColor(this.getForeground()); - g.setStroke(new BasicStroke(this.lineWidth)); - - //Draw N symbol - PointF[] points = new PointF[4]; - float x = this.getWidth() / 2; - float y = this.getHeight() / 6; - float w = this.getWidth() / 6; - float h = this.getHeight() / 4; - points[0] = new PointF(x - w / 2, y + h / 2); - points[1] = new PointF(x - w / 2, y - h / 2); - points[2] = new PointF(x + w / 2, y + h / 2); - points[3] = new PointF(x + w / 2, y - h / 2); - Draw.drawPolyline(points, g); - - //Draw arrow - w = this.getWidth() / 2; - h = this.getHeight() * 2 / 3; - points = new PointF[3]; - points[0] = new PointF(x - w / 2, this.getHeight()); - points[1] = new PointF(x, this.getHeight() - h / 2); - points[2] = new PointF(x, this.getHeight() - h); - Draw.fillPolygon(points, g, null); - Draw.drawPolyline(points, g); - - points = new PointF[4]; - points[0] = new PointF(x + w / 2, this.getHeight()); - points[1] = new PointF(x, this.getHeight() - h / 2); - points[2] = new PointF(x, this.getHeight() - h); - points[3] = points[0]; - Draw.drawPolyline(points, g); - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.chart; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import org.meteoinfo.chart.plot.MapPlot; +import org.meteoinfo.layout.NorthArrowType; + +/** + * + * @author Yaqiang Wang + */ +public class ChartNorthArrow extends ChartElement { +// + + private MapPlot mapPlot; + private boolean _antiAlias; + private float lineWidth; + private boolean _drawNeatLine; + private Color _neatLineColor; + private float _neatLineSize; + private NorthArrowType _northArrowType; + private float _angle; + // + // + + /** + * Constructor + * + * @param mapPlot The map plot + */ + public ChartNorthArrow(MapPlot mapPlot) { + super(); + + this.setWidth(50); + this.setHeight(50); + + this.mapPlot = mapPlot; + this.lineWidth = 1; + _antiAlias = true; + _drawNeatLine = false; + _neatLineColor = Color.black; + _neatLineSize = 1; + _northArrowType = NorthArrowType.NORTHARROW_1; + _angle = 0; + } + // + // + + /** + * Get map plot + * + * @return The map plot + */ + public MapPlot getMapPlot() { + return this.mapPlot; + } + + /** + * Get line widht + * @return Line width + */ + public float getLineWidth() { + return this.lineWidth; + } + + /** + * Set line width + * @param value Line width + */ + public void setLineWidth(float value) { + this.lineWidth = value; + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get angle + * + * @return Angle + */ + public float getAngle() { + return _angle; + } + + /** + * Set angle + * + * @param angle The angle + */ + public void setAngle(float angle) { + _angle = angle; + } + + // + // + /** + * Draw text + * + * @param g Graphics2D + * @param x X + * @param y Y + */ + public void draw(Graphics2D g, float x, float y) { + AffineTransform oldMatrix = g.getTransform(); + g.translate(x, y); + if (_angle != 0) { + g.rotate(_angle); + } + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackground()); + g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); + } + + drawNorthArrow(g); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + /** + * Paint graphics + * + * @param g Graphics + * @param pageLocation Page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { + AffineTransform oldMatrix = g.getTransform(); + PointF aP = pageToScreen(this.getX(), this.getY(), pageLocation, zoom); + g.translate(aP.X, aP.Y); + g.scale(zoom, zoom); + if (_angle != 0) { + g.rotate(_angle); + } + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackground()); + g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); + } + + drawNorthArrow(g); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawNorthArrow(Graphics2D g) { + switch (_northArrowType) { + case NORTHARROW_1: + drawNorthArrow1(g); + break; + } + } + + private void drawNorthArrow1(Graphics2D g) { + g.setColor(this.getForeground()); + g.setStroke(new BasicStroke(this.lineWidth)); + + //Draw N symbol + PointF[] points = new PointF[4]; + float x = this.getWidth() / 2; + float y = this.getHeight() / 6; + float w = this.getWidth() / 6; + float h = this.getHeight() / 4; + points[0] = new PointF(x - w / 2, y + h / 2); + points[1] = new PointF(x - w / 2, y - h / 2); + points[2] = new PointF(x + w / 2, y + h / 2); + points[3] = new PointF(x + w / 2, y - h / 2); + Draw.drawPolyline(points, g); + + //Draw arrow + w = this.getWidth() / 2; + h = this.getHeight() * 2 / 3; + points = new PointF[3]; + points[0] = new PointF(x - w / 2, this.getHeight()); + points[1] = new PointF(x, this.getHeight() - h / 2); + points[2] = new PointF(x, this.getHeight() - h); + Draw.fillPolygon(points, g, null); + Draw.drawPolyline(points, g); + + points = new PointF[4]; + points[0] = new PointF(x + w / 2, this.getHeight()); + points[1] = new PointF(x, this.getHeight() - h / 2); + points[2] = new PointF(x, this.getHeight() - h); + points[3] = points[0]; + Draw.drawPolyline(points, g); + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartPanel.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartPanel.java index 91344501..0be014f6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartPanel.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartPanel.java @@ -81,11 +81,11 @@ import org.meteoinfo.chart.plot.AbstractPlot2D; import org.meteoinfo.chart.plot.Plot3D; import org.meteoinfo.chart.plot.PlotType; import org.meteoinfo.chart.plot3d.Projector; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.PointF; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.data.mapdata.Field; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.PointF; import org.meteoinfo.image.ImageUtil; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartScaleBar.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartScaleBar.java index a191471e..4e813f5d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartScaleBar.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartScaleBar.java @@ -1,457 +1,457 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import org.meteoinfo.chart.plot.MapPlot; -import org.meteoinfo.global.PointF; -import org.meteoinfo.layout.ScaleBarType; -import org.meteoinfo.layout.ScaleBarUnits; - -/** - * - * @author Yaqiang Wang - */ -public class ChartScaleBar extends ChartElement { - // - - private MapPlot mapPlot; - private boolean _antiAlias; - private float lineWidth; - private Font _font; - private ScaleBarType _scaleBarType; - private ScaleBarUnits _unit; - private String _unitText; - private int _numBreaks; - private boolean _drawNeatLine; - private Color _neatLineColor; - private float _neatLineSize; - private boolean _drawScaleText; - private float _yShiftScale = 2.0f; - // - // - - /** - * Constructor - * - * @param mapPlot The map plot - */ - public ChartScaleBar(MapPlot mapPlot) { - super(); - //this.setElementType(ElementType.LayoutScaleBar); - //this.setResizeAbility(ResizeAbility.ResizeAll); - - this.width = 200; - this.height = 50; - this.mapPlot = mapPlot; - _antiAlias = true; - _scaleBarType = ScaleBarType.SCALELINE_1; - lineWidth = 1; - _drawNeatLine = false; - _neatLineColor = Color.black; - _neatLineSize = 1; - _font = new Font("Arial", Font.PLAIN, 12); - _unit = ScaleBarUnits.KILOMETERS; - _unitText = "km"; - _numBreaks = 4; - _drawScaleText = false; - } - // - // - - /** - * Get map plot - * - * @return The map plot - */ - public MapPlot getMapPlot() { - return mapPlot; - } - - /** - * Get line widht - * @return Line width - */ - public float getLineWidth() { - return this.lineWidth; - } - - /** - * Set line width - * @param value Line width - */ - public void setLineWidth(float value) { - this.lineWidth = value; - } - - /** - * Get scale bar type - * - * @return Scale bar type - */ - public ScaleBarType getScaleBarType() { - return _scaleBarType; - } - - /** - * Set scale bar type - * - * @param type Scale bar type - */ - public void setScaleBarType(ScaleBarType type) { - _scaleBarType = type; - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get font - * - * @return The font - */ - public Font getFont() { - return _font; - } - - /** - * Set font - * - * @param font The font - */ - public void setFont(Font font) { - _font = font; - } - - /** - * Get break number - * - * @return The break number - */ - public int getBreakNumber() { - return _numBreaks; - } - - /** - * Set break number - * - * @param num Break number - */ - public void setBreakNumber(int num) { - _numBreaks = num; - } - - /** - * Get if draw scale text - * - * @return If draw scale text - */ - public boolean isDrawScaleText() { - return _drawScaleText; - } - - /** - * Set if draw scale text - * - * @param istrue If draw scale text - */ - public void setDrawScaleText(boolean istrue) { - _drawScaleText = istrue; - } - // - // - /** - * Draw text - * - * @param g Graphics2D - * @param x X - * @param y Y - */ - public void draw(Graphics2D g, float x, float y) { - AffineTransform oldMatrix = g.getTransform(); - g.translate(x, y); - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackground()); - g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); - } - - drawScaleBar(g); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - /** - * Paint graphics - * - * @param g Graphics - * @param pageLocation Page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation) { - AffineTransform oldMatrix = g.getTransform(); - PointF aP = pageToScreen(this.getX(), this.getY(), pageLocation, 1); - g.translate(aP.X, aP.Y); - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackground()); - g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); - } - - drawScaleBar(g); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawScaleBar(Graphics2D g) { - //Calculates the width of one break in greographic units - FontMetrics metrics = g.getFontMetrics(this._font); - float unitLegnth = metrics.stringWidth(_unitText) * 2; - float widthNoUnit = (this.getWidth() - unitLegnth); - long geoBreakWidth = (long) (getGeoWidth(widthNoUnit / _numBreaks)); - - //If the geobreakWidth is less than 1 we return and don't draw anything - if (geoBreakWidth < 1) { - return; - } - - double n = Math.pow(10, String.valueOf(geoBreakWidth).length() - 1); - geoBreakWidth = (long) (Math.floor(geoBreakWidth / n) * n); - - long breakWidth = (long) (getWidth(geoBreakWidth)); - FontMetrics metrics1 = g.getFontMetrics(_font); - float fontHeight = metrics1.getHeight(); - float leftStart = metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - - //Draw scale text - double scale = geoBreakWidth * getConversionFactor(_unit) * 100 / (breakWidth / 96 * 2.539999918); - if (_drawScaleText) { - g.setFont(this._font); - g.setColor(this.getForeground()); - g.drawString("1 : " + String.format("{0:0,0}", scale), - leftStart - (metrics.stringWidth(String.valueOf(Math.abs(0))) / 2), fontHeight * 2.5F); - } - - //Draw scale bar - switch (_scaleBarType) { - case SCALELINE_1: - drawScaleLine1(g, breakWidth, geoBreakWidth); - break; - case SCALELINE_2: - drawScaleLine2(g, breakWidth, geoBreakWidth); - break; - case ALTERNATING_BAR: - drawAlternatingBar(g, breakWidth, geoBreakWidth); - break; - } - } - - private double getConversionFactor(ScaleBarUnits unit) { - switch (unit) { - case KILOMETERS: - return 1000; - default: - return 1; - } - } - - private double getGeoWidth(double width) { - double geoWidth = width / mapPlot.getMapFrame().getMapView().getXScale() / getConversionFactor(_unit); - if (mapPlot.getMapFrame().getMapView().getProjection().isLonLatMap()) { - geoWidth = geoWidth * getLonDistScale(); - } - - return geoWidth; - } - - private double getWidth(double geoWidth) { - double width = geoWidth * mapPlot.getMapFrame().getMapView().getXScale() * getConversionFactor(_unit); - if (mapPlot.getMapFrame().getMapView().getProjection().isLonLatMap()) { - width = width / getLonDistScale(); - } - - return width; - } - - private double getLonDistScale() { - //Get meters of one longitude degree - double pY = (mapPlot.getMapFrame().getMapView().getViewExtent().maxY + mapPlot.getMapFrame().getMapView().getViewExtent().minY) / 2; - double ProjX = 0, ProjY = pY, pProjX = 1, pProjY = pY; - double dx = Math.abs(ProjX - pProjX); - double dy = Math.abs(ProjY - pProjY); - double dist; - double y = (ProjY + pProjY) / 2; - double factor = Math.cos(y * Math.PI / 180); - dx *= factor; - dist = Math.sqrt(dx * dx + dy * dy); - dist = dist * 111319.5; - - return dist; - } - - private void drawScaleLine1(Graphics2D g, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight(); - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 10; - - g.setColor(this.getForeground()); - g.setStroke(new BasicStroke(this.lineWidth)); - g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); - g.setFont(this._font); - for (int i = 0; i <= _numBreaks; i++) { - g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight * 1.6f + yShift)); - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - } - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - private void drawScaleLine2(Graphics2D g, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight(); - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 5; - - g.setColor(this.getForeground()); - g.setStroke(new BasicStroke(this.lineWidth)); - g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); - g.setFont(this._font); - for (int i = 0; i <= _numBreaks; i++) { - g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight + (fontHeight * 1.1f) + yShift)); - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - } - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - private void drawAlternatingBar(Graphics2D g, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight(); - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 5; - float rHeight = fontHeight / 2; - - boolean isFill = false; - g.setStroke(new BasicStroke(this.lineWidth)); - g.setColor(this.getForeground()); - g.setFont(this._font); - for (int i = 0; i <= _numBreaks; i++) { - if (i < _numBreaks) { - if (isFill) { - g.fill(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); - } - g.draw(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); - } - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - isFill = !isFill; - } - g.setColor(this.getForeground()); - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import org.meteoinfo.chart.plot.MapPlot; +import org.meteoinfo.common.PointF; +import org.meteoinfo.layout.ScaleBarType; +import org.meteoinfo.layout.ScaleBarUnits; + +/** + * + * @author Yaqiang Wang + */ +public class ChartScaleBar extends ChartElement { + // + + private MapPlot mapPlot; + private boolean _antiAlias; + private float lineWidth; + private Font _font; + private ScaleBarType _scaleBarType; + private ScaleBarUnits _unit; + private String _unitText; + private int _numBreaks; + private boolean _drawNeatLine; + private Color _neatLineColor; + private float _neatLineSize; + private boolean _drawScaleText; + private float _yShiftScale = 2.0f; + // + // + + /** + * Constructor + * + * @param mapPlot The map plot + */ + public ChartScaleBar(MapPlot mapPlot) { + super(); + //this.setElementType(ElementType.LayoutScaleBar); + //this.setResizeAbility(ResizeAbility.ResizeAll); + + this.width = 200; + this.height = 50; + this.mapPlot = mapPlot; + _antiAlias = true; + _scaleBarType = ScaleBarType.SCALELINE_1; + lineWidth = 1; + _drawNeatLine = false; + _neatLineColor = Color.black; + _neatLineSize = 1; + _font = new Font("Arial", Font.PLAIN, 12); + _unit = ScaleBarUnits.KILOMETERS; + _unitText = "km"; + _numBreaks = 4; + _drawScaleText = false; + } + // + // + + /** + * Get map plot + * + * @return The map plot + */ + public MapPlot getMapPlot() { + return mapPlot; + } + + /** + * Get line widht + * @return Line width + */ + public float getLineWidth() { + return this.lineWidth; + } + + /** + * Set line width + * @param value Line width + */ + public void setLineWidth(float value) { + this.lineWidth = value; + } + + /** + * Get scale bar type + * + * @return Scale bar type + */ + public ScaleBarType getScaleBarType() { + return _scaleBarType; + } + + /** + * Set scale bar type + * + * @param type Scale bar type + */ + public void setScaleBarType(ScaleBarType type) { + _scaleBarType = type; + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get font + * + * @return The font + */ + public Font getFont() { + return _font; + } + + /** + * Set font + * + * @param font The font + */ + public void setFont(Font font) { + _font = font; + } + + /** + * Get break number + * + * @return The break number + */ + public int getBreakNumber() { + return _numBreaks; + } + + /** + * Set break number + * + * @param num Break number + */ + public void setBreakNumber(int num) { + _numBreaks = num; + } + + /** + * Get if draw scale text + * + * @return If draw scale text + */ + public boolean isDrawScaleText() { + return _drawScaleText; + } + + /** + * Set if draw scale text + * + * @param istrue If draw scale text + */ + public void setDrawScaleText(boolean istrue) { + _drawScaleText = istrue; + } + // + // + /** + * Draw text + * + * @param g Graphics2D + * @param x X + * @param y Y + */ + public void draw(Graphics2D g, float x, float y) { + AffineTransform oldMatrix = g.getTransform(); + g.translate(x, y); + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackground()); + g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); + } + + drawScaleBar(g); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + /** + * Paint graphics + * + * @param g Graphics + * @param pageLocation Page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation) { + AffineTransform oldMatrix = g.getTransform(); + PointF aP = pageToScreen(this.getX(), this.getY(), pageLocation, 1); + g.translate(aP.X, aP.Y); + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackground()); + g.fill(new Rectangle.Float(0, 0, this.getWidth(), this.getHeight())); + } + + drawScaleBar(g); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize), (this.getHeight() - _neatLineSize)); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawScaleBar(Graphics2D g) { + //Calculates the width of one break in greographic units + FontMetrics metrics = g.getFontMetrics(this._font); + float unitLegnth = metrics.stringWidth(_unitText) * 2; + float widthNoUnit = (this.getWidth() - unitLegnth); + long geoBreakWidth = (long) (getGeoWidth(widthNoUnit / _numBreaks)); + + //If the geobreakWidth is less than 1 we return and don't draw anything + if (geoBreakWidth < 1) { + return; + } + + double n = Math.pow(10, String.valueOf(geoBreakWidth).length() - 1); + geoBreakWidth = (long) (Math.floor(geoBreakWidth / n) * n); + + long breakWidth = (long) (getWidth(geoBreakWidth)); + FontMetrics metrics1 = g.getFontMetrics(_font); + float fontHeight = metrics1.getHeight(); + float leftStart = metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + + //Draw scale text + double scale = geoBreakWidth * getConversionFactor(_unit) * 100 / (breakWidth / 96 * 2.539999918); + if (_drawScaleText) { + g.setFont(this._font); + g.setColor(this.getForeground()); + g.drawString("1 : " + String.format("{0:0,0}", scale), + leftStart - (metrics.stringWidth(String.valueOf(Math.abs(0))) / 2), fontHeight * 2.5F); + } + + //Draw scale bar + switch (_scaleBarType) { + case SCALELINE_1: + drawScaleLine1(g, breakWidth, geoBreakWidth); + break; + case SCALELINE_2: + drawScaleLine2(g, breakWidth, geoBreakWidth); + break; + case ALTERNATING_BAR: + drawAlternatingBar(g, breakWidth, geoBreakWidth); + break; + } + } + + private double getConversionFactor(ScaleBarUnits unit) { + switch (unit) { + case KILOMETERS: + return 1000; + default: + return 1; + } + } + + private double getGeoWidth(double width) { + double geoWidth = width / mapPlot.getMapFrame().getMapView().getXScale() / getConversionFactor(_unit); + if (mapPlot.getMapFrame().getMapView().getProjection().isLonLatMap()) { + geoWidth = geoWidth * getLonDistScale(); + } + + return geoWidth; + } + + private double getWidth(double geoWidth) { + double width = geoWidth * mapPlot.getMapFrame().getMapView().getXScale() * getConversionFactor(_unit); + if (mapPlot.getMapFrame().getMapView().getProjection().isLonLatMap()) { + width = width / getLonDistScale(); + } + + return width; + } + + private double getLonDistScale() { + //Get meters of one longitude degree + double pY = (mapPlot.getMapFrame().getMapView().getViewExtent().maxY + mapPlot.getMapFrame().getMapView().getViewExtent().minY) / 2; + double ProjX = 0, ProjY = pY, pProjX = 1, pProjY = pY; + double dx = Math.abs(ProjX - pProjX); + double dy = Math.abs(ProjY - pProjY); + double dist; + double y = (ProjY + pProjY) / 2; + double factor = Math.cos(y * Math.PI / 180); + dx *= factor; + dist = Math.sqrt(dx * dx + dy * dy); + dist = dist * 111319.5; + + return dist; + } + + private void drawScaleLine1(Graphics2D g, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight(); + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 10; + + g.setColor(this.getForeground()); + g.setStroke(new BasicStroke(this.lineWidth)); + g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); + g.setFont(this._font); + for (int i = 0; i <= _numBreaks; i++) { + g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight * 1.6f + yShift)); + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + } + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + private void drawScaleLine2(Graphics2D g, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight(); + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 5; + + g.setColor(this.getForeground()); + g.setStroke(new BasicStroke(this.lineWidth)); + g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); + g.setFont(this._font); + for (int i = 0; i <= _numBreaks; i++) { + g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight + (fontHeight * 1.1f) + yShift)); + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + } + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + private void drawAlternatingBar(Graphics2D g, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight(); + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 5; + float rHeight = fontHeight / 2; + + boolean isFill = false; + g.setStroke(new BasicStroke(this.lineWidth)); + g.setColor(this.getForeground()); + g.setFont(this._font); + for (int i = 0; i <= _numBreaks; i++) { + if (i < _numBreaks) { + if (isFill) { + g.fill(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); + } + g.draw(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); + } + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + isFill = !isFill; + } + g.setColor(this.getForeground()); + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText.java index 7aefc4be..716e9294 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText.java @@ -1,740 +1,740 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.meteoinfo.chart.plot.XAlign; -import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Extent; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryFactory; -import org.meteoinfo.shape.Shape; -import org.meteoinfo.shape.ShapeTypes; - -/** - * - * @author yaqiang - */ -public class ChartText extends Shape { - - // - protected double x; - protected double y; - private Font font; - private List text; - private Color color; - private int lineSpace; - private CoordinateType coordinates; - private Color background; - private boolean drawBackground; - private boolean drawNeatline; - private Color neatLineColor; - private float neatLineSize; - private float gap; - protected float angle; - private XAlign xAlign; - private YAlign yAlign; - private boolean useExternalFont; - protected double xShift; - protected double yShift; - - // - // - /** - * Constructor - */ - public ChartText() { - font = new Font("Arial", Font.PLAIN, 14); - color = Color.black; - lineSpace = 5; - coordinates = CoordinateType.DATA; - this.background = Color.white; - this.drawBackground = false; - this.drawNeatline = false; - this.neatLineColor = Color.black; - this.neatLineSize = 1.0f; - this.gap = 3.0f; - this.angle = 0.0f; - this.xAlign = XAlign.LEFT; - this.yAlign = YAlign.BOTTOM; - this.useExternalFont = false; - this.xShift = 0; - this.yShift = 0; - } - - /** - * Constructor - * - * @param text Text - */ - public ChartText(String text) { - this(); - this.text = new ArrayList<>(); - String[] lines = text.split("\n"); - this.text.addAll(Arrays.asList(lines)); - } - - /** - * Constructor - * - * @param text Text - */ - public ChartText(List text) { - this(); - this.text = text; - } - - /** - * Constructor - * - * @param text Text - * @param font Font - */ - public ChartText(String text, Font font) { - this(); - this.text = new ArrayList<>(); - String[] lines = text.split("\n"); - this.text.addAll(Arrays.asList(lines)); - this.font = font; - } - - /** - * Constructor - * - * @param text Text - * @param font Font - */ - public ChartText(List text, Font font) { - this(); - this.text = text; - this.font = font; - } - // - // - - /** - * Get text - * - * @return Text - */ - public String getText() { - return text.get(0); - } - - /** - * Set text - * - * @param value Text - */ - public void setText(String value) { - text = new ArrayList<>(); - String[] lines = value.split("\n"); - this.text.addAll(Arrays.asList(lines)); - } - - /** - * Get texts - * - * @return Text list - */ - public List getTexts() { - return text; - } - - /** - * Set texts - * - * @param value Text list - */ - public void setTexts(List value) { - text = value; - } - - /** - * Get font - * - * @return Font - */ - public Font getFont() { - return font; - } - - /** - * Set font - * - * @param value Font - */ - public void setFont(Font value) { - font = value; - } - - /** - * Get title color - * - * @return Title color - */ - public Color getColor() { - return color; - } - - /** - * Set title color - * - * @param value Title color - */ - public void setColor(Color value) { - this.color = value; - } - - /** - * Get x - * - * @return X - */ - public double getX() { - return this.x; - } - - /** - * Set x - * - * @param value X - */ - public void setX(double value) { - this.x = value; - } - - /** - * Get y - * - * @return Y - */ - public double getY() { - return this.y; - } - - /** - * Set y - * - * @param value Y - */ - public void setY(double value) { - this.y = value; - } - - /** - * Get line space - * - * @return Line space - */ - public int getLineSpace() { - return this.lineSpace; - } - - /** - * Set line space - * - * @param value Line space - */ - public void setLineSpace(int value) { - this.lineSpace = value; - } - - /** - * Get coordinates - * - * @return Coordinates - */ - public CoordinateType getCoordinates() { - return this.coordinates; - } - - /** - * Set coordinates - * - * @param value Coordinates - */ - public void setCoordinates(CoordinateType value) { - this.coordinates = value; - } - - /** - * Set coordinates - * - * @param value Coordinates - */ - public void setCoordinates(String value) { - switch (value) { - case "axes": - this.coordinates = CoordinateType.AXES; - break; - case "figure": - this.coordinates = CoordinateType.FIGURE; - break; - case "data": - this.coordinates = CoordinateType.DATA; - break; - case "inches": - this.coordinates = CoordinateType.INCHES; - break; - } - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackground() { - return this.background; - } - - /** - * Set background color - * - * @param value Background color - */ - public void setBackground(Color value) { - this.background = value; - } - - /** - * Get if is fill background - * - * @return Boolean - */ - public boolean isFill() { - return this.drawBackground; - } - - /** - * Set fill background or not - * - * @param value Boolean - */ - public void setFill(boolean value) { - this.drawBackground = value; - } - - /** - * Get draw neatline or not - * - * @return Boolean - */ - public boolean isDrawNeatline() { - return this.drawNeatline; - } - - /** - * Set draw neatline or not - * - * @param value Boolean - */ - public void setDrawNeatline(boolean value) { - this.drawNeatline = value; - } - - /** - * Get neatline color - * - * @return Neatline color - */ - public Color getNeatlineColor() { - return this.neatLineColor; - } - - /** - * Set neatline color - * - * @param value Neatline color - */ - public void setNeatlineColor(Color value) { - this.neatLineColor = value; - } - - /** - * Get neatline size - * - * @return Neatline size - */ - public float getNeatlineSize() { - return this.neatLineSize; - } - - /** - * Set neatline size - * - * @param value Neatline size - */ - public void setNeatlineSize(float value) { - this.neatLineSize = value; - } - - /** - * Get gap - * - * @return Gap - */ - public float getGap() { - return this.gap; - } - - /** - * Set gap - * - * @param value Gap - */ - public void setGap(float value) { - this.gap = value; - } - - /** - * Get angle - * - * @return Angle - */ - public float getAngle() { - return this.angle; - } - - /** - * Set angle - * - * @param value Angle - */ - public void setAngle(float value) { - this.angle = value; - } - - /** - * Get x align - * - * @return X align - */ - public XAlign getXAlign() { - return this.xAlign; - } - - /** - * Set x align - * - * @param value X align - */ - public void setXAlign(XAlign value) { - this.xAlign = value; - } - - /** - * Set x align - * - * @param value X align string - */ - public void setXAlign(String value) { - this.xAlign = XAlign.valueOf(value.toUpperCase()); - } - - /** - * Get y align - * - * @return Y align - */ - public YAlign getYAlign() { - return this.yAlign; - } - - /** - * Set y align - * - * @param value Y align - */ - public void setYAlign(YAlign value) { - this.yAlign = value; - } - - /** - * Set y align - * - * @param value Y align string - */ - public void setYAlign(String value) { - this.yAlign = YAlign.valueOf(value.toUpperCase()); - } - - /** - * Get if use external font - only for LaTeX string - * - * @return Boolean - */ - public boolean isUseExternalFont() { - return this.useExternalFont; - } - - /** - * Set if use external font - only for LaTeX string - * - * @param value Boolean - */ - public void setUseExternalFont(boolean value) { - this.useExternalFont = value; - } - - /** - * Get x shift - * @return X shift - */ - public double getXShift() { - return this.xShift; - } - - /** - * Set x shift - * @param value X shift - */ - public void setXShift(double value) { - this.xShift = value; - } - - /** - * Get y shift - * @return Y shift - */ - public double getYShift() { - return this.yShift; - } - - /** - * Set y shift - * @param value Y shift - */ - public void setYShift(double value) { - this.yShift = value; - } - - // - // - /** - * Add text in new line - * - * @param value The text string - */ - public void addText(String value) { - this.text.add(value); - } - - @Override - public ShapeTypes getShapeType() { - return ShapeTypes.TEXT; - } - - /** - * Get text line number - * - * @return Text line number - */ - public int getLineNum() { - return this.text.size(); - } - - /** - * Get text dimension with angle - * - * @param g Graphics2D - * @return Dimension - */ - public Dimension getTrueDimension(Graphics2D g) { - Dimension dim = getDimension(g); - if (this.angle != 0) { - int width = dim.width; - int height = dim.height; - int temp; - if (angle == 90 || angle == -90) { - temp = width; - width = height; - height = temp; - } else { - width = (int) ((width * Math.cos(Math.toRadians(angle))) + (height * Math.sin(Math.toRadians(angle)))); - height = (int) ((width * Math.sin(Math.toRadians(angle))) + (height * Math.cos(Math.toRadians(angle)))); - } - return new Dimension(width, height); - } else { - return dim; - } - } - - /** - * Get text dimension - * - * @param g Graphics2D - * @return Dimension - */ - public Dimension getDimension(Graphics2D g) { - g.setFont(font); - int width = 0, height = 0; - for (String line : this.text) { - Dimension dim = Draw.getStringDimension(line, g); - if (width < dim.width) { - width = dim.width; - } - height += dim.height + this.lineSpace; - } - height -= this.lineSpace; - - return new Dimension(width, height); - } - - /** - * To geometry method - * - * @param factory GeometryFactory - * @return Geometry - */ - @Override - public Geometry toGeometry(GeometryFactory factory) { - return null; - } - - /** - * Set point - * - * @param x X - * @param y Y - */ - public void setPoint(double x, double y) { - this.x = x; - this.y = y; - Extent aExtent = new Extent(); - aExtent.minX = x; - aExtent.maxX = x; - aExtent.minY = y; - aExtent.maxY = y; - this.setExtent(aExtent); - } - - /** - * To string - * - * @return String - */ - @Override - public String toString() { - if (this.text.size() == 1) { - return this.text.get(0); - } else { - String r = ""; - for (int i = 0; i < this.text.size(); i++) { - if (i == 0) { - r = this.text.get(i); - } else { - r = r + "\n" + this.text.get(i); - } - } - return r; - } - } - - /** - * Draw text - * - * @param g Graphics2D - * @param x X - * @param y Y - */ - public void draw(Graphics2D g, float x, float y) { - Dimension dim = this.getDimension(g); - x += this.xShift; - y += this.yShift; - - AffineTransform tempTrans = g.getTransform(); - if (this.angle != 0) { - //AffineTransform myTrans = new AffineTransform(); - AffineTransform myTrans = (AffineTransform) tempTrans.clone(); - myTrans.translate(x, y); - //myTrans.translate(tempTrans.getTranslateX() + x, tempTrans.getTranslateY() + y); - myTrans.rotate(-angle * Math.PI / 180); - g.setTransform(myTrans); - x = 0; - y = 0; - } - - Rectangle.Double rect = new Rectangle.Double(x, y - dim.getHeight(), dim.getWidth(), dim.getHeight()); - rect.setRect(rect.x - gap, rect.y - gap, rect.width + gap * 2, - rect.height + gap * 2); - if (this.drawBackground) { - g.setColor(this.background); - g.fill(rect); - } - if (this.drawNeatline) { - g.setColor(this.neatLineColor); - Stroke oldStroke = g.getStroke(); - g.setStroke(new BasicStroke(neatLineSize)); - g.draw(rect); - g.setStroke(oldStroke); - } - - g.setColor(this.color); - g.setFont(font); - switch (this.yAlign) { - case BOTTOM: - y = y - dim.height; - break; - case CENTER: - y = y - dim.height * 0.5f; - break; - } - - for (String str : this.text) { - dim = Draw.getStringDimension(str, g); - Draw.drawString(g, x, y, str, xAlign, YAlign.TOP, useExternalFont); - y += dim.height; - y += this.lineSpace; - } - - if (this.angle != 0) { - g.setTransform(tempTrans); - } - } - - /** - * Clone - * - * @return Cloned object - */ - @Override - public Object clone() { - ChartText ct = new ChartText(); - ct.angle = this.angle; - ct.background = this.background; - ct.color = this.color; - ct.coordinates = this.coordinates; - ct.drawBackground = this.drawBackground; - ct.drawNeatline = this.drawNeatline; - ct.font = this.font; - ct.gap = this.gap; - ct.lineSpace = this.lineSpace; - ct.neatLineColor = this.neatLineColor; - ct.neatLineSize = this.neatLineSize; - ct.text = this.text; - ct.useExternalFont = this.useExternalFont; - ct.x = this.x; - ct.xAlign = this.xAlign; - ct.y = this.y; - ct.yAlign = this.yAlign; - - return ct; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.meteoinfo.chart.plot.XAlign; +import org.meteoinfo.chart.plot.YAlign; +import org.meteoinfo.common.Extent; +import org.meteoinfo.drawing.Draw; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.meteoinfo.shape.Shape; +import org.meteoinfo.shape.ShapeTypes; + +/** + * + * @author yaqiang + */ +public class ChartText extends Shape { + + // + protected double x; + protected double y; + private Font font; + private List text; + private Color color; + private int lineSpace; + private CoordinateType coordinates; + private Color background; + private boolean drawBackground; + private boolean drawNeatline; + private Color neatLineColor; + private float neatLineSize; + private float gap; + protected float angle; + private XAlign xAlign; + private YAlign yAlign; + private boolean useExternalFont; + protected double xShift; + protected double yShift; + + // + // + /** + * Constructor + */ + public ChartText() { + font = new Font("Arial", Font.PLAIN, 14); + color = Color.black; + lineSpace = 5; + coordinates = CoordinateType.DATA; + this.background = Color.white; + this.drawBackground = false; + this.drawNeatline = false; + this.neatLineColor = Color.black; + this.neatLineSize = 1.0f; + this.gap = 3.0f; + this.angle = 0.0f; + this.xAlign = XAlign.LEFT; + this.yAlign = YAlign.BOTTOM; + this.useExternalFont = false; + this.xShift = 0; + this.yShift = 0; + } + + /** + * Constructor + * + * @param text Text + */ + public ChartText(String text) { + this(); + this.text = new ArrayList<>(); + String[] lines = text.split("\n"); + this.text.addAll(Arrays.asList(lines)); + } + + /** + * Constructor + * + * @param text Text + */ + public ChartText(List text) { + this(); + this.text = text; + } + + /** + * Constructor + * + * @param text Text + * @param font Font + */ + public ChartText(String text, Font font) { + this(); + this.text = new ArrayList<>(); + String[] lines = text.split("\n"); + this.text.addAll(Arrays.asList(lines)); + this.font = font; + } + + /** + * Constructor + * + * @param text Text + * @param font Font + */ + public ChartText(List text, Font font) { + this(); + this.text = text; + this.font = font; + } + // + // + + /** + * Get text + * + * @return Text + */ + public String getText() { + return text.get(0); + } + + /** + * Set text + * + * @param value Text + */ + public void setText(String value) { + text = new ArrayList<>(); + String[] lines = value.split("\n"); + this.text.addAll(Arrays.asList(lines)); + } + + /** + * Get texts + * + * @return Text list + */ + public List getTexts() { + return text; + } + + /** + * Set texts + * + * @param value Text list + */ + public void setTexts(List value) { + text = value; + } + + /** + * Get font + * + * @return Font + */ + public Font getFont() { + return font; + } + + /** + * Set font + * + * @param value Font + */ + public void setFont(Font value) { + font = value; + } + + /** + * Get title color + * + * @return Title color + */ + public Color getColor() { + return color; + } + + /** + * Set title color + * + * @param value Title color + */ + public void setColor(Color value) { + this.color = value; + } + + /** + * Get x + * + * @return X + */ + public double getX() { + return this.x; + } + + /** + * Set x + * + * @param value X + */ + public void setX(double value) { + this.x = value; + } + + /** + * Get y + * + * @return Y + */ + public double getY() { + return this.y; + } + + /** + * Set y + * + * @param value Y + */ + public void setY(double value) { + this.y = value; + } + + /** + * Get line space + * + * @return Line space + */ + public int getLineSpace() { + return this.lineSpace; + } + + /** + * Set line space + * + * @param value Line space + */ + public void setLineSpace(int value) { + this.lineSpace = value; + } + + /** + * Get coordinates + * + * @return Coordinates + */ + public CoordinateType getCoordinates() { + return this.coordinates; + } + + /** + * Set coordinates + * + * @param value Coordinates + */ + public void setCoordinates(CoordinateType value) { + this.coordinates = value; + } + + /** + * Set coordinates + * + * @param value Coordinates + */ + public void setCoordinates(String value) { + switch (value) { + case "axes": + this.coordinates = CoordinateType.AXES; + break; + case "figure": + this.coordinates = CoordinateType.FIGURE; + break; + case "data": + this.coordinates = CoordinateType.DATA; + break; + case "inches": + this.coordinates = CoordinateType.INCHES; + break; + } + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackground() { + return this.background; + } + + /** + * Set background color + * + * @param value Background color + */ + public void setBackground(Color value) { + this.background = value; + } + + /** + * Get if is fill background + * + * @return Boolean + */ + public boolean isFill() { + return this.drawBackground; + } + + /** + * Set fill background or not + * + * @param value Boolean + */ + public void setFill(boolean value) { + this.drawBackground = value; + } + + /** + * Get draw neatline or not + * + * @return Boolean + */ + public boolean isDrawNeatline() { + return this.drawNeatline; + } + + /** + * Set draw neatline or not + * + * @param value Boolean + */ + public void setDrawNeatline(boolean value) { + this.drawNeatline = value; + } + + /** + * Get neatline color + * + * @return Neatline color + */ + public Color getNeatlineColor() { + return this.neatLineColor; + } + + /** + * Set neatline color + * + * @param value Neatline color + */ + public void setNeatlineColor(Color value) { + this.neatLineColor = value; + } + + /** + * Get neatline size + * + * @return Neatline size + */ + public float getNeatlineSize() { + return this.neatLineSize; + } + + /** + * Set neatline size + * + * @param value Neatline size + */ + public void setNeatlineSize(float value) { + this.neatLineSize = value; + } + + /** + * Get gap + * + * @return Gap + */ + public float getGap() { + return this.gap; + } + + /** + * Set gap + * + * @param value Gap + */ + public void setGap(float value) { + this.gap = value; + } + + /** + * Get angle + * + * @return Angle + */ + public float getAngle() { + return this.angle; + } + + /** + * Set angle + * + * @param value Angle + */ + public void setAngle(float value) { + this.angle = value; + } + + /** + * Get x align + * + * @return X align + */ + public XAlign getXAlign() { + return this.xAlign; + } + + /** + * Set x align + * + * @param value X align + */ + public void setXAlign(XAlign value) { + this.xAlign = value; + } + + /** + * Set x align + * + * @param value X align string + */ + public void setXAlign(String value) { + this.xAlign = XAlign.valueOf(value.toUpperCase()); + } + + /** + * Get y align + * + * @return Y align + */ + public YAlign getYAlign() { + return this.yAlign; + } + + /** + * Set y align + * + * @param value Y align + */ + public void setYAlign(YAlign value) { + this.yAlign = value; + } + + /** + * Set y align + * + * @param value Y align string + */ + public void setYAlign(String value) { + this.yAlign = YAlign.valueOf(value.toUpperCase()); + } + + /** + * Get if use external font - only for LaTeX string + * + * @return Boolean + */ + public boolean isUseExternalFont() { + return this.useExternalFont; + } + + /** + * Set if use external font - only for LaTeX string + * + * @param value Boolean + */ + public void setUseExternalFont(boolean value) { + this.useExternalFont = value; + } + + /** + * Get x shift + * @return X shift + */ + public double getXShift() { + return this.xShift; + } + + /** + * Set x shift + * @param value X shift + */ + public void setXShift(double value) { + this.xShift = value; + } + + /** + * Get y shift + * @return Y shift + */ + public double getYShift() { + return this.yShift; + } + + /** + * Set y shift + * @param value Y shift + */ + public void setYShift(double value) { + this.yShift = value; + } + + // + // + /** + * Add text in new line + * + * @param value The text string + */ + public void addText(String value) { + this.text.add(value); + } + + @Override + public ShapeTypes getShapeType() { + return ShapeTypes.TEXT; + } + + /** + * Get text line number + * + * @return Text line number + */ + public int getLineNum() { + return this.text.size(); + } + + /** + * Get text dimension with angle + * + * @param g Graphics2D + * @return Dimension + */ + public Dimension getTrueDimension(Graphics2D g) { + Dimension dim = getDimension(g); + if (this.angle != 0) { + int width = dim.width; + int height = dim.height; + int temp; + if (angle == 90 || angle == -90) { + temp = width; + width = height; + height = temp; + } else { + width = (int) ((width * Math.cos(Math.toRadians(angle))) + (height * Math.sin(Math.toRadians(angle)))); + height = (int) ((width * Math.sin(Math.toRadians(angle))) + (height * Math.cos(Math.toRadians(angle)))); + } + return new Dimension(width, height); + } else { + return dim; + } + } + + /** + * Get text dimension + * + * @param g Graphics2D + * @return Dimension + */ + public Dimension getDimension(Graphics2D g) { + g.setFont(font); + int width = 0, height = 0; + for (String line : this.text) { + Dimension dim = Draw.getStringDimension(line, g); + if (width < dim.width) { + width = dim.width; + } + height += dim.height + this.lineSpace; + } + height -= this.lineSpace; + + return new Dimension(width, height); + } + + /** + * To geometry method + * + * @param factory GeometryFactory + * @return Geometry + */ + @Override + public Geometry toGeometry(GeometryFactory factory) { + return null; + } + + /** + * Set point + * + * @param x X + * @param y Y + */ + public void setPoint(double x, double y) { + this.x = x; + this.y = y; + Extent aExtent = new Extent(); + aExtent.minX = x; + aExtent.maxX = x; + aExtent.minY = y; + aExtent.maxY = y; + this.setExtent(aExtent); + } + + /** + * To string + * + * @return String + */ + @Override + public String toString() { + if (this.text.size() == 1) { + return this.text.get(0); + } else { + String r = ""; + for (int i = 0; i < this.text.size(); i++) { + if (i == 0) { + r = this.text.get(i); + } else { + r = r + "\n" + this.text.get(i); + } + } + return r; + } + } + + /** + * Draw text + * + * @param g Graphics2D + * @param x X + * @param y Y + */ + public void draw(Graphics2D g, float x, float y) { + Dimension dim = this.getDimension(g); + x += this.xShift; + y += this.yShift; + + AffineTransform tempTrans = g.getTransform(); + if (this.angle != 0) { + //AffineTransform myTrans = new AffineTransform(); + AffineTransform myTrans = (AffineTransform) tempTrans.clone(); + myTrans.translate(x, y); + //myTrans.translate(tempTrans.getTranslateX() + x, tempTrans.getTranslateY() + y); + myTrans.rotate(-angle * Math.PI / 180); + g.setTransform(myTrans); + x = 0; + y = 0; + } + + Rectangle.Double rect = new Rectangle.Double(x, y - dim.getHeight(), dim.getWidth(), dim.getHeight()); + rect.setRect(rect.x - gap, rect.y - gap, rect.width + gap * 2, + rect.height + gap * 2); + if (this.drawBackground) { + g.setColor(this.background); + g.fill(rect); + } + if (this.drawNeatline) { + g.setColor(this.neatLineColor); + Stroke oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(neatLineSize)); + g.draw(rect); + g.setStroke(oldStroke); + } + + g.setColor(this.color); + g.setFont(font); + switch (this.yAlign) { + case BOTTOM: + y = y - dim.height; + break; + case CENTER: + y = y - dim.height * 0.5f; + break; + } + + for (String str : this.text) { + dim = Draw.getStringDimension(str, g); + Draw.drawString(g, x, y, str, xAlign, YAlign.TOP, useExternalFont); + y += dim.height; + y += this.lineSpace; + } + + if (this.angle != 0) { + g.setTransform(tempTrans); + } + } + + /** + * Clone + * + * @return Cloned object + */ + @Override + public Object clone() { + ChartText ct = new ChartText(); + ct.angle = this.angle; + ct.background = this.background; + ct.color = this.color; + ct.coordinates = this.coordinates; + ct.drawBackground = this.drawBackground; + ct.drawNeatline = this.drawNeatline; + ct.font = this.font; + ct.gap = this.gap; + ct.lineSpace = this.lineSpace; + ct.neatLineColor = this.neatLineColor; + ct.neatLineSize = this.neatLineSize; + ct.text = this.text; + ct.useExternalFont = this.useExternalFont; + ct.x = this.x; + ct.xAlign = this.xAlign; + ct.y = this.y; + ct.yAlign = this.yAlign; + + return ct; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText3D.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText3D.java index c2fcef04..9f1bdd42 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText3D.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartText3D.java @@ -1,127 +1,127 @@ -/* This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.chart; - -import java.awt.Point; -import org.meteoinfo.chart.plot3d.Projector; -import org.meteoinfo.data.DataMath; -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.shape.PointZ; - -/** - * - * @author Yaqiang Wang - * yaqiang.wang@gmail.com - */ -public class ChartText3D extends ChartText { - private double z; - private PointZ zdir = null; - - /** - * Get z coordinate value - * @return Z coordinate value - */ - public double getZ(){ - return this.z; - } - - /** - * Set z coordinate value - * @param value Z coordinate value - */ - public void setZ(double value){ - this.z = value; - } - - /** - * Get zdir point - * @return ZDir point - */ - public PointZ getZDir(){ - return zdir; - } - - /** - * Set zdir point - * @param value ZDir point - */ - public void setZDir(PointZ value){ - this.zdir = value; - } - - /** - * Set zdir point - * @param x X coordinate value - * @param y Y coordinate value - * @param z Z coordinate value - */ - public void setZDir(float x, float y, float z){ - if (x == 0 && y == 0 && z == 0) - this.zdir = null; - else - this.zdir = new PointZ(x, y, z); - } - - /** - * Set zdir point - * @param value ZDir point - */ - public void setZDir(String value){ - float x1 = 0, y1 = 0, z1 = 0; - switch(value.toLowerCase()){ - case "x": - x1 = 1; - break; - case "y": - y1 = 1; - break; - case "z": - z1 = 1; - break; - } - this.setZDir(x1, y1, z1); - } - - /** - * Set point - * - * @param x X - * @param y Y - * @param z Z - */ - public void setPoint(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - Extent3D aExtent = new Extent3D(); - aExtent.minX = x; - aExtent.maxX = x; - aExtent.minY = y; - aExtent.maxY = y; - aExtent.minZ = z; - aExtent.maxZ = z; - this.setExtent(aExtent); - } - - /** - * Update angle - * @param projector Projector - */ - public void updateAngle(Projector projector){ - if (this.zdir == null) - return; - - Point p0 = projector.project(0, 0, 0); - Point p1 = projector.project((float)this.zdir.X, (float)this.zdir.Y, (float)this.zdir.Z); - double[] value = DataMath.getDSFromUV(p1.x - p0.x, p1.y - p0.y); - this.angle = (float)value[0]; - } -} +/* This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.chart; + +import java.awt.Point; +import org.meteoinfo.chart.plot3d.Projector; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.data.DataMath; +import org.meteoinfo.shape.PointZ; + +/** + * + * @author Yaqiang Wang + * yaqiang.wang@gmail.com + */ +public class ChartText3D extends ChartText { + private double z; + private PointZ zdir = null; + + /** + * Get z coordinate value + * @return Z coordinate value + */ + public double getZ(){ + return this.z; + } + + /** + * Set z coordinate value + * @param value Z coordinate value + */ + public void setZ(double value){ + this.z = value; + } + + /** + * Get zdir point + * @return ZDir point + */ + public PointZ getZDir(){ + return zdir; + } + + /** + * Set zdir point + * @param value ZDir point + */ + public void setZDir(PointZ value){ + this.zdir = value; + } + + /** + * Set zdir point + * @param x X coordinate value + * @param y Y coordinate value + * @param z Z coordinate value + */ + public void setZDir(float x, float y, float z){ + if (x == 0 && y == 0 && z == 0) + this.zdir = null; + else + this.zdir = new PointZ(x, y, z); + } + + /** + * Set zdir point + * @param value ZDir point + */ + public void setZDir(String value){ + float x1 = 0, y1 = 0, z1 = 0; + switch(value.toLowerCase()){ + case "x": + x1 = 1; + break; + case "y": + y1 = 1; + break; + case "z": + z1 = 1; + break; + } + this.setZDir(x1, y1, z1); + } + + /** + * Set point + * + * @param x X + * @param y Y + * @param z Z + */ + public void setPoint(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + Extent3D aExtent = new Extent3D(); + aExtent.minX = x; + aExtent.maxX = x; + aExtent.minY = y; + aExtent.maxY = y; + aExtent.minZ = z; + aExtent.maxZ = z; + this.setExtent(aExtent); + } + + /** + * Update angle + * @param projector Projector + */ + public void updateAngle(Projector projector){ + if (this.zdir == null) + return; + + Point p0 = projector.project(0, 0, 0); + Point p1 = projector.project((float)this.zdir.X, (float)this.zdir.Y, (float)this.zdir.Z); + double[] value = DataMath.getDSFromUV(p1.x - p0.x, p1.y - p0.y); + this.angle = (float)value[0]; + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartWindArrow.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartWindArrow.java index 77d27fcf..bb279fcc 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartWindArrow.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/ChartWindArrow.java @@ -1,390 +1,391 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.Rectangle2D; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.PointF; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.legend.ArrowBreak; -import org.meteoinfo.shape.GraphicCollection; -import org.meteoinfo.shape.WindArrow; - -/** - * - * @author Yaqiang Wang - */ -public class ChartWindArrow { - - // - private final WindArrow windArrow; - private ArrowBreak arrowBreak; - private Font font; - //private Color color; - private Color labelColor; - private float x; - private float y; - private String label; - private int labelSep; - private Object layer; - private Color background; - private boolean drawBackground; - private boolean drawNeatline; - private Color neatLineColor; - private float neatLineSize; - - // - // - /** - * Constructor - */ - public ChartWindArrow() { - this.windArrow = new WindArrow(); - this.windArrow.angle = 270; - this.windArrow.length = 20; - this.arrowBreak = new ArrowBreak(); - this.font = new Font("Arial", Font.PLAIN, 12); - //this.color = Color.black; - this.labelColor = Color.black; - this.labelSep = 5; - this.background = Color.white; - this.drawBackground = false; - this.drawNeatline = false; - this.neatLineColor = Color.black; - this.neatLineSize = 1.0f; - } - - // - // - /** - * Get wind arrow - * - * @return Wind arrow - */ - public WindArrow getWindArrow() { - return this.windArrow; - } - - /** - * Get arrow break - * @return Arrow break - */ - public ArrowBreak getArrowBreak() { - return this.arrowBreak; - } - - /** - * Set arrow break - * @param value Arrow break - */ - public void setArrowBreak(ArrowBreak value) { - this.arrowBreak = value; - } - - /** - * Get length - * - * @return Length - */ - public float getLength() { - return this.windArrow.length; - } - - /** - * Set length - * - * @param value Length - */ - public void setLength(float value) { - this.windArrow.length = value; - this.label = String.valueOf(value); - this.label = DataConvert.removeTailingZeros(this.label); - } - - /** - * Get angle - * - * @return Angle - */ - public double getAngle() { - return this.windArrow.angle; - } - - /** - * Set angle - * - * @param value Angle - */ - public void setAngle(double value) { - this.windArrow.angle = value; - } - - /** - * Get layer - * - * @return Layer - */ - public Object getLayer() { - return this.layer; - } - - /** - * Set layer - * - * @param value Layer - */ - public void setLayer(Object value) { - this.layer = value; - } - - /** - * Get font - * - * @return Font - */ - public Font getFont() { - return font; - } - - /** - * Set font - * - * @param value Font - */ - public void setFont(Font value) { - font = value; - } - - /** - * Get label color - * - * @return Label color - */ - public Color getLabelColor() { - return this.labelColor; - } - - /** - * Set label color - * - * @param value Label color - */ - public void setLabelColor(Color value) { - this.labelColor = value; - } - - /** - * Get the distance between arrow and label - * @return Distance between arrow and label - */ - public int getLabelSep(){ - return this.labelSep; - } - - /** - * Set the distance between arrow and label - * @param value Distance between arrow and label - */ - public void setLabelSep(int value) { - this.labelSep = value; - } - - /** - * Get x - * - * @return X - */ - public float getX() { - return this.x; - } - - /** - * Set x - * - * @param value X - */ - public void setX(float value) { - this.x = value; - } - - /** - * Get y - * - * @return Y - */ - public float getY() { - return this.y; - } - - /** - * Set y - * - * @param value Y - */ - public void setY(float value) { - this.y = value; - } - - /** - * Get label - * - * @return Label - */ - public String getLabel() { - return this.label; - } - - /** - * Set label - * - * @param value Label - */ - public void setLabel(String value) { - this.label = value; - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackground() { - return this.background; - } - - /** - * Set background color - * - * @param value Background color - */ - public void setBackground(Color value) { - this.background = value; - } - - /** - * Get if is fill background - * - * @return Boolean - */ - public boolean isFill() { - return this.drawBackground; - } - - /** - * Set fill background or not - * - * @param value Boolean - */ - public void setFill(boolean value) { - this.drawBackground = value; - } - - /** - * Get draw neatline or not - * - * @return Boolean - */ - public boolean isDrawNeatline() { - return this.drawNeatline; - } - - /** - * Set draw neatline or not - * - * @param value Boolean - */ - public void setDrawNeatline(boolean value) { - this.drawNeatline = value; - } - - /** - * Get neatline color - * - * @return Neatline color - */ - public Color getNeatlineColor() { - return this.neatLineColor; - } - - /** - * Set neatline color - * - * @param value Neatline color - */ - public void setNeatlineColor(Color value) { - this.neatLineColor = value; - } - - /** - * Get neatline size - * - * @return Neatline size - */ - public float getNeatlineSize() { - return this.neatLineSize; - } - - /** - * Set neatline size - * - * @param value Neatline size - */ - public void setNeatlineSize(float value) { - this.neatLineSize = value; - } - - // - // - /** - * Draw text - * - * @param g Graphics2D - * @param x X - * @param y Y - */ - public void draw(Graphics2D g, float x, float y) { - Object rendering = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - float zoom = 1.0f; - if (this.layer != null) { - if (this.layer instanceof VectorLayer) { - zoom = ((VectorLayer) this.layer).getDrawingZoom(); - } else if (this.layer instanceof GraphicCollection) { - zoom = ((GraphicCollection) this.layer).getArrowZoom(); - } - } - g.setFont(this.font); - //String drawStr = this.label wa.getLabel(); - Dimension dim = Draw.getStringDimension(this.label, g); - if (this.drawBackground || this.drawNeatline) { - Rectangle2D rect = Draw.getArrawBorder(new PointF(x, y), this.windArrow, g, zoom); - double gap = 5; - double width = Math.max(rect.getWidth(), dim.getWidth()); - rect.setRect(rect.getX() - gap, rect.getY() - gap - 2, width + gap * 2, - rect.getHeight() + dim.height + this.labelSep + gap + 2); - if (this.drawBackground) { - g.setColor(this.background); - g.fill(rect); - } - if (this.drawNeatline) { - g.setColor(this.neatLineColor); - g.draw(rect); - } - } - //Draw.drawArraw(this.color, new PointF(x, y), this.windArrow, g, zoom); - Draw.drawArraw(new PointF(x, y), windArrow, arrowBreak, g, zoom); - g.setColor(this.labelColor); - Draw.drawString(g, this.label, x, y + dim.height + this.labelSep); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, rendering); - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.legend.ArrowBreak; +import org.meteoinfo.shape.GraphicCollection; +import org.meteoinfo.shape.WindArrow; + +/** + * + * @author Yaqiang Wang + */ +public class ChartWindArrow { + + // + private final WindArrow windArrow; + private ArrowBreak arrowBreak; + private Font font; + //private Color color; + private Color labelColor; + private float x; + private float y; + private String label; + private int labelSep; + private Object layer; + private Color background; + private boolean drawBackground; + private boolean drawNeatline; + private Color neatLineColor; + private float neatLineSize; + + // + // + /** + * Constructor + */ + public ChartWindArrow() { + this.windArrow = new WindArrow(); + this.windArrow.angle = 270; + this.windArrow.length = 20; + this.arrowBreak = new ArrowBreak(); + this.font = new Font("Arial", Font.PLAIN, 12); + //this.color = Color.black; + this.labelColor = Color.black; + this.labelSep = 5; + this.background = Color.white; + this.drawBackground = false; + this.drawNeatline = false; + this.neatLineColor = Color.black; + this.neatLineSize = 1.0f; + } + + // + // + /** + * Get wind arrow + * + * @return Wind arrow + */ + public WindArrow getWindArrow() { + return this.windArrow; + } + + /** + * Get arrow break + * @return Arrow break + */ + public ArrowBreak getArrowBreak() { + return this.arrowBreak; + } + + /** + * Set arrow break + * @param value Arrow break + */ + public void setArrowBreak(ArrowBreak value) { + this.arrowBreak = value; + } + + /** + * Get length + * + * @return Length + */ + public float getLength() { + return this.windArrow.length; + } + + /** + * Set length + * + * @param value Length + */ + public void setLength(float value) { + this.windArrow.length = value; + this.label = String.valueOf(value); + this.label = DataConvert.removeTailingZeros(this.label); + } + + /** + * Get angle + * + * @return Angle + */ + public double getAngle() { + return this.windArrow.angle; + } + + /** + * Set angle + * + * @param value Angle + */ + public void setAngle(double value) { + this.windArrow.angle = value; + } + + /** + * Get layer + * + * @return Layer + */ + public Object getLayer() { + return this.layer; + } + + /** + * Set layer + * + * @param value Layer + */ + public void setLayer(Object value) { + this.layer = value; + } + + /** + * Get font + * + * @return Font + */ + public Font getFont() { + return font; + } + + /** + * Set font + * + * @param value Font + */ + public void setFont(Font value) { + font = value; + } + + /** + * Get label color + * + * @return Label color + */ + public Color getLabelColor() { + return this.labelColor; + } + + /** + * Set label color + * + * @param value Label color + */ + public void setLabelColor(Color value) { + this.labelColor = value; + } + + /** + * Get the distance between arrow and label + * @return Distance between arrow and label + */ + public int getLabelSep(){ + return this.labelSep; + } + + /** + * Set the distance between arrow and label + * @param value Distance between arrow and label + */ + public void setLabelSep(int value) { + this.labelSep = value; + } + + /** + * Get x + * + * @return X + */ + public float getX() { + return this.x; + } + + /** + * Set x + * + * @param value X + */ + public void setX(float value) { + this.x = value; + } + + /** + * Get y + * + * @return Y + */ + public float getY() { + return this.y; + } + + /** + * Set y + * + * @param value Y + */ + public void setY(float value) { + this.y = value; + } + + /** + * Get label + * + * @return Label + */ + public String getLabel() { + return this.label; + } + + /** + * Set label + * + * @param value Label + */ + public void setLabel(String value) { + this.label = value; + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackground() { + return this.background; + } + + /** + * Set background color + * + * @param value Background color + */ + public void setBackground(Color value) { + this.background = value; + } + + /** + * Get if is fill background + * + * @return Boolean + */ + public boolean isFill() { + return this.drawBackground; + } + + /** + * Set fill background or not + * + * @param value Boolean + */ + public void setFill(boolean value) { + this.drawBackground = value; + } + + /** + * Get draw neatline or not + * + * @return Boolean + */ + public boolean isDrawNeatline() { + return this.drawNeatline; + } + + /** + * Set draw neatline or not + * + * @param value Boolean + */ + public void setDrawNeatline(boolean value) { + this.drawNeatline = value; + } + + /** + * Get neatline color + * + * @return Neatline color + */ + public Color getNeatlineColor() { + return this.neatLineColor; + } + + /** + * Set neatline color + * + * @param value Neatline color + */ + public void setNeatlineColor(Color value) { + this.neatLineColor = value; + } + + /** + * Get neatline size + * + * @return Neatline size + */ + public float getNeatlineSize() { + return this.neatLineSize; + } + + /** + * Set neatline size + * + * @param value Neatline size + */ + public void setNeatlineSize(float value) { + this.neatLineSize = value; + } + + // + // + /** + * Draw text + * + * @param g Graphics2D + * @param x X + * @param y Y + */ + public void draw(Graphics2D g, float x, float y) { + Object rendering = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + float zoom = 1.0f; + if (this.layer != null) { + if (this.layer instanceof VectorLayer) { + zoom = ((VectorLayer) this.layer).getDrawingZoom(); + } else if (this.layer instanceof GraphicCollection) { + zoom = ((GraphicCollection) this.layer).getArrowZoom(); + } + } + g.setFont(this.font); + //String drawStr = this.label wa.getLabel(); + Dimension dim = Draw.getStringDimension(this.label, g); + if (this.drawBackground || this.drawNeatline) { + Rectangle2D rect = Draw.getArrawBorder(new PointF(x, y), this.windArrow, g, zoom); + double gap = 5; + double width = Math.max(rect.getWidth(), dim.getWidth()); + rect.setRect(rect.getX() - gap, rect.getY() - gap - 2, width + gap * 2, + rect.getHeight() + dim.height + this.labelSep + gap + 2); + if (this.drawBackground) { + g.setColor(this.background); + g.fill(rect); + } + if (this.drawNeatline) { + g.setColor(this.neatLineColor); + g.draw(rect); + } + } + //Draw.drawArraw(this.color, new PointF(x, y), this.windArrow, g, zoom); + Draw.drawArraw(new PointF(x, y), windArrow, arrowBreak, g, zoom); + g.setColor(this.labelColor); + Draw.drawString(g, this.label, x, y + dim.height + this.labelSep); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, rendering); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java index 30cf6687..88611ba4 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java @@ -23,10 +23,10 @@ import org.meteoinfo.chart.Location; import org.meteoinfo.chart.plot.AbstractPlot2D; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.drawing.Draw; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.legend.LineStyles; import org.meteoinfo.ndarray.util.BigDecimalUtil; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/LogAxis.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/LogAxis.java index f2bf2201..ba2f4874 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/LogAxis.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/LogAxis.java @@ -1,83 +1,83 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart.axis; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.chart.ChartText; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.MIMath; - -/** - * - * @author Yaqiang Wang - */ -public class LogAxis extends Axis { - // - // - // - /** - * Constructor - * @param axis Axis - */ - public LogAxis(Axis axis){ - super(axis); - } - // - // - // - // - /** - * Update tick values - */ - @Override - public void updateTickValues() { - double[] r = MIMath.getIntervalValues_Log(this.getMinValue(), this.getMaxValue()); - this.setTickValues((double[]) r); - this.setTickDeltaValue(1); - } - - @Override - public void updateTickLabels(){ - List tls = new ArrayList<>(); - String lab; - if (this.isAutoTick()) { - if (this.getTickValues() == null) { - return; - } - for (double value : this.getTickValues()) { - lab = String.valueOf(value); - lab = DataConvert.removeTailingZeros(lab); - tls.add(new ChartText(lab)); - } - - List values = new ArrayList<>(); - for (ChartText tl : tls){ - values.add(Double.parseDouble(tl.getText())); - } - tls.clear(); - int e; - for (Double v : values){ - e = (int) Math.floor(Math.log10(v)); - tls.add(new ChartText("$10^{" + String.valueOf(e) + "}$")); - } - } else { - for (int i = 0; i < this.getTickLocations().size(); i++) { - if (i >= this.getTickLabels().size()) { - break; - } - double v = this.getTickLocations().get(i); - if (v >= this.getMinValue() && v <= this.getMaxValue()) { - tls.add(this.getTickLabels().get(i)); - } - } - } - - this.setTickLabels(tls); - } - - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart.axis; + +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.chart.ChartText; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.global.DataConvert; + +/** + * + * @author Yaqiang Wang + */ +public class LogAxis extends Axis { + // + // + // + /** + * Constructor + * @param axis Axis + */ + public LogAxis(Axis axis){ + super(axis); + } + // + // + // + // + /** + * Update tick values + */ + @Override + public void updateTickValues() { + double[] r = MIMath.getIntervalValues_Log(this.getMinValue(), this.getMaxValue()); + this.setTickValues((double[]) r); + this.setTickDeltaValue(1); + } + + @Override + public void updateTickLabels(){ + List tls = new ArrayList<>(); + String lab; + if (this.isAutoTick()) { + if (this.getTickValues() == null) { + return; + } + for (double value : this.getTickValues()) { + lab = String.valueOf(value); + lab = DataConvert.removeTailingZeros(lab); + tls.add(new ChartText(lab)); + } + + List values = new ArrayList<>(); + for (ChartText tl : tls){ + values.add(Double.parseDouble(tl.getText())); + } + tls.clear(); + int e; + for (Double v : values){ + e = (int) Math.floor(Math.log10(v)); + tls.add(new ChartText("$10^{" + String.valueOf(e) + "}$")); + } + } else { + for (int i = 0; i < this.getTickLocations().size(); i++) { + if (i >= this.getTickLabels().size()) { + break; + } + double v = this.getTickLocations().get(i); + if (v >= this.getMinValue() && v <= this.getMaxValue()) { + tls.add(this.getTickLabels().get(i)); + } + } + } + + this.setTickLabels(tls); + } + + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/ProjLonLatAxis.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/ProjLonLatAxis.java index 9a6d2182..ff14ef5e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/ProjLonLatAxis.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/ProjLonLatAxis.java @@ -1,174 +1,174 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart.axis; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.chart.ChartText; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.info.ProjectionInfo; -import org.meteoinfo.projection.Reproject; - -/** - * - * @author Yaqiang Wang - */ -public class ProjLonLatAxis extends LonLatAxis{ - // - private ProjectionInfo proj; - private double x_y; - // - // - /** - * Constructor - * @param label Label - * @param isX Is x/longitude axis or not - * @param proj Projection - */ - public ProjLonLatAxis(String label, boolean isX, ProjectionInfo proj){ - super(label, isX, isX); - this.proj = proj; - } - - /** - * Constructor - * @param label Label - * @param isX Is x/longitude axis or not - * @param proj Projection - * @param xy X or Y value of the axis - using for projection - */ - public ProjLonLatAxis(String label, boolean isX, ProjectionInfo proj, double xy){ - super(label, isX); - this.proj = proj; - this.x_y = xy; - } - // - // - /** - * Get projection - * @return Projection - */ - public ProjectionInfo getProject(){ - return this.proj; - } - - /** - * Set projection - * @param value Projection - */ - public void setProject(ProjectionInfo value){ - this.proj = value; - } - - /** - * Get x_y value - * @return x_y value - */ - public double getX_Y(){ - return this.x_y; - } - - /** - * Set x_y value - * @param value x_y value - */ - public void setX_Y(double value){ - this.x_y = value; - //this.updateTickValues(); - } - // - // - /** - * Update tick values - */ - @Override - public void updateTickValues() { - if (this.proj == null) - return; - - double min = this.getMinValue(); - double max = this.getMaxValue(); - //Calculate min and max lon or lat - ProjectionInfo toproj = KnownCoordinateSystems.geographic.world.WGS1984; - double minv, maxv; - double[][] points = new double[2][]; - if (this.isXAxis()){ - points[0] = new double[]{min, this.x_y}; - points[1] = new double[]{max, this.x_y}; - Reproject.reprojectPoints(points, this.proj, toproj); - minv = points[0][0]; - maxv = points[1][0]; - } else { - points[0] = new double[]{this.x_y, min}; - points[1] = new double[]{this.x_y, max}; - Reproject.reprojectPoints(points, this.proj, toproj); - minv = points[0][1]; - maxv = points[1][1]; - } - //Get tick values - List r = MIMath.getIntervalValues1(minv, maxv); - double[] values = (double[])r.get(0); - double[] tickValues = new double[values.length]; - - this.setTickValues((double[]) r.get(0)); - this.setTickDeltaValue((Double) r.get(1)); - } - - /** - * Get tick labels - * - */ - @Override - public void updateTickLabels() { - List tls = new ArrayList<>(); - String lab; - for (double v : this.getTickValues()) { - double value = v; - if (value > 180) { - value = value - 360; - } - lab = String.valueOf(value); - lab = DataConvert.removeTailingZeros(lab); - if (this.isXAxis()) { - if (value == -180) { - lab = "180"; - } else if (!(value == 0 || value == 180)) { - if (lab.substring(0, 1).equals("-")) { - lab = lab.substring(1) + "W"; - } else { - lab = lab + "E"; - } - } - } else { - if (!(value == 0)) { - if (lab.substring(0, 1).equals("-")) { - lab = lab.substring(1) + "S"; - } else { - lab = lab + "N"; - } - } - } - if (this.isDrawDegreeSymbol()) { - if (lab.endsWith("E") || lab.endsWith("W") || lab.endsWith("N") || lab.endsWith("S")) { - lab = lab.substring(0, lab.length() - 1) + String.valueOf((char) 186) + lab.substring(lab.length() - 1); - } else { - lab = lab + String.valueOf((char) 186); - } - } - tls.add(new ChartText(lab)); - } - - this.setTickLabels(tls); - } - - @Override - public Object clone() throws CloneNotSupportedException { - return (ProjLonLatAxis)super.clone(); - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart.axis; + +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.chart.ChartText; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.info.ProjectionInfo; +import org.meteoinfo.projection.Reproject; + +/** + * + * @author Yaqiang Wang + */ +public class ProjLonLatAxis extends LonLatAxis{ + // + private ProjectionInfo proj; + private double x_y; + // + // + /** + * Constructor + * @param label Label + * @param isX Is x/longitude axis or not + * @param proj Projection + */ + public ProjLonLatAxis(String label, boolean isX, ProjectionInfo proj){ + super(label, isX, isX); + this.proj = proj; + } + + /** + * Constructor + * @param label Label + * @param isX Is x/longitude axis or not + * @param proj Projection + * @param xy X or Y value of the axis - using for projection + */ + public ProjLonLatAxis(String label, boolean isX, ProjectionInfo proj, double xy){ + super(label, isX); + this.proj = proj; + this.x_y = xy; + } + // + // + /** + * Get projection + * @return Projection + */ + public ProjectionInfo getProject(){ + return this.proj; + } + + /** + * Set projection + * @param value Projection + */ + public void setProject(ProjectionInfo value){ + this.proj = value; + } + + /** + * Get x_y value + * @return x_y value + */ + public double getX_Y(){ + return this.x_y; + } + + /** + * Set x_y value + * @param value x_y value + */ + public void setX_Y(double value){ + this.x_y = value; + //this.updateTickValues(); + } + // + // + /** + * Update tick values + */ + @Override + public void updateTickValues() { + if (this.proj == null) + return; + + double min = this.getMinValue(); + double max = this.getMaxValue(); + //Calculate min and max lon or lat + ProjectionInfo toproj = KnownCoordinateSystems.geographic.world.WGS1984; + double minv, maxv; + double[][] points = new double[2][]; + if (this.isXAxis()){ + points[0] = new double[]{min, this.x_y}; + points[1] = new double[]{max, this.x_y}; + Reproject.reprojectPoints(points, this.proj, toproj); + minv = points[0][0]; + maxv = points[1][0]; + } else { + points[0] = new double[]{this.x_y, min}; + points[1] = new double[]{this.x_y, max}; + Reproject.reprojectPoints(points, this.proj, toproj); + minv = points[0][1]; + maxv = points[1][1]; + } + //Get tick values + List r = MIMath.getIntervalValues1(minv, maxv); + double[] values = (double[])r.get(0); + double[] tickValues = new double[values.length]; + + this.setTickValues((double[]) r.get(0)); + this.setTickDeltaValue((Double) r.get(1)); + } + + /** + * Get tick labels + * + */ + @Override + public void updateTickLabels() { + List tls = new ArrayList<>(); + String lab; + for (double v : this.getTickValues()) { + double value = v; + if (value > 180) { + value = value - 360; + } + lab = String.valueOf(value); + lab = DataConvert.removeTailingZeros(lab); + if (this.isXAxis()) { + if (value == -180) { + lab = "180"; + } else if (!(value == 0 || value == 180)) { + if (lab.substring(0, 1).equals("-")) { + lab = lab.substring(1) + "W"; + } else { + lab = lab + "E"; + } + } + } else { + if (!(value == 0)) { + if (lab.substring(0, 1).equals("-")) { + lab = lab.substring(1) + "S"; + } else { + lab = lab + "N"; + } + } + } + if (this.isDrawDegreeSymbol()) { + if (lab.endsWith("E") || lab.endsWith("W") || lab.endsWith("N") || lab.endsWith("S")) { + lab = lab.substring(0, lab.length() - 1) + String.valueOf((char) 186) + lab.substring(lab.length() - 1); + } else { + lab = lab + String.valueOf((char) 186); + } + } + tls.add(new ChartText(lab)); + } + + this.setTickLabels(tls); + } + + @Override + public Object clone() throws CloneNotSupportedException { + return (ProjLonLatAxis)super.clone(); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/TimeAxis.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/TimeAxis.java index 5841f86b..8694fa7c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/TimeAxis.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/TimeAxis.java @@ -8,10 +8,9 @@ package org.meteoinfo.chart.axis; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; import org.meteoinfo.chart.ChartText; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.common.util.JDateUtil; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/GLChartPanel.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/GLChartPanel.java index 2427ed24..46276ab1 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/GLChartPanel.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/GLChartPanel.java @@ -18,7 +18,6 @@ import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.*; -import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import javax.imageio.stream.ImageOutputStream; @@ -26,7 +25,7 @@ import javax.swing.*; import org.meteoinfo.chart.IChartPanel; import org.meteoinfo.chart.MouseMode; -import org.meteoinfo.global.Extent3D; +import org.meteoinfo.common.Extent3D; import org.meteoinfo.image.ImageUtil; import org.w3c.dom.Element; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/IsosurfaceGraphics.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/IsosurfaceGraphics.java index a164f92e..6fbccfbb 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/IsosurfaceGraphics.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/IsosurfaceGraphics.java @@ -1,58 +1,59 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart.jogl; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.chart.plot3d.GraphicCollection3D; -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.shape.PointZ; - -/** - * - * @author yaqiang - */ -public class IsosurfaceGraphics extends GraphicCollection3D { - private List triangles = new ArrayList<>(); - - /** - * Constructor - */ - public IsosurfaceGraphics() { - super(); - this.allTriangle = true; - } - - /** - * Get triangles - * @return Triangles - */ - public List getTriangles() { - return this.triangles; - } - - /** - * Set triangles - * @param value Triangles - */ - public void setTriangles(List value) { - this.triangles = value; - } - - /** - * Add a triangle - * @param triangle Triangle - */ - public void addTriangle(PointZ[] triangle) { - this.triangles.add(triangle); - Extent3D extent = MIMath.getExtent(triangle); - if (this.triangles.size() == 1) - this.setExtent(extent); - else - this.setExtent(MIMath.getLagerExtent(extent, this.getExtent())); - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart.jogl; + +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.chart.plot3d.GraphicCollection3D; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.geoprocess.GeometryUtil; +import org.meteoinfo.shape.PointZ; + +/** + * + * @author yaqiang + */ +public class IsosurfaceGraphics extends GraphicCollection3D { + private List triangles = new ArrayList<>(); + + /** + * Constructor + */ + public IsosurfaceGraphics() { + super(); + this.allTriangle = true; + } + + /** + * Get triangles + * @return Triangles + */ + public List getTriangles() { + return this.triangles; + } + + /** + * Set triangles + * @param value Triangles + */ + public void setTriangles(List value) { + this.triangles = value; + } + + /** + * Add a triangle + * @param triangle Triangle + */ + public void addTriangle(PointZ[] triangle) { + this.triangles.add(triangle); + Extent3D extent = GeometryUtil.getExtent(triangle); + if (this.triangles.size() == 1) + this.setExtent(extent); + else + this.setExtent(MIMath.getLagerExtent(extent, this.getExtent())); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java index 30af1c35..3dbe88ed 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java @@ -15,8 +15,8 @@ import java.util.Random; import org.meteoinfo.chart.jogl.mc.MarchingCubes; import org.meteoinfo.chart.jogl.mc.CallbackMC; import org.meteoinfo.chart.plot3d.GraphicCollection3D; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.Extent3D; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.Extent3D; import org.meteoinfo.layer.ImageLayer; import org.meteoinfo.legend.ColorBreak; import org.meteoinfo.legend.LegendScheme; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java index d0b24087..6c75b446 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java @@ -6,15 +6,12 @@ package org.meteoinfo.chart.jogl; import com.jogamp.opengl.*; -import com.jogamp.opengl.fixedfunc.GLLightingFunc; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.glu.GLUquadric; import com.jogamp.opengl.glu.GLUtessellator; -import com.jogamp.opengl.glu.GLUtessellatorCallback; import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.util.awt.TextRenderer; import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureCoords; import com.jogamp.opengl.util.texture.awt.AWTTextureIO; import com.jogamp.opengl.util.gl2.GLUT; import com.jogamp.opengl.math.VectorUtil; @@ -33,7 +30,6 @@ import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JFrame; -import jogamp.opengl.glu.tessellator.GLUtessellatorImpl; import org.meteoinfo.chart.ChartColorBar; import org.meteoinfo.chart.ChartLegend; import org.meteoinfo.chart.ChartText; @@ -41,23 +37,18 @@ import org.meteoinfo.chart.ChartText3D; import org.meteoinfo.chart.Margin; import org.meteoinfo.chart.axis.Axis; import org.meteoinfo.chart.jogl.tessellator.Primitive; -import org.meteoinfo.chart.jogl.tessellator.PrimitiveTessellator; import org.meteoinfo.chart.jogl.tessellator.TessPolygon; -import org.meteoinfo.chart.jogl.tessellator.TriangleTessellator; import org.meteoinfo.chart.plot.*; import org.meteoinfo.chart.plot3d.GraphicCollection3D; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.Extent3D; import org.meteoinfo.data.Dataset; import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.global.util.FontUtil; import org.meteoinfo.legend.*; import org.meteoinfo.math.meteo.MeteoMath; import org.meteoinfo.shape.*; -import static org.meteoinfo.shape.ShapeTypes.PointZ; - /** * * @author wyq diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/SurfaceGraphics.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/SurfaceGraphics.java index d2951e85..dc884495 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/SurfaceGraphics.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/SurfaceGraphics.java @@ -6,7 +6,7 @@ package org.meteoinfo.chart.jogl; import org.meteoinfo.chart.plot3d.GraphicCollection3D; -import org.meteoinfo.global.Extent3D; +import org.meteoinfo.common.Extent3D; import org.meteoinfo.legend.ColorBreak; import org.meteoinfo.legend.LegendScheme; import org.meteoinfo.legend.PolygonBreak; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Transform.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Transform.java index 8936a203..9bedae10 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Transform.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/jogl/Transform.java @@ -1,6 +1,6 @@ package org.meteoinfo.chart.jogl; -import org.meteoinfo.global.Extent3D; +import org.meteoinfo.common.Extent3D; import org.meteoinfo.shape.PointZ; public class Transform { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/AbstractPlot2D.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/AbstractPlot2D.java index 370abcf2..7fcd0727 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/AbstractPlot2D.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/AbstractPlot2D.java @@ -27,11 +27,9 @@ import org.meteoinfo.chart.Location; import org.meteoinfo.chart.Margin; import org.meteoinfo.chart.axis.Axis; import org.meteoinfo.chart.axis.LogAxis; -import static org.meteoinfo.chart.plot.Plot.MINIMUM_HEIGHT_TO_DRAW; -import static org.meteoinfo.chart.plot.Plot.MINIMUM_WIDTH_TO_DRAW; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointF; import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointF; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java index 631a6090..6abfbbd6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java @@ -18,20 +18,19 @@ import java.util.List; import org.apache.commons.lang3.ArrayUtils; import org.meteoinfo.chart.ChartText; import org.meteoinfo.chart.plot3d.GraphicCollection3D; -import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.math.ArrayUtil; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.XYListDataset; import org.meteoinfo.data.analysis.Statistics; import org.meteoinfo.drawing.ContourDraw; import org.meteoinfo.drawing.Draw; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.legend.PointStyle; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.layer.ImageLayer; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.legend.ArrowLineBreak; @@ -48,6 +47,8 @@ import org.meteoinfo.legend.PointBreak; import org.meteoinfo.legend.PolygonBreak; import org.meteoinfo.legend.PolylineBreak; import org.meteoinfo.legend.StreamlineBreak; +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.math.meteo.MeteoMath; import org.meteoinfo.ndarray.*; import org.meteoinfo.ndarray.util.BigDecimalUtil; @@ -3100,7 +3101,7 @@ public class GraphicFactory { } aPolyline.setPoints(pList); aPolyline.setValue(v); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); switch (ls.getLegendType()) { case UniqueValue: @@ -3216,7 +3217,7 @@ public class GraphicFactory { } aPolyline.setPoints(pList); aPolyline.setValue(v); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); cbb = ls.findLegendBreak(v); graphics.add(new Graphic(aPolyline, cbb)); } @@ -3325,7 +3326,7 @@ public class GraphicFactory { } aPolyline.setPoints(pList); aPolyline.setValue(v); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); cbb = ls.findLegendBreak(v); graphics.add(new Graphic(aPolyline, cbb)); } @@ -3391,7 +3392,7 @@ public class GraphicFactory { } PolygonShape aPolygonShape = new PolygonShape(); aPolygonShape.setPoints(pList); - aPolygonShape.setExtent(MIMath.getPointsExtent(pList)); + aPolygonShape.setExtent(GeometryUtil.getPointsExtent(pList)); aPolygonShape.lowValue = v; if (poly.HasHoles()) { for (PolyLine holeLine : poly.HoleLines) { @@ -3555,7 +3556,7 @@ public class GraphicFactory { } PolygonZShape aPolygonShape = new PolygonZShape(); aPolygonShape.setPoints(pList); - aPolygonShape.setExtent(MIMath.getPointsExtent(pList)); + aPolygonShape.setExtent(GeometryUtil.getPointsExtent(pList)); aPolygonShape.lowValue = v; if (poly.HasHoles()) { switch (zdir) { @@ -3734,7 +3735,7 @@ public class GraphicFactory { } PolygonZShape aPolygonShape = new PolygonZShape(); aPolygonShape.setPoints(pList); - aPolygonShape.setExtent(MIMath.getPointsExtent(pList)); + aPolygonShape.setExtent(GeometryUtil.getPointsExtent(pList)); aPolygonShape.lowValue = v; if (poly.HasHoles()) { switch (zdir) { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/MapPlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/MapPlot.java index c24c86fe..b9900e09 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/MapPlot.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/MapPlot.java @@ -28,15 +28,14 @@ import org.meteoinfo.chart.ChartScaleBar; import org.meteoinfo.chart.ChartText; import org.meteoinfo.chart.Location; import org.meteoinfo.chart.axis.LonLatAxis; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.data.Dataset; import org.meteoinfo.data.mapdata.webmap.IWebMapPanel; import org.meteoinfo.data.mapdata.webmap.TileLoadListener; import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.layer.LayerCollection; import org.meteoinfo.layer.MapLayer; import org.meteoinfo.legend.LabelBreak; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PiePlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PiePlot.java index 7ec6b371..6c4865a9 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PiePlot.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PiePlot.java @@ -1,160 +1,161 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart.plot; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.PointF; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.shape.ArcShape; -import org.meteoinfo.shape.Graphic; -import org.meteoinfo.shape.GraphicCollection; -import org.meteoinfo.shape.Shape; - -/** - * - * @author Yaqiang Wang - */ -public class PiePlot extends Plot2D { - - // - // - // - /** - * Constructor - */ - public PiePlot(){ - super(); - this.setAutoAspect(false); - } - // - // - // - // - @Override - void drawGraph(Graphics2D g, Rectangle2D area) { - AffineTransform oldMatrix = g.getTransform(); - //Rectangle oldRegion = g.getClipBounds(); - //g.setClip(area); - g.translate(area.getX(), area.getY()); - - //Draw background - if (this.background != null) { - g.setColor(this.getBackground()); - g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); - } - - for (int m = 0; m < this.getGraphics().getNumGraphics(); m++) { - Graphic graphic = this.getGraphics().get(m); - ColorBreak cb = graphic.getLegend(); - float dist = 5; - float ex = this.getExplode(); - Font labelFont = ((GraphicCollection)graphic).getLabelSet().getLabelFont(); - Color labelColor = ((GraphicCollection)graphic).getLabelSet().getLabelColor(); - for (int i = 0; i < graphic.getNumGraphics(); i++) { - Graphic gg = graphic.getGraphicN(i); - if (!graphic.isSingleLegend()) { - cb = gg.getLegend(); - } - Shape shape = gg.getShape(); - this.drawArc(g, (ArcShape) shape, (PolygonBreak) cb, area, dist, ex, labelFont, - labelColor); - } - } - - g.setTransform(oldMatrix); - //g.setClip(oldRegion); - } - - private float getExplode() { - Graphic graphic = this.getGraphics().get(0); - float ex = 0; - for (int i = 0; i < graphic.getNumGraphics(); i++) { - Graphic gg = graphic.getGraphicN(i); - ArcShape shape = (ArcShape) gg.getShape(); - if (shape.getExplode() > 0) { - ex = 10; - break; - } - } - return ex; - } - - private void drawArc(Graphics2D g, ArcShape aShape, PolygonBreak aPGB, - Rectangle2D area, float dist, float ex, Font labelFont, Color labelColor) { - float startAngle = aShape.getStartAngle(); - float sweepAngle = aShape.getSweepAngle(); - float angle = startAngle + sweepAngle / 2; - float space = 20; - Rectangle2D rect = new Rectangle2D.Double(area.getX() + ex + space, area.getY() + ex + space, area.getWidth() - ex - space, - area.getHeight() - ex - space); - double dx = 0, dy = 0; - if (aShape.getExplode() > 0) { - dx = ex * Math.cos((360 - angle) * Math.PI / 180); - dy = ex * Math.sin((360 - angle) * Math.PI / 180); - rect.setRect(rect.getX() + dx, rect.getY() + dy, rect.getWidth(), rect.getHeight()); - } - float sx = (float) (rect.getX() - area.getX()); - float sy = (float) (rect.getY() - area.getY()); - Draw.drawPie(new PointF(sx, sy), (float) rect.getWidth(), (float) rect.getHeight(), - startAngle, sweepAngle, aPGB, g); - - //Draw label - //Rectangle clip = g.getClipBounds(); - //if (clip != null) { - // g.setClip(null); - //} - float x, y, w, h; - PointF sPoint = new PointF((float) (rect.getWidth() * 0.5 + sx), (float) (rect.getHeight() * 0.5 + sy)); - String label = aPGB.getCaption(); - if (angle > 360) { - angle = angle - 360; - } - float r = (float) (rect.getWidth() * 0.5) + dist; - PointF lPoint = Draw.getPieLabelPoint(sPoint, r, angle); - x = lPoint.X; - y = lPoint.Y; - Dimension dim = Draw.getStringDimension(label, g); - h = dim.height; - w = dim.width; - if ((angle >= 0 && angle < 45)) { - //x = x + dis; - y = y - h; - } else if (angle >= 45 && angle < 90) { - //y = y - dis; - } else if (angle >= 90 && angle < 135) { - x = x - w; - //y = y - dis; - } else if (angle >= 135 && angle < 225) { - x = x - w - 3; - y = y + h / 2; - } else if (angle >= 225 && angle < 270) { - x = x - w / 2; - y = y + h; - } else if (angle >= 270 && angle < 315) { - //x = x + dis; - y = y + h; - } else { - //x = x + dis; - y = y + h / 2; - } - g.setFont(labelFont); - g.setColor(labelColor); - //g.drawOval((int)(x - 3), (int)(y - 3), 6, 6); - g.drawString(label, x, y); - - //if (clip != null) { - // g.setClip(clip); - //} - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart.plot; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.shape.ArcShape; +import org.meteoinfo.shape.Graphic; +import org.meteoinfo.shape.GraphicCollection; +import org.meteoinfo.shape.Shape; + +/** + * + * @author Yaqiang Wang + */ +public class PiePlot extends Plot2D { + + // + // + // + /** + * Constructor + */ + public PiePlot(){ + super(); + this.setAutoAspect(false); + } + // + // + // + // + @Override + void drawGraph(Graphics2D g, Rectangle2D area) { + AffineTransform oldMatrix = g.getTransform(); + //Rectangle oldRegion = g.getClipBounds(); + //g.setClip(area); + g.translate(area.getX(), area.getY()); + + //Draw background + if (this.background != null) { + g.setColor(this.getBackground()); + g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); + } + + for (int m = 0; m < this.getGraphics().getNumGraphics(); m++) { + Graphic graphic = this.getGraphics().get(m); + ColorBreak cb = graphic.getLegend(); + float dist = 5; + float ex = this.getExplode(); + Font labelFont = ((GraphicCollection)graphic).getLabelSet().getLabelFont(); + Color labelColor = ((GraphicCollection)graphic).getLabelSet().getLabelColor(); + for (int i = 0; i < graphic.getNumGraphics(); i++) { + Graphic gg = graphic.getGraphicN(i); + if (!graphic.isSingleLegend()) { + cb = gg.getLegend(); + } + Shape shape = gg.getShape(); + this.drawArc(g, (ArcShape) shape, (PolygonBreak) cb, area, dist, ex, labelFont, + labelColor); + } + } + + g.setTransform(oldMatrix); + //g.setClip(oldRegion); + } + + private float getExplode() { + Graphic graphic = this.getGraphics().get(0); + float ex = 0; + for (int i = 0; i < graphic.getNumGraphics(); i++) { + Graphic gg = graphic.getGraphicN(i); + ArcShape shape = (ArcShape) gg.getShape(); + if (shape.getExplode() > 0) { + ex = 10; + break; + } + } + return ex; + } + + private void drawArc(Graphics2D g, ArcShape aShape, PolygonBreak aPGB, + Rectangle2D area, float dist, float ex, Font labelFont, Color labelColor) { + float startAngle = aShape.getStartAngle(); + float sweepAngle = aShape.getSweepAngle(); + float angle = startAngle + sweepAngle / 2; + float space = 20; + Rectangle2D rect = new Rectangle2D.Double(area.getX() + ex + space, area.getY() + ex + space, area.getWidth() - ex - space, + area.getHeight() - ex - space); + double dx = 0, dy = 0; + if (aShape.getExplode() > 0) { + dx = ex * Math.cos((360 - angle) * Math.PI / 180); + dy = ex * Math.sin((360 - angle) * Math.PI / 180); + rect.setRect(rect.getX() + dx, rect.getY() + dy, rect.getWidth(), rect.getHeight()); + } + float sx = (float) (rect.getX() - area.getX()); + float sy = (float) (rect.getY() - area.getY()); + Draw.drawPie(new PointF(sx, sy), (float) rect.getWidth(), (float) rect.getHeight(), + startAngle, sweepAngle, aPGB, g); + + //Draw label + //Rectangle clip = g.getClipBounds(); + //if (clip != null) { + // g.setClip(null); + //} + float x, y, w, h; + PointF sPoint = new PointF((float) (rect.getWidth() * 0.5 + sx), (float) (rect.getHeight() * 0.5 + sy)); + String label = aPGB.getCaption(); + if (angle > 360) { + angle = angle - 360; + } + float r = (float) (rect.getWidth() * 0.5) + dist; + PointF lPoint = Draw.getPieLabelPoint(sPoint, r, angle); + x = lPoint.X; + y = lPoint.Y; + Dimension dim = Draw.getStringDimension(label, g); + h = dim.height; + w = dim.width; + if ((angle >= 0 && angle < 45)) { + //x = x + dis; + y = y - h; + } else if (angle >= 45 && angle < 90) { + //y = y - dis; + } else if (angle >= 90 && angle < 135) { + x = x - w; + //y = y - dis; + } else if (angle >= 135 && angle < 225) { + x = x - w - 3; + y = y + h / 2; + } else if (angle >= 225 && angle < 270) { + x = x - w / 2; + y = y + h; + } else if (angle >= 270 && angle < 315) { + //x = x + dis; + y = y + h; + } else { + //x = x + dis; + y = y + h / 2; + } + g.setFont(labelFont); + g.setColor(labelColor); + //g.drawOval((int)(x - 3), (int)(y - 3), 6, 6); + g.drawString(label, x, y); + + //if (clip != null) { + // g.setClip(clip); + //} + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot2D.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot2D.java index 71f0dccb..6010a86f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot2D.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot2D.java @@ -35,16 +35,17 @@ import org.meteoinfo.chart.ChartLegend; import org.meteoinfo.chart.ChartText; import org.meteoinfo.chart.axis.LogAxis; import org.meteoinfo.chart.axis.TimeAxis; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.data.Dataset; import org.meteoinfo.drawing.Draw; import static org.meteoinfo.drawing.Draw.getHatchImage; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; + +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.legend.ArrowBreak; import org.meteoinfo.legend.BarBreak; -import static org.meteoinfo.legend.BreakTypes.LabelBreak; import org.meteoinfo.legend.ColorBreak; import org.meteoinfo.legend.ColorBreakCollection; import org.meteoinfo.legend.LabelBreak; @@ -767,7 +768,7 @@ public class Plot2D extends AbstractPlot2D { aY = (float) sXY[1]; points.add(new PointD(aX, aY)); } - Extent aExtent = MIMath.getPointsExtent(points); + Extent aExtent = GeometryUtil.getPointsExtent(points); rect.x = (int) aExtent.minX; rect.y = (int) aExtent.minY; rect.width = (int) (aExtent.maxX - aExtent.minX); @@ -779,7 +780,7 @@ public class Plot2D extends AbstractPlot2D { } private List drawPolygon(Graphics2D g, Polygon aPG, PolygonBreak aPGB, - boolean isSelected, Rectangle2D area) { + boolean isSelected, Rectangle2D area) { int len = aPG.getOutLine().size(); GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, len); PointD wPoint; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot3D.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot3D.java index 8f938963..958dcbd6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot3D.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/Plot3D.java @@ -10,7 +10,6 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; @@ -31,13 +30,13 @@ import org.meteoinfo.chart.axis.Axis; import org.meteoinfo.chart.axis.LogAxis; import org.meteoinfo.chart.plot3d.GraphicCollection3D; import org.meteoinfo.chart.plot3d.Projector; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointF; import org.meteoinfo.data.DataMath; import org.meteoinfo.data.Dataset; import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointF; import org.meteoinfo.legend.*; import org.meteoinfo.math.sort.QuickSort; import org.meteoinfo.shape.*; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java index a3b4c9d2..d233f8e0 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java @@ -16,11 +16,11 @@ import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; import org.meteoinfo.chart.Margin; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; import org.meteoinfo.drawing.Draw; import static org.meteoinfo.drawing.Draw.getDashPattern; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; import org.meteoinfo.legend.LineStyles; import org.meteoinfo.shape.Graphic; import org.meteoinfo.shape.GraphicCollection; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/XY1DPlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/XY1DPlot.java index 384f1a4e..abcf29e4 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/XY1DPlot.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/XY1DPlot.java @@ -1,874 +1,874 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.chart.plot; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.meteoinfo.chart.ChartLegend; -import org.meteoinfo.chart.Location; -import org.meteoinfo.chart.axis.TimeAxis; -import org.meteoinfo.data.Dataset; -import org.meteoinfo.data.XYDataset; -import org.meteoinfo.data.XYErrorSeriesData; -import org.meteoinfo.data.XYListDataset; -import org.meteoinfo.data.XYSeriesData; -import org.meteoinfo.data.XYYSeriesData; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointF; -import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.LegendScheme; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import org.meteoinfo.shape.ShapeTypes; - -/** - * - * @author yaqiang - */ -public class XY1DPlot extends AbstractPlot2D { - - // - private XYListDataset dataset; - private ChartPlotMethod chartPlotMethod; - private List seriesLegends; - private boolean useBreak2D; - private float barWidth; - private boolean autoBarWidth; - - // - // - /** - * Constructor - */ - public XY1DPlot() { - super(); - - this.dataset = new XYListDataset(); - this.chartPlotMethod = ChartPlotMethod.LINE; - this.useBreak2D = false; - this.seriesLegends = new ArrayList<>(); - this.barWidth = 0.8f; - this.autoBarWidth = true; - } - - /** - * Constructor - * - * @param dateset Dataset - */ - public XY1DPlot(XYDataset dateset) { - this(); - this.setDataset(dateset); - } - - /** - * Constructor - * - * @param orientation Plot orientation - * @param dateset Dataset - */ - public XY1DPlot(PlotOrientation orientation, XYDataset dateset) { - this(); - this.setPlotOrientation(orientation); - this.setDataset(dateset); - } - - /** - * Constructor - * - * @param isTime If x axis is time - * @param dateset Dataset - */ - public XY1DPlot(boolean isTime, XYDataset dateset) { - this(); - if (isTime) { - try { - this.setXAxis(new TimeAxis("X", true)); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); - } - this.getAxis(Location.TOP).setDrawTickLabel(false); - } - //this.getXAxis().setTimeAxis(isTime); - this.setDataset(dateset); - } - - /** - * Constructor - * - * @param isTime If x axis is time - * @param cpMethod Plot method - * @param dateset Dataset - */ - public XY1DPlot(boolean isTime, ChartPlotMethod cpMethod, XYDataset dateset) { - this(); - if (isTime) { - try { - this.setXAxis(new TimeAxis("X", true)); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); - } - this.getAxis(Location.TOP).setDrawTickLabel(false); - } - //this.getXAxis().setTimeAxis(isTime); - this.setChartPlotMethod(cpMethod); - this.setDataset(dateset); - } - - /** - * Constructor - * - * @param isTime If x axis is time - * @param orientation Plot orientation - * @param dateset Dataset - */ - public XY1DPlot(boolean isTime, PlotOrientation orientation, XYDataset dateset) { - this(); - if (isTime) { - try { - this.setXAxis(new TimeAxis("X", true)); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); - } - this.getAxis(Location.TOP).setDrawTickLabel(false); - } - //this.getXAxis().setTimeAxis(isTime); - this.setPlotOrientation(orientation); - this.setDataset(dateset); - } - - // - // - @Override - public XYDataset getDataset() { - return dataset; - } - - @Override - public void setDataset(Dataset value) { - dataset = (XYListDataset) value; - Extent extent = this.getAutoExtent(); - this.setDrawExtent(extent); - this.setExtent(extent); - this.updateSeriesLegend(); - } - - private void updateSeriesLegend() { - //this.seriesLegends.clear(); - int si = this.seriesLegends.size(); - if (si > dataset.getSeriesCount()) { - si = 0; - } - for (int i = si; i < dataset.getSeriesCount(); i++) { - Color color = ColorUtil.getCommonColor(i); - switch (this.chartPlotMethod) { - case LINE: - case LINE_POINT: - PolylineBreak plb = new PolylineBreak(); - if (this.chartPlotMethod == ChartPlotMethod.LINE) { - plb.setDrawSymbol(false); - } else { - plb.setDrawSymbol(true); - plb.setSymbolColor(color); - plb.setSymbolFillColor(color); - } - plb.setColor(color); - plb.setCaption(dataset.getSeriesKey(i)); - seriesLegends.add(new SeriesLegend(plb)); - break; - case POINT: - PointBreak pb = new PointBreak(); - pb.setColor(color); - pb.setCaption(dataset.getSeriesKey(i)); - seriesLegends.add(new SeriesLegend(pb)); - break; - case BAR: - PolygonBreak pgb = new PolygonBreak(); - pgb.setColor(color); - pgb.setCaption(dataset.getSeriesKey(i)); - seriesLegends.add(new SeriesLegend(pgb)); - break; - } - } - } - - /** - * Get chart plot method - * - * @return Chart plot method - */ - public ChartPlotMethod getChartPlotMethod() { - return this.chartPlotMethod; - } - - /** - * Set chart plot method - * - * @param value Chart plot method - */ - public void setChartPlotMethod(ChartPlotMethod value) { - this.chartPlotMethod = value; - if (this.dataset != null) { - this.updateSeriesLegend(); - } - } - - @Override - public PlotType getPlotType() { - return PlotType.XY; - } - - /** - * Get Series legend breaks - * - * @return Series legend breaks - */ - public List getLegendBreaks() { - return this.seriesLegends; - } - -// /** -// * Get point breaks -// * -// * @return Point breaks -// */ -// public PointBreak[] getPointBreaks() { -// return this.pointBreaks; -// } - /** - * If use item 2D point breaks - * - * @return Boolean - */ - public boolean isUseBreak2D() { - return this.useBreak2D; - } - - /** - * Set if use item 2D point breaks - * - * @param value Boolean - */ - public void setUseBeak2D(boolean value) { - this.useBreak2D = value; - } - - /** - * Get bar width ratio - * - * @return Bar width ratio - */ - public float getBarWidth() { - return this.barWidth; - } - - /** - * Set bar width ratio - * - * @param value Bar width ratio - */ - public void setBarWidth(float value) { - this.barWidth = value; - } - - /** - * Get if automatically decide bar width - * - * @return Boolean - */ - public boolean isAutoBarWidth() { - return this.autoBarWidth; - } - - /** - * Set if automatically decide bar height - * - * @param value Boolean - */ - public void setAutoBarWidth(boolean value) { - this.autoBarWidth = value; - } - - // - // - /** - * Add a series data - * - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, double[] xvs, double[] yvs) { - ((XYListDataset) this.dataset).addSeries(seriesKey, xvs, yvs); - PolylineBreak plb = new PolylineBreak(); - plb.setColor(ColorUtil.getCommonColor(this.dataset.getSeriesCount())); - plb.setCaption(seriesKey); - seriesLegends.add(new SeriesLegend(plb)); - - Extent extent = this.getAutoExtent(); - this.setDrawExtent(extent); - } - - /** - * Remove last series - */ - public void removeLastSeries() { - XYListDataset ds = (XYListDataset) this.dataset; - ds.removeSeries(dataset.getSeriesCount() - 1); - this.seriesLegends.remove(this.seriesLegends.size() - 1); - - Extent extent = this.getAutoExtent(); - this.setDrawExtent(extent); - } - - private PointF[] getScreenPoints(double[] xdata, double[] ydata, List mvIdx, Rectangle2D area) { - int len = xdata.length; - PointF[] points = new PointF[len]; - double[] xy; - if (this.getPlotOrientation() == PlotOrientation.VERTICAL) { - for (int j = 0; j < len; j++) { - xy = this.projToScreen(xdata[j], ydata[j], area); - points[j] = new PointF((float) xy[0], (float) xy[1]); - } - } else { - for (int j = 0; j < len; j++) { - xy = this.projToScreen(xdata[j], ydata[j], area); - points[j] = new PointF((float) xy[0], (float) xy[1]); - } - } -// if (this.getYAxis().isInverse()) { -// PointF[] npoints = new PointF[len]; -// PointF p; -// float y; -// for (int j = 0; j < len; j++) { -// p = points[len - j - 1]; -// y = (float) area.getHeight() - p.Y; -// npoints[j] = new PointF(p.X, y); -// } -// points = npoints; -// if (!mvIdx.isEmpty()) { -// for (int j = 0; j < mvIdx.size(); j++) { -// mvIdx.set(j, len - mvIdx.get(j) - 1); -// } -// } -// } -// if (this.getXAxis().isInverse()) { -// PointF[] npoints = new PointF[len]; -// PointF p; -// float x; -// for (int j = 0; j < len; j++) { -// p = points[len - j - 1]; -// x = (float) area.getWidth() - p.X; -// npoints[j] = new PointF(x, p.Y); -// } -// points = npoints; -// if (!mvIdx.isEmpty()) { -// for (int j = 0; j < mvIdx.size(); j++) { -// mvIdx.set(j, len - mvIdx.get(j) - 1); -// } -// } -// } - - return points; - } - - @Override - void drawGraph(Graphics2D g, Rectangle2D area) { - AffineTransform oldMatrix = g.getTransform(); - Rectangle oldRegion = g.getClipBounds(); - g.setClip(area); - g.translate(area.getX(), area.getY()); - - //Draw background - if (this.background != null) { - g.setColor(this.getBackground()); - g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); - } - - double[] xy; - xy = this.projToScreen(0, 0, area); - float y0 = (float) xy[1]; - boolean drawBaseline = false; - for (int i = 0; i < this.dataset.getSeriesCount(); i++) { - XYSeriesData sdata = this.dataset.getSeriesData(i); - int len = sdata.dataLength(); - List mvIdx = sdata.getMissingValueIndex(); - PointF[] points = getScreenPoints(sdata.getXdata(), sdata.getYdata(), mvIdx, area); - SeriesLegend slegend = this.seriesLegends.get(i); - if (slegend.isLine()) { - if (mvIdx.isEmpty()) { - Draw.drawPolyline(points, (PolylineBreak) slegend.getLegendBreak(), g); - } else { - Draw.drawPolyline(points, (PolylineBreak) slegend.getLegendBreak(), g, mvIdx); - } - } else if (slegend.isPoint()) { - if (slegend.isMutiple()) { - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - Draw.drawPoint(points[j], (PointBreak) slegend.getLegendBreak(j), g); - } - } - } else { - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - Draw.drawPoint(points[j], (PointBreak) slegend.getLegendBreak(), g); - } - } - } - } else if (slegend.isPolygon()) { - switch (slegend.getPlotMethod()) { - case BAR: - if (sdata instanceof XYErrorSeriesData) { - drawBaseline = true; - XYErrorSeriesData esdata = (XYErrorSeriesData) sdata; - double[] bottom = esdata.getBottom(); - float[] yBottoms = null; - if (bottom != null) { - yBottoms = new float[bottom.length]; - for (int j = 0; j < bottom.length; j++) { - xy = this.projToScreen(esdata.getBottom(j), esdata.getBottom(j), area); - yBottoms[j] = (float) xy[1]; - } - } - float width = this.barWidth; - if (this.autoBarWidth) { - if (points.length > 1) { - width = (float) ((points[1].X - points[0].X) * 0.5) / this.dataset.getSeriesCount(); - } else { - width = (float) (area.getWidth() / 10) / this.dataset.getSeriesCount(); - } - float height; - PolygonBreak pgb; - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - pgb = (PolygonBreak) slegend.getLegendBreak(j); - height = Math.abs((float) (points[j].Y - y0)); - float yBottom = y0; - if (yBottoms != null) { - if (j < yBottoms.length) { - yBottom = yBottoms[j]; - } else { - yBottom = yBottoms[0]; - } - } - float yb = yBottom; - if (points[j].Y >= y0) { - yb += height; - } - Draw.drawBar(new PointF(points[j].X - width * this.dataset.getSeriesCount() / 2 - + i * width, yb), width, height, pgb, g, false, 5); - if (esdata.getYerror() != null) { - PointF p = (PointF) points[j].clone(); - p.Y -= y0 - yBottom; - double elen = 6; - double error = esdata.getYerror(j); - error = this.projYLength(error, area); - double x = p.X - width * this.dataset.getSeriesCount() / 2 - + i * width + width / 2; - g.setColor(slegend.getErrorColor()); - g.draw(new Line2D.Double(x, p.Y - error, x, p.Y + error)); - g.draw(new Line2D.Double(x - (elen * 0.5), p.Y - error, x + (elen * 0.5), p.Y - error)); - g.draw(new Line2D.Double(x - (elen * 0.5), p.Y + error, x + (elen * 0.5), p.Y + error)); - } - } - } - } else { - width = (float) this.projXLength(width, area); - float height; - PolygonBreak pgb; - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - pgb = (PolygonBreak) slegend.getLegendBreak(j); - height = Math.abs((float) (points[j].Y - y0)); - float yBottom = y0; - if (yBottoms != null) { - if (j < yBottoms.length) { - yBottom = yBottoms[j]; - } else { - yBottom = yBottoms[0]; - } - } - float yb = yBottom; - if (points[j].Y >= y0) { - yb += height; - } - Draw.drawBar(new PointF(points[j].X, yb), width, height, pgb, g, false, 5); - if (esdata.getYerror() != null) { - PointF p = (PointF) points[j].clone(); - p.Y -= y0 - yBottom; - double elen = 6; - double error = esdata.getYerror(j); - error = this.projYLength(error, area); - double x = p.X + width / 2; - g.setColor(slegend.getErrorColor()); - g.draw(new Line2D.Double(x, p.Y - error, x, p.Y + error)); - g.draw(new Line2D.Double(x - (elen * 0.5), p.Y - error, x + (elen * 0.5), p.Y - error)); - g.draw(new Line2D.Double(x - (elen * 0.5), p.Y + error, x + (elen * 0.5), p.Y + error)); - } - } - } - } - } else { - drawBaseline = true; - float width = this.barWidth; - if (this.autoBarWidth) { - if (points.length > 1) { - width = (float) ((points[1].X - points[0].X) * 0.5) / this.dataset.getSeriesCount(); - } else { - width = (float) (area.getWidth() / 10) / this.dataset.getSeriesCount(); - } - float height; - PolygonBreak pgb; - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - pgb = (PolygonBreak) slegend.getLegendBreak(j); - height = Math.abs((float) (points[j].Y - y0)); - float yb = y0; - if (points[j].Y >= y0) { - yb += height; - } - Draw.drawBar(new PointF(points[j].X - width * this.dataset.getSeriesCount() / 2 - + i * width, yb), width, height, pgb, g, false, 5); - } - } - } else { - width = (float) this.projXLength(width, area); - float height; - PolygonBreak pgb; - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - pgb = (PolygonBreak) slegend.getLegendBreak(j); - height = Math.abs((float) (points[j].Y - y0)); - float yb = y0; - if (points[j].Y >= y0) { - yb += height; - } - Draw.drawBar(new PointF(points[j].X, yb), width, height, pgb, g, false, 5); - } - } - } - } - break; - case FILL: - XYYSeriesData xyydata = (XYYSeriesData) sdata; - PointF[] y2Points = this.getScreenPoints(xyydata.getXdata(), xyydata.getY2data(), mvIdx, area); - if (xyydata.getWhere() == null) { - PointF[] npoints = new PointF[len * 2]; - for (int j = 0; j < len; j++) { - npoints[j] = points[len - j - 1]; - npoints[j + len] = y2Points[j]; - } - Draw.drawPolygon(npoints, (PolygonBreak) slegend.getLegendBreak(), g); - } else { - boolean ob = false; - List> idxs = new ArrayList<>(); - List idx = new ArrayList<>(); - for (int j = 0; j < len; j++) { - if (xyydata.getWhere().get(j)) { - if (!ob) { - idx = new ArrayList<>(); - } - idx.add(j); - } else if (ob) { - idxs.add(idx); - } - ob = xyydata.getWhere().get(j); - } - for (List index : idxs) { - int nn = index.size(); - if (nn >= 2) { - PointF[] npoints = new PointF[nn * 2]; - int ii, ii2; - for (int j = 0; j < nn; j++) { - ii = index.get(j); - ii2 = index.get(nn - j - 1); - npoints[j] = points[ii]; - npoints[j + index.size()] = y2Points[ii2]; - } - Draw.drawPolygon(npoints, (PolygonBreak) slegend.getLegendBreak(), g); - } - } - } - break; - } - } - - //Draw baseline - if (drawBaseline) { - g.setColor(Color.black); - g.draw(new Line2D.Double(0, y0, area.getWidth(), y0)); - } - - //Draw error bar - if (sdata instanceof XYErrorSeriesData) { - XYErrorSeriesData esdata = (XYErrorSeriesData) sdata; - g.setColor(slegend.getLegendBreak().getColor()); - PointF p; - double error; - double elen = 6; - if (esdata.getYerror() != null) { - if (slegend.getPlotMethod() == ChartPlotMethod.BAR) { - - } else { - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - p = points[j]; - error = esdata.getYerror(j); - error = this.projYLength(error, area); - g.draw(new Line2D.Double(p.X, p.Y - error, p.X, p.Y + error)); - g.draw(new Line2D.Double(p.X - (elen * 0.5), p.Y - error, p.X + (elen * 0.5), p.Y - error)); - g.draw(new Line2D.Double(p.X - (elen * 0.5), p.Y + error, p.X + (elen * 0.5), p.Y + error)); - } - } - } - } - if (esdata.getXerror() != null) { - for (int j = 0; j < len; j++) { - if (!mvIdx.contains(j)) { - p = points[j]; - error = esdata.getXerror(j); - error = this.projXLength(error, area); - g.draw(new Line2D.Double(p.X - error, p.Y, p.X + error, p.Y)); - g.draw(new Line2D.Double(p.X - error, p.Y - (elen * 0.5), p.X - error, p.Y + (elen * 0.5))); - g.draw(new Line2D.Double(p.X + error, p.Y - (elen * 0.5), p.X + error, p.Y + (elen * 0.5))); - } - } - } - } - } - - //Draw texts -// for (ChartText text : this.getTexts()) { -// xy = this.projToScreen(text.getX(), text.getY(), area); -// float x = (float) xy[0]; -// float y = (float) xy[1]; -// g.setFont(text.getFont()); -// g.setColor(text.getColor()); -// //Dimension dim = Draw.getStringDimension(text.getText(), g); -// //y -= dim.height * 2 / 3; -// Draw.drawString(g, text.getText(), x, y); -// } - g.setTransform(oldMatrix); - g.setClip(oldRegion); - } - - /** - * Get a item point break - * - * @param seriesIdx Series index - * @param itemIdx Item index - * @return Item point break; - */ - public PointBreak getItemPointBreak(int seriesIdx, int itemIdx) { - return (PointBreak) this.seriesLegends.get(seriesIdx).getLegendBreak(itemIdx); - } - - /** - * Set item point break - * - * @param seriesIdx Series index - * @param itemIdx Item index - * @param pb Item point break - */ - public void setItemPointBreak(int seriesIdx, int itemIdx, PointBreak pb) { - this.seriesLegends.get(seriesIdx).setLegendBreak(itemIdx, pb); - } - - /** - * Get legend break - * - * @param seriesIdx Series index - * @return Legend break - */ - public ColorBreak getLegendBreak(int seriesIdx) { - return this.seriesLegends.get(seriesIdx).getLegendBreak(); - } - - /** - * Set legend break - * - * @param seriesIdx Series index - * @param cb Legend break - */ - public void setLegendBreak(int seriesIdx, ColorBreak cb) { - this.seriesLegends.get(seriesIdx).setLegendBreak(cb); - } - - /** - * Set series legend - * - * @param seriesIdx Series index - * @param sLegend SeriesLegend - */ - public void setLegendBreak(int seriesIdx, SeriesLegend sLegend) { - this.seriesLegends.set(seriesIdx, sLegend); - } - -// /** -// * Get point break -// * -// * @param seriesIdx Series index -// * @return Point break -// */ -// public PointBreak getPointBreak(int seriesIdx) { -// return this.pointBreaks[seriesIdx]; -// } -// -// /** -// * Set point break -// * -// * @param seriesIdx Series index -// * @param pb Point break -// */ -// public void setPointBreak(int seriesIdx, PointBreak pb) { -// this.pointBreaks[seriesIdx] = pb; -// } -// -// /** -// * Get polygon break -// * -// * @param seriesIdx Series index -// * @return Polygon break -// */ -// public PolygonBreak getPolygonBreak(int seriesIdx) { -// return this.polygonBreaks[seriesIdx]; -// } -// -// /** -// * Set polygon break -// * -// * @param seriesIdx Series index -// * @param pgb Polygon break -// */ -// public void setPolygonBreak(int seriesIdx, PolygonBreak pgb) { -// this.polygonBreaks[seriesIdx] = pgb; -// } - private double getBarXInterval(int idx) { - double[] xvalues = this.dataset.getXValues(idx); - if (xvalues.length == 1) { - if (xvalues[0] == 0) { - return 1; - } else { - return xvalues[0] / 10; - } - } else { - return xvalues[1] - xvalues[0]; - } - } - - private int getBarIndex() { - int idx = -1; - for (int i = 0; i < this.seriesLegends.size(); i++) { - if (this.seriesLegends.get(i).getPlotMethod() == ChartPlotMethod.BAR) { - idx = i; - break; - } - } - return idx; - } - - /** - * Get auto extent - * - * @return Auto extent - */ - @Override - public Extent getAutoExtent() { - Extent extent = dataset.getDataExtent(); - if (extent.minX == extent.maxX){ - extent.minX = extent.minX - Math.abs(extent.minX); - extent.maxX = extent.maxX + Math.abs(extent.minX); - } - if (extent.minY == extent.maxY){ - extent.minY = extent.minY - Math.abs(extent.minY); - extent.maxY = extent.maxY + Math.abs(extent.maxY); - } - - int barIdx = this.getBarIndex(); - if (barIdx >= 0) { - double dx = getBarXInterval(barIdx); - extent.minX -= dx; - extent.maxX += dx; - } - double[] xValues; - if (this.getXAxis() instanceof TimeAxis) { - //if (this.getXAxis().isTimeAxis()) { - xValues = (double[]) MIMath.getIntervalValues(extent.minX, extent.maxX, false).get(0); - xValues[0] = extent.minX; - xValues[xValues.length - 1] = extent.maxX; - } else { - xValues = (double[]) MIMath.getIntervalValues(extent.minX, extent.maxX, true).get(0); - } - double[] yValues = (double[]) MIMath.getIntervalValues(extent.minY, extent.maxY, true).get(0); - if (this.getPlotOrientation() == PlotOrientation.VERTICAL) { - return new Extent(xValues[0], xValues[xValues.length - 1], yValues[0], yValues[yValues.length - 1]); - } else { - return new Extent(yValues[0], yValues[yValues.length - 1], xValues[0], xValues[xValues.length - 1]); - } - } - - /** - * Set auto extent - */ - @Override - public void setAutoExtent() { - Extent extent = this.getAutoExtent(); - this.setDrawExtent(extent); - } - - /** - * Get legend scheme - * - * @return Legend scheme - */ - public LegendScheme getLegendScheme() { -// LegendScheme ls = null; -// switch (this.chartPlotMethod) { -// case LINE: -// case LINE_POINT: -// ls = new LegendScheme(ShapeTypes.Polyline); -// ls.getLegendBreaks().addAll(Arrays.asList(this.lineBreaks)); -// break; -// case POINT: -// ls = new LegendScheme(ShapeTypes.Point); -// ls.getLegendBreaks().addAll(Arrays.asList(this.pointBreaks)); -// break; -// case BAR: -// ls = new LegendScheme(ShapeTypes.Polygon); -// ls.getLegendBreaks().addAll(Arrays.asList(this.polygonBreaks)); -// break; -// } - ShapeTypes stype = ShapeTypes.Polyline; - LegendScheme ls = new LegendScheme(stype); - for (SeriesLegend slegend : this.seriesLegends) { - ls.getLegendBreaks().add(slegend.getLegendBreak()); - } - return ls; - } - - @Override - public void updateLegendScheme() { - if (this.getLegend() == null) { - this.setLegend(new ChartLegend(this.getLegendScheme())); - } else { - this.getLegend().setLegendScheme(this.getLegendScheme()); - } - } - - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.chart.plot; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.meteoinfo.chart.ChartLegend; +import org.meteoinfo.chart.Location; +import org.meteoinfo.chart.axis.TimeAxis; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointF; +import org.meteoinfo.data.Dataset; +import org.meteoinfo.data.XYDataset; +import org.meteoinfo.data.XYErrorSeriesData; +import org.meteoinfo.data.XYListDataset; +import org.meteoinfo.data.XYSeriesData; +import org.meteoinfo.data.XYYSeriesData; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.global.colors.ColorUtil; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.LegendScheme; +import org.meteoinfo.legend.PointBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.legend.PolylineBreak; +import org.meteoinfo.shape.ShapeTypes; + +/** + * + * @author yaqiang + */ +public class XY1DPlot extends AbstractPlot2D { + + // + private XYListDataset dataset; + private ChartPlotMethod chartPlotMethod; + private List seriesLegends; + private boolean useBreak2D; + private float barWidth; + private boolean autoBarWidth; + + // + // + /** + * Constructor + */ + public XY1DPlot() { + super(); + + this.dataset = new XYListDataset(); + this.chartPlotMethod = ChartPlotMethod.LINE; + this.useBreak2D = false; + this.seriesLegends = new ArrayList<>(); + this.barWidth = 0.8f; + this.autoBarWidth = true; + } + + /** + * Constructor + * + * @param dateset Dataset + */ + public XY1DPlot(XYDataset dateset) { + this(); + this.setDataset(dateset); + } + + /** + * Constructor + * + * @param orientation Plot orientation + * @param dateset Dataset + */ + public XY1DPlot(PlotOrientation orientation, XYDataset dateset) { + this(); + this.setPlotOrientation(orientation); + this.setDataset(dateset); + } + + /** + * Constructor + * + * @param isTime If x axis is time + * @param dateset Dataset + */ + public XY1DPlot(boolean isTime, XYDataset dateset) { + this(); + if (isTime) { + try { + this.setXAxis(new TimeAxis("X", true)); + } catch (CloneNotSupportedException ex) { + Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); + } + this.getAxis(Location.TOP).setDrawTickLabel(false); + } + //this.getXAxis().setTimeAxis(isTime); + this.setDataset(dateset); + } + + /** + * Constructor + * + * @param isTime If x axis is time + * @param cpMethod Plot method + * @param dateset Dataset + */ + public XY1DPlot(boolean isTime, ChartPlotMethod cpMethod, XYDataset dateset) { + this(); + if (isTime) { + try { + this.setXAxis(new TimeAxis("X", true)); + } catch (CloneNotSupportedException ex) { + Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); + } + this.getAxis(Location.TOP).setDrawTickLabel(false); + } + //this.getXAxis().setTimeAxis(isTime); + this.setChartPlotMethod(cpMethod); + this.setDataset(dateset); + } + + /** + * Constructor + * + * @param isTime If x axis is time + * @param orientation Plot orientation + * @param dateset Dataset + */ + public XY1DPlot(boolean isTime, PlotOrientation orientation, XYDataset dateset) { + this(); + if (isTime) { + try { + this.setXAxis(new TimeAxis("X", true)); + } catch (CloneNotSupportedException ex) { + Logger.getLogger(XY1DPlot.class.getName()).log(Level.SEVERE, null, ex); + } + this.getAxis(Location.TOP).setDrawTickLabel(false); + } + //this.getXAxis().setTimeAxis(isTime); + this.setPlotOrientation(orientation); + this.setDataset(dateset); + } + + // + // + @Override + public XYDataset getDataset() { + return dataset; + } + + @Override + public void setDataset(Dataset value) { + dataset = (XYListDataset) value; + Extent extent = this.getAutoExtent(); + this.setDrawExtent(extent); + this.setExtent(extent); + this.updateSeriesLegend(); + } + + private void updateSeriesLegend() { + //this.seriesLegends.clear(); + int si = this.seriesLegends.size(); + if (si > dataset.getSeriesCount()) { + si = 0; + } + for (int i = si; i < dataset.getSeriesCount(); i++) { + Color color = ColorUtil.getCommonColor(i); + switch (this.chartPlotMethod) { + case LINE: + case LINE_POINT: + PolylineBreak plb = new PolylineBreak(); + if (this.chartPlotMethod == ChartPlotMethod.LINE) { + plb.setDrawSymbol(false); + } else { + plb.setDrawSymbol(true); + plb.setSymbolColor(color); + plb.setSymbolFillColor(color); + } + plb.setColor(color); + plb.setCaption(dataset.getSeriesKey(i)); + seriesLegends.add(new SeriesLegend(plb)); + break; + case POINT: + PointBreak pb = new PointBreak(); + pb.setColor(color); + pb.setCaption(dataset.getSeriesKey(i)); + seriesLegends.add(new SeriesLegend(pb)); + break; + case BAR: + PolygonBreak pgb = new PolygonBreak(); + pgb.setColor(color); + pgb.setCaption(dataset.getSeriesKey(i)); + seriesLegends.add(new SeriesLegend(pgb)); + break; + } + } + } + + /** + * Get chart plot method + * + * @return Chart plot method + */ + public ChartPlotMethod getChartPlotMethod() { + return this.chartPlotMethod; + } + + /** + * Set chart plot method + * + * @param value Chart plot method + */ + public void setChartPlotMethod(ChartPlotMethod value) { + this.chartPlotMethod = value; + if (this.dataset != null) { + this.updateSeriesLegend(); + } + } + + @Override + public PlotType getPlotType() { + return PlotType.XY; + } + + /** + * Get Series legend breaks + * + * @return Series legend breaks + */ + public List getLegendBreaks() { + return this.seriesLegends; + } + +// /** +// * Get point breaks +// * +// * @return Point breaks +// */ +// public PointBreak[] getPointBreaks() { +// return this.pointBreaks; +// } + /** + * If use item 2D point breaks + * + * @return Boolean + */ + public boolean isUseBreak2D() { + return this.useBreak2D; + } + + /** + * Set if use item 2D point breaks + * + * @param value Boolean + */ + public void setUseBeak2D(boolean value) { + this.useBreak2D = value; + } + + /** + * Get bar width ratio + * + * @return Bar width ratio + */ + public float getBarWidth() { + return this.barWidth; + } + + /** + * Set bar width ratio + * + * @param value Bar width ratio + */ + public void setBarWidth(float value) { + this.barWidth = value; + } + + /** + * Get if automatically decide bar width + * + * @return Boolean + */ + public boolean isAutoBarWidth() { + return this.autoBarWidth; + } + + /** + * Set if automatically decide bar height + * + * @param value Boolean + */ + public void setAutoBarWidth(boolean value) { + this.autoBarWidth = value; + } + + // + // + /** + * Add a series data + * + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, double[] xvs, double[] yvs) { + ((XYListDataset) this.dataset).addSeries(seriesKey, xvs, yvs); + PolylineBreak plb = new PolylineBreak(); + plb.setColor(ColorUtil.getCommonColor(this.dataset.getSeriesCount())); + plb.setCaption(seriesKey); + seriesLegends.add(new SeriesLegend(plb)); + + Extent extent = this.getAutoExtent(); + this.setDrawExtent(extent); + } + + /** + * Remove last series + */ + public void removeLastSeries() { + XYListDataset ds = (XYListDataset) this.dataset; + ds.removeSeries(dataset.getSeriesCount() - 1); + this.seriesLegends.remove(this.seriesLegends.size() - 1); + + Extent extent = this.getAutoExtent(); + this.setDrawExtent(extent); + } + + private PointF[] getScreenPoints(double[] xdata, double[] ydata, List mvIdx, Rectangle2D area) { + int len = xdata.length; + PointF[] points = new PointF[len]; + double[] xy; + if (this.getPlotOrientation() == PlotOrientation.VERTICAL) { + for (int j = 0; j < len; j++) { + xy = this.projToScreen(xdata[j], ydata[j], area); + points[j] = new PointF((float) xy[0], (float) xy[1]); + } + } else { + for (int j = 0; j < len; j++) { + xy = this.projToScreen(xdata[j], ydata[j], area); + points[j] = new PointF((float) xy[0], (float) xy[1]); + } + } +// if (this.getYAxis().isInverse()) { +// PointF[] npoints = new PointF[len]; +// PointF p; +// float y; +// for (int j = 0; j < len; j++) { +// p = points[len - j - 1]; +// y = (float) area.getHeight() - p.Y; +// npoints[j] = new PointF(p.X, y); +// } +// points = npoints; +// if (!mvIdx.isEmpty()) { +// for (int j = 0; j < mvIdx.size(); j++) { +// mvIdx.set(j, len - mvIdx.get(j) - 1); +// } +// } +// } +// if (this.getXAxis().isInverse()) { +// PointF[] npoints = new PointF[len]; +// PointF p; +// float x; +// for (int j = 0; j < len; j++) { +// p = points[len - j - 1]; +// x = (float) area.getWidth() - p.X; +// npoints[j] = new PointF(x, p.Y); +// } +// points = npoints; +// if (!mvIdx.isEmpty()) { +// for (int j = 0; j < mvIdx.size(); j++) { +// mvIdx.set(j, len - mvIdx.get(j) - 1); +// } +// } +// } + + return points; + } + + @Override + void drawGraph(Graphics2D g, Rectangle2D area) { + AffineTransform oldMatrix = g.getTransform(); + Rectangle oldRegion = g.getClipBounds(); + g.setClip(area); + g.translate(area.getX(), area.getY()); + + //Draw background + if (this.background != null) { + g.setColor(this.getBackground()); + g.fill(new Rectangle2D.Double(0, 0, area.getWidth(), area.getHeight())); + } + + double[] xy; + xy = this.projToScreen(0, 0, area); + float y0 = (float) xy[1]; + boolean drawBaseline = false; + for (int i = 0; i < this.dataset.getSeriesCount(); i++) { + XYSeriesData sdata = this.dataset.getSeriesData(i); + int len = sdata.dataLength(); + List mvIdx = sdata.getMissingValueIndex(); + PointF[] points = getScreenPoints(sdata.getXdata(), sdata.getYdata(), mvIdx, area); + SeriesLegend slegend = this.seriesLegends.get(i); + if (slegend.isLine()) { + if (mvIdx.isEmpty()) { + Draw.drawPolyline(points, (PolylineBreak) slegend.getLegendBreak(), g); + } else { + Draw.drawPolyline(points, (PolylineBreak) slegend.getLegendBreak(), g, mvIdx); + } + } else if (slegend.isPoint()) { + if (slegend.isMutiple()) { + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + Draw.drawPoint(points[j], (PointBreak) slegend.getLegendBreak(j), g); + } + } + } else { + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + Draw.drawPoint(points[j], (PointBreak) slegend.getLegendBreak(), g); + } + } + } + } else if (slegend.isPolygon()) { + switch (slegend.getPlotMethod()) { + case BAR: + if (sdata instanceof XYErrorSeriesData) { + drawBaseline = true; + XYErrorSeriesData esdata = (XYErrorSeriesData) sdata; + double[] bottom = esdata.getBottom(); + float[] yBottoms = null; + if (bottom != null) { + yBottoms = new float[bottom.length]; + for (int j = 0; j < bottom.length; j++) { + xy = this.projToScreen(esdata.getBottom(j), esdata.getBottom(j), area); + yBottoms[j] = (float) xy[1]; + } + } + float width = this.barWidth; + if (this.autoBarWidth) { + if (points.length > 1) { + width = (float) ((points[1].X - points[0].X) * 0.5) / this.dataset.getSeriesCount(); + } else { + width = (float) (area.getWidth() / 10) / this.dataset.getSeriesCount(); + } + float height; + PolygonBreak pgb; + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + pgb = (PolygonBreak) slegend.getLegendBreak(j); + height = Math.abs((float) (points[j].Y - y0)); + float yBottom = y0; + if (yBottoms != null) { + if (j < yBottoms.length) { + yBottom = yBottoms[j]; + } else { + yBottom = yBottoms[0]; + } + } + float yb = yBottom; + if (points[j].Y >= y0) { + yb += height; + } + Draw.drawBar(new PointF(points[j].X - width * this.dataset.getSeriesCount() / 2 + + i * width, yb), width, height, pgb, g, false, 5); + if (esdata.getYerror() != null) { + PointF p = (PointF) points[j].clone(); + p.Y -= y0 - yBottom; + double elen = 6; + double error = esdata.getYerror(j); + error = this.projYLength(error, area); + double x = p.X - width * this.dataset.getSeriesCount() / 2 + + i * width + width / 2; + g.setColor(slegend.getErrorColor()); + g.draw(new Line2D.Double(x, p.Y - error, x, p.Y + error)); + g.draw(new Line2D.Double(x - (elen * 0.5), p.Y - error, x + (elen * 0.5), p.Y - error)); + g.draw(new Line2D.Double(x - (elen * 0.5), p.Y + error, x + (elen * 0.5), p.Y + error)); + } + } + } + } else { + width = (float) this.projXLength(width, area); + float height; + PolygonBreak pgb; + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + pgb = (PolygonBreak) slegend.getLegendBreak(j); + height = Math.abs((float) (points[j].Y - y0)); + float yBottom = y0; + if (yBottoms != null) { + if (j < yBottoms.length) { + yBottom = yBottoms[j]; + } else { + yBottom = yBottoms[0]; + } + } + float yb = yBottom; + if (points[j].Y >= y0) { + yb += height; + } + Draw.drawBar(new PointF(points[j].X, yb), width, height, pgb, g, false, 5); + if (esdata.getYerror() != null) { + PointF p = (PointF) points[j].clone(); + p.Y -= y0 - yBottom; + double elen = 6; + double error = esdata.getYerror(j); + error = this.projYLength(error, area); + double x = p.X + width / 2; + g.setColor(slegend.getErrorColor()); + g.draw(new Line2D.Double(x, p.Y - error, x, p.Y + error)); + g.draw(new Line2D.Double(x - (elen * 0.5), p.Y - error, x + (elen * 0.5), p.Y - error)); + g.draw(new Line2D.Double(x - (elen * 0.5), p.Y + error, x + (elen * 0.5), p.Y + error)); + } + } + } + } + } else { + drawBaseline = true; + float width = this.barWidth; + if (this.autoBarWidth) { + if (points.length > 1) { + width = (float) ((points[1].X - points[0].X) * 0.5) / this.dataset.getSeriesCount(); + } else { + width = (float) (area.getWidth() / 10) / this.dataset.getSeriesCount(); + } + float height; + PolygonBreak pgb; + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + pgb = (PolygonBreak) slegend.getLegendBreak(j); + height = Math.abs((float) (points[j].Y - y0)); + float yb = y0; + if (points[j].Y >= y0) { + yb += height; + } + Draw.drawBar(new PointF(points[j].X - width * this.dataset.getSeriesCount() / 2 + + i * width, yb), width, height, pgb, g, false, 5); + } + } + } else { + width = (float) this.projXLength(width, area); + float height; + PolygonBreak pgb; + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + pgb = (PolygonBreak) slegend.getLegendBreak(j); + height = Math.abs((float) (points[j].Y - y0)); + float yb = y0; + if (points[j].Y >= y0) { + yb += height; + } + Draw.drawBar(new PointF(points[j].X, yb), width, height, pgb, g, false, 5); + } + } + } + } + break; + case FILL: + XYYSeriesData xyydata = (XYYSeriesData) sdata; + PointF[] y2Points = this.getScreenPoints(xyydata.getXdata(), xyydata.getY2data(), mvIdx, area); + if (xyydata.getWhere() == null) { + PointF[] npoints = new PointF[len * 2]; + for (int j = 0; j < len; j++) { + npoints[j] = points[len - j - 1]; + npoints[j + len] = y2Points[j]; + } + Draw.drawPolygon(npoints, (PolygonBreak) slegend.getLegendBreak(), g); + } else { + boolean ob = false; + List> idxs = new ArrayList<>(); + List idx = new ArrayList<>(); + for (int j = 0; j < len; j++) { + if (xyydata.getWhere().get(j)) { + if (!ob) { + idx = new ArrayList<>(); + } + idx.add(j); + } else if (ob) { + idxs.add(idx); + } + ob = xyydata.getWhere().get(j); + } + for (List index : idxs) { + int nn = index.size(); + if (nn >= 2) { + PointF[] npoints = new PointF[nn * 2]; + int ii, ii2; + for (int j = 0; j < nn; j++) { + ii = index.get(j); + ii2 = index.get(nn - j - 1); + npoints[j] = points[ii]; + npoints[j + index.size()] = y2Points[ii2]; + } + Draw.drawPolygon(npoints, (PolygonBreak) slegend.getLegendBreak(), g); + } + } + } + break; + } + } + + //Draw baseline + if (drawBaseline) { + g.setColor(Color.black); + g.draw(new Line2D.Double(0, y0, area.getWidth(), y0)); + } + + //Draw error bar + if (sdata instanceof XYErrorSeriesData) { + XYErrorSeriesData esdata = (XYErrorSeriesData) sdata; + g.setColor(slegend.getLegendBreak().getColor()); + PointF p; + double error; + double elen = 6; + if (esdata.getYerror() != null) { + if (slegend.getPlotMethod() == ChartPlotMethod.BAR) { + + } else { + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + p = points[j]; + error = esdata.getYerror(j); + error = this.projYLength(error, area); + g.draw(new Line2D.Double(p.X, p.Y - error, p.X, p.Y + error)); + g.draw(new Line2D.Double(p.X - (elen * 0.5), p.Y - error, p.X + (elen * 0.5), p.Y - error)); + g.draw(new Line2D.Double(p.X - (elen * 0.5), p.Y + error, p.X + (elen * 0.5), p.Y + error)); + } + } + } + } + if (esdata.getXerror() != null) { + for (int j = 0; j < len; j++) { + if (!mvIdx.contains(j)) { + p = points[j]; + error = esdata.getXerror(j); + error = this.projXLength(error, area); + g.draw(new Line2D.Double(p.X - error, p.Y, p.X + error, p.Y)); + g.draw(new Line2D.Double(p.X - error, p.Y - (elen * 0.5), p.X - error, p.Y + (elen * 0.5))); + g.draw(new Line2D.Double(p.X + error, p.Y - (elen * 0.5), p.X + error, p.Y + (elen * 0.5))); + } + } + } + } + } + + //Draw texts +// for (ChartText text : this.getTexts()) { +// xy = this.projToScreen(text.getX(), text.getY(), area); +// float x = (float) xy[0]; +// float y = (float) xy[1]; +// g.setFont(text.getFont()); +// g.setColor(text.getColor()); +// //Dimension dim = Draw.getStringDimension(text.getText(), g); +// //y -= dim.height * 2 / 3; +// Draw.drawString(g, text.getText(), x, y); +// } + g.setTransform(oldMatrix); + g.setClip(oldRegion); + } + + /** + * Get a item point break + * + * @param seriesIdx Series index + * @param itemIdx Item index + * @return Item point break; + */ + public PointBreak getItemPointBreak(int seriesIdx, int itemIdx) { + return (PointBreak) this.seriesLegends.get(seriesIdx).getLegendBreak(itemIdx); + } + + /** + * Set item point break + * + * @param seriesIdx Series index + * @param itemIdx Item index + * @param pb Item point break + */ + public void setItemPointBreak(int seriesIdx, int itemIdx, PointBreak pb) { + this.seriesLegends.get(seriesIdx).setLegendBreak(itemIdx, pb); + } + + /** + * Get legend break + * + * @param seriesIdx Series index + * @return Legend break + */ + public ColorBreak getLegendBreak(int seriesIdx) { + return this.seriesLegends.get(seriesIdx).getLegendBreak(); + } + + /** + * Set legend break + * + * @param seriesIdx Series index + * @param cb Legend break + */ + public void setLegendBreak(int seriesIdx, ColorBreak cb) { + this.seriesLegends.get(seriesIdx).setLegendBreak(cb); + } + + /** + * Set series legend + * + * @param seriesIdx Series index + * @param sLegend SeriesLegend + */ + public void setLegendBreak(int seriesIdx, SeriesLegend sLegend) { + this.seriesLegends.set(seriesIdx, sLegend); + } + +// /** +// * Get point break +// * +// * @param seriesIdx Series index +// * @return Point break +// */ +// public PointBreak getPointBreak(int seriesIdx) { +// return this.pointBreaks[seriesIdx]; +// } +// +// /** +// * Set point break +// * +// * @param seriesIdx Series index +// * @param pb Point break +// */ +// public void setPointBreak(int seriesIdx, PointBreak pb) { +// this.pointBreaks[seriesIdx] = pb; +// } +// +// /** +// * Get polygon break +// * +// * @param seriesIdx Series index +// * @return Polygon break +// */ +// public PolygonBreak getPolygonBreak(int seriesIdx) { +// return this.polygonBreaks[seriesIdx]; +// } +// +// /** +// * Set polygon break +// * +// * @param seriesIdx Series index +// * @param pgb Polygon break +// */ +// public void setPolygonBreak(int seriesIdx, PolygonBreak pgb) { +// this.polygonBreaks[seriesIdx] = pgb; +// } + private double getBarXInterval(int idx) { + double[] xvalues = this.dataset.getXValues(idx); + if (xvalues.length == 1) { + if (xvalues[0] == 0) { + return 1; + } else { + return xvalues[0] / 10; + } + } else { + return xvalues[1] - xvalues[0]; + } + } + + private int getBarIndex() { + int idx = -1; + for (int i = 0; i < this.seriesLegends.size(); i++) { + if (this.seriesLegends.get(i).getPlotMethod() == ChartPlotMethod.BAR) { + idx = i; + break; + } + } + return idx; + } + + /** + * Get auto extent + * + * @return Auto extent + */ + @Override + public Extent getAutoExtent() { + Extent extent = dataset.getDataExtent(); + if (extent.minX == extent.maxX){ + extent.minX = extent.minX - Math.abs(extent.minX); + extent.maxX = extent.maxX + Math.abs(extent.minX); + } + if (extent.minY == extent.maxY){ + extent.minY = extent.minY - Math.abs(extent.minY); + extent.maxY = extent.maxY + Math.abs(extent.maxY); + } + + int barIdx = this.getBarIndex(); + if (barIdx >= 0) { + double dx = getBarXInterval(barIdx); + extent.minX -= dx; + extent.maxX += dx; + } + double[] xValues; + if (this.getXAxis() instanceof TimeAxis) { + //if (this.getXAxis().isTimeAxis()) { + xValues = (double[]) MIMath.getIntervalValues(extent.minX, extent.maxX, false).get(0); + xValues[0] = extent.minX; + xValues[xValues.length - 1] = extent.maxX; + } else { + xValues = (double[]) MIMath.getIntervalValues(extent.minX, extent.maxX, true).get(0); + } + double[] yValues = (double[]) MIMath.getIntervalValues(extent.minY, extent.maxY, true).get(0); + if (this.getPlotOrientation() == PlotOrientation.VERTICAL) { + return new Extent(xValues[0], xValues[xValues.length - 1], yValues[0], yValues[yValues.length - 1]); + } else { + return new Extent(yValues[0], yValues[yValues.length - 1], xValues[0], xValues[xValues.length - 1]); + } + } + + /** + * Set auto extent + */ + @Override + public void setAutoExtent() { + Extent extent = this.getAutoExtent(); + this.setDrawExtent(extent); + } + + /** + * Get legend scheme + * + * @return Legend scheme + */ + public LegendScheme getLegendScheme() { +// LegendScheme ls = null; +// switch (this.chartPlotMethod) { +// case LINE: +// case LINE_POINT: +// ls = new LegendScheme(ShapeTypes.Polyline); +// ls.getLegendBreaks().addAll(Arrays.asList(this.lineBreaks)); +// break; +// case POINT: +// ls = new LegendScheme(ShapeTypes.Point); +// ls.getLegendBreaks().addAll(Arrays.asList(this.pointBreaks)); +// break; +// case BAR: +// ls = new LegendScheme(ShapeTypes.Polygon); +// ls.getLegendBreaks().addAll(Arrays.asList(this.polygonBreaks)); +// break; +// } + ShapeTypes stype = ShapeTypes.Polyline; + LegendScheme ls = new LegendScheme(stype); + for (SeriesLegend slegend : this.seriesLegends) { + ls.getLegendBreaks().add(slegend.getLegendBreak()); + } + return ls; + } + + @Override + public void updateLegendScheme() { + if (this.getLegend() == null) { + this.setLegend(new ChartLegend(this.getLegendScheme())); + } else { + this.getLegend().setLegendScheme(this.getLegendScheme()); + } + } + + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataMath.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataMath.java index b63d9e01..e17f56c8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataMath.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataMath.java @@ -14,9 +14,10 @@ package org.meteoinfo.data; import java.util.ArrayList; -import org.meteoinfo.global.MIMath; import java.util.Arrays; import java.util.List; + +import org.meteoinfo.common.MIMath; import org.meteoinfo.table.ColumnData; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataRange.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataRange.java index 356940c3..00071c6a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataRange.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/DataRange.java @@ -1,96 +1,96 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import org.meteoinfo.global.MIMath; - -/** - * - * @author wyq - */ -public class DataRange { - // - private double min; - private double max; - // - // - /** - * Constructor - */ - public DataRange(){ - - } - - /** - * Constructor - * @param min Minimum value - * @param max Maximum value - */ - public DataRange(double min, double max){ - this.min = min; - this.max = max; - } - - /** - * Constructor - * @param value Data value - */ - public DataRange(double value){ - this.min = value; - this.max = value; - } - // - // - /** - * Get minimum value - * @return Minimum value - */ - public double getMin(){ - return this.min; - } - - /** - * Set minimum value - * @param value Minimum value - */ - public void setMin(double value){ - this.min = value; - } - - /** - * Get maximum value - * @return Maximum value - */ - public double getMax(){ - return this.max; - } - - /** - * Set maximum value - * @param value Maximum value - */ - public void setMax(double value) { - this.max = value; - } - // - // - /** - * Get data range - * @return Data range - */ - public double getRange(){ - return this.max - this.min; - } - - /** - * Get if the data range is zero - * @return Boolean - */ - public boolean isFixed(){ - return MIMath.doubleEquals(max, min); - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import org.meteoinfo.common.MIMath; + +/** + * + * @author wyq + */ +public class DataRange { + // + private double min; + private double max; + // + // + /** + * Constructor + */ + public DataRange(){ + + } + + /** + * Constructor + * @param min Minimum value + * @param max Maximum value + */ + public DataRange(double min, double max){ + this.min = min; + this.max = max; + } + + /** + * Constructor + * @param value Data value + */ + public DataRange(double value){ + this.min = value; + this.max = value; + } + // + // + /** + * Get minimum value + * @return Minimum value + */ + public double getMin(){ + return this.min; + } + + /** + * Set minimum value + * @param value Minimum value + */ + public void setMin(double value){ + this.min = value; + } + + /** + * Get maximum value + * @return Maximum value + */ + public double getMax(){ + return this.max; + } + + /** + * Set maximum value + * @param value Maximum value + */ + public void setMax(double value) { + this.max = value; + } + // + // + /** + * Get data range + * @return Data range + */ + public double getRange(){ + return this.max - this.min; + } + + /** + * Get if the data range is zero + * @return Boolean + */ + public boolean isFixed(){ + return MIMath.doubleEquals(max, min); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java index 31bab42f..916f4f9e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java @@ -13,16 +13,13 @@ */ package org.meteoinfo.data; -import org.meteoinfo.math.ArrayUtil; -import org.meteoinfo.math.ArrayMath; import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; @@ -31,6 +28,10 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.*; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.data.meteodata.GridDataSetting; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java index ad5dcfa2..852042ac 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java @@ -14,10 +14,12 @@ package org.meteoinfo.data; import java.io.BufferedReader; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; + import java.io.BufferedWriter; import java.io.DataOutputStream; import java.io.File; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/SeriesUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/SeriesUtil.java index 71ebee42..36781bab 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/SeriesUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/SeriesUtil.java @@ -1,164 +1,165 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import org.meteoinfo.math.ArrayMath; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import org.meteoinfo.ndarray.Array; - -/** - * - * @author Yaqiang Wang - */ -public class SeriesUtil { - - /** - * Get indices - * @param index Index array - * @param labels Labels - * @return Indices - */ - public static Object[] getIndices(List index, Array labels) { - return getIndices(index, ArrayMath.asList(labels)); - } - - /** - * Get indices - * @param index Index array - * @param labels Labels - * @return Indices - */ - public static Object[] getIndices(Array index, Array labels) { - return getIndices(ArrayMath.asList(index), ArrayMath.asList(labels)); - } - - /** - * Get indices - * @param index Index array - * @param labels Labels - * @return Indices - */ - public static Object[] getIndices(List index, List labels) { - List r = new ArrayList<>(); - List rIndex = new ArrayList<>(); - List rData = new ArrayList<>(); - List rrIndex = new ArrayList<>(); - Object[] rr; - List r1; - List rIndex1; - for (Object l : labels){ - rr = getIndices(index, l); - r1 = (ArrayList)rr[0]; - rIndex1 = (ArrayList)rr[1]; - if (r1.isEmpty()){ - rData.add(0); - rrIndex.add(l); - } else { - r.addAll(r1); - rIndex.addAll(rIndex1); - for (Iterator it = r1.iterator(); it.hasNext();) { - it.next(); - rData.add(1); - rrIndex.add(l); - } - } - } - - return new Object[]{r, rIndex, rData, rrIndex}; - } - - /** - * Get indices - * @param index Index array - * @param label Label - * @return Indices - */ - public static Object[] getIndices(List index, Object label) { - List r = new ArrayList<>(); - List rIndex = new ArrayList<>(); - for (int i = 0; i < index.size(); i++){ - if (index.get(i).equals(label)){ - r.add(i); - rIndex.add(index.get(i)); - } - } - - return new Object[]{r, rIndex}; - } - - /** - * Sub list by index - * @param list The list - * @param index The index - * @return Result list - */ - public static List subList(List list, List index){ - List r = new ArrayList<>(); - for (int i : index){ - r.add(list.get(i)); - } - - return r; - } - -// /** -// * Fill key list -// * @param data Valid data array -// * @param rrdata Result data flags -// * @return Result data array with same length as key list -// */ -// public static Array fillKeyList(Array data, List rrdata){ -// Array kdata = Array.factory(data.getDataType(), new int[]{rrdata.size()}); -// Object nanObj = null; -// switch (data.getDataType()){ -// case FLOAT: -// nanObj = Float.NaN; -// break; -// case DOUBLE: -// nanObj = Double.NaN; -// break; -// } -// int idx = 0; -// int i = 0; -// for (int f : rrdata){ -// if (f == 0) -// kdata.setObject(i, nanObj); -// else { -// kdata.setObject(i, data.getObject(idx)); -// idx += 1; -// } -// i += 1; -// } -// -// return kdata; -// } - - /** - * Fill key list - * @param data Valid data array - * @param rrdata Result data flags - * @return Result data array with same length as key list - */ - public static Array fillKeyList(Array data, List rrdata){ - Array kdata = Array.factory(data.getDataType(), new int[]{rrdata.size()}); - int idx = 0; - int i = 0; - for (int f : rrdata){ - if (f == 0) - kdata.setObject(i, Double.NaN); - else { - kdata.setObject(i, data.getObject(idx)); - idx += 1; - } - i += 1; - } - - return kdata; - } - -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.ndarray.Array; + +/** + * + * @author Yaqiang Wang + */ +public class SeriesUtil { + + /** + * Get indices + * @param index Index array + * @param labels Labels + * @return Indices + */ + public static Object[] getIndices(List index, Array labels) { + return getIndices(index, ArrayMath.asList(labels)); + } + + /** + * Get indices + * @param index Index array + * @param labels Labels + * @return Indices + */ + public static Object[] getIndices(Array index, Array labels) { + return getIndices(ArrayMath.asList(index), ArrayMath.asList(labels)); + } + + /** + * Get indices + * @param index Index array + * @param labels Labels + * @return Indices + */ + public static Object[] getIndices(List index, List labels) { + List r = new ArrayList<>(); + List rIndex = new ArrayList<>(); + List rData = new ArrayList<>(); + List rrIndex = new ArrayList<>(); + Object[] rr; + List r1; + List rIndex1; + for (Object l : labels){ + rr = getIndices(index, l); + r1 = (ArrayList)rr[0]; + rIndex1 = (ArrayList)rr[1]; + if (r1.isEmpty()){ + rData.add(0); + rrIndex.add(l); + } else { + r.addAll(r1); + rIndex.addAll(rIndex1); + for (Iterator it = r1.iterator(); it.hasNext();) { + it.next(); + rData.add(1); + rrIndex.add(l); + } + } + } + + return new Object[]{r, rIndex, rData, rrIndex}; + } + + /** + * Get indices + * @param index Index array + * @param label Label + * @return Indices + */ + public static Object[] getIndices(List index, Object label) { + List r = new ArrayList<>(); + List rIndex = new ArrayList<>(); + for (int i = 0; i < index.size(); i++){ + if (index.get(i).equals(label)){ + r.add(i); + rIndex.add(index.get(i)); + } + } + + return new Object[]{r, rIndex}; + } + + /** + * Sub list by index + * @param list The list + * @param index The index + * @return Result list + */ + public static List subList(List list, List index){ + List r = new ArrayList<>(); + for (int i : index){ + r.add(list.get(i)); + } + + return r; + } + +// /** +// * Fill key list +// * @param data Valid data array +// * @param rrdata Result data flags +// * @return Result data array with same length as key list +// */ +// public static Array fillKeyList(Array data, List rrdata){ +// Array kdata = Array.factory(data.getDataType(), new int[]{rrdata.size()}); +// Object nanObj = null; +// switch (data.getDataType()){ +// case FLOAT: +// nanObj = Float.NaN; +// break; +// case DOUBLE: +// nanObj = Double.NaN; +// break; +// } +// int idx = 0; +// int i = 0; +// for (int f : rrdata){ +// if (f == 0) +// kdata.setObject(i, nanObj); +// else { +// kdata.setObject(i, data.getObject(idx)); +// idx += 1; +// } +// i += 1; +// } +// +// return kdata; +// } + + /** + * Fill key list + * @param data Valid data array + * @param rrdata Result data flags + * @return Result data array with same length as key list + */ + public static Array fillKeyList(Array data, List rrdata){ + Array kdata = Array.factory(data.getDataType(), new int[]{rrdata.size()}); + int idx = 0; + int i = 0; + for (int f : rrdata){ + if (f == 0) + kdata.setObject(i, Double.NaN); + else { + kdata.setObject(i, data.getObject(idx)); + idx += 1; + } + i += 1; + } + + return kdata; + } + +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationData.java index 967b9941..8df35d0b 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationData.java @@ -17,17 +17,19 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.data.meteodata.GridDataSetting; import org.meteoinfo.geoprocess.analysis.InterpolationSetting; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.meteoinfo.geoprocess.GeoComputation; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.PointD; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.projection.Reproject; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationTableData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationTableData.java index 2caf2b0d..ef0cb830 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationTableData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/StationTableData.java @@ -1,202 +1,203 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JOptionPane; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.info.ProjectionInfo; - -/** - * - * @author yaqiang - */ -public class StationTableData extends TableData{ - // - private ProjectionInfo projInfo; - private int stIdx; - private int lonIdx; - private int latIdx; - // - // - /** - * Constructor - */ - public StationTableData(){ - this.projInfo = KnownCoordinateSystems.geographic.world.WGS1984; - stIdx = 0; - lonIdx = 1; - latIdx = 2; - } - // - // - /** - * Get projection info - * @return Projection info - */ - public ProjectionInfo getProjectionInfo(){ - return this.projInfo; - } - - /** - * Set projection info - * @param value Projection info - */ - public void setProjectionInfo(ProjectionInfo value){ - this.projInfo = value; - } - - /** - * Get station column index - * @return Station column index - */ - public int getStationIndex(){ - return this.stIdx; - } - - /** - * Set station column index - * @param value Statin column index - */ - public void setStationIndex(int value){ - this.stIdx = value; - } - - /** - * Get longitude column index - * @return Longitude column index - */ - public int getLonIndex(){ - return this.lonIdx; - } - - /** - * Set longitude column index - * @param value Longitude column index - */ - public void setLonIndex(int value){ - this.latIdx = value; - } - - /** - * Get latitude column index - * @return Latitude column index - */ - public int getLatIndex(){ - return this.latIdx; - } - - /** - * Set Latitude column index - * @param value Latitude column index - */ - public void setLatIndex(int value){ - this.lonIdx = value; - } - // - // - /** - * Read data table from ASCII file - * - * @param fileName File name - * @param lonIdx Longitude index - * @param latIdx Latitude index - * @throws java.io.FileNotFoundException - */ - public void readASCIIFile(String fileName, int lonIdx, int latIdx) throws FileNotFoundException, IOException, Exception { - this.readASCIIFile(fileName, 0, lonIdx, latIdx); - } - - /** - * Read data table from ASCII file - * - * @param fileName File name - * @param stIdx Station column index - * @param lonIdx Longitude column index - * @param latIdx Latitude column index - * @throws java.io.FileNotFoundException - */ - public void readASCIIFile(String fileName, int stIdx, int lonIdx, int latIdx) throws FileNotFoundException, IOException, Exception { - this.lonIdx = lonIdx; - this.latIdx = latIdx; - //DataTable dTable = new DataTable(); - - BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "utf-8")); - String title = sr.readLine().trim(); - //Determine separator - String separator = GlobalUtil.getDelimiter(title); - String[] titleArray = GlobalUtil.split(title, separator); - if (titleArray.length < 2) { - JOptionPane.showMessageDialog(null, "File Format Error!"); - sr.close(); - } else { - //Get fields - List dataIdxs = new ArrayList<>(); - String fieldName; - for (int i = 0; i < titleArray.length; i++) { - fieldName = titleArray[i]; - if (i == lonIdx || i == latIdx) - this.addColumn(fieldName, DataType.FLOAT); - else - this.addColumn(fieldName, DataType.STRING); - dataIdxs.add(i); - } - - String[] dataArray; - int rn = 0; - String line = sr.readLine(); - while (line != null) { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - dataArray = GlobalUtil.split(line, separator); - this.addRow(); - int cn = 0; - for (int idx : dataIdxs) { - if (idx == lonIdx || idx == latIdx) - this.setValue(rn, cn, Float.parseFloat(dataArray[idx])); - else - this.setValue(rn, cn, dataArray[idx]); - cn++; - } - - rn += 1; - line = sr.readLine(); - } - - //dataTable = dTable; - sr.close(); - } - } - - /** - * Clone - * @return Cloned StationTableData object - */ - @Override - public Object clone(){ - StationTableData std = new StationTableData(); - std = (StationTableData)super.clone(); - //std.dataTable = (DataTable)this.dataTable.clone(); - std.missingValue = this.missingValue; - std.projInfo = this.projInfo; - std.stIdx = this.stIdx; - std.lonIdx = this.lonIdx; - std.latIdx = this.latIdx; - - return std; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JOptionPane; + +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.ndarray.DataType; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.info.ProjectionInfo; + +/** + * + * @author yaqiang + */ +public class StationTableData extends TableData{ + // + private ProjectionInfo projInfo; + private int stIdx; + private int lonIdx; + private int latIdx; + // + // + /** + * Constructor + */ + public StationTableData(){ + this.projInfo = KnownCoordinateSystems.geographic.world.WGS1984; + stIdx = 0; + lonIdx = 1; + latIdx = 2; + } + // + // + /** + * Get projection info + * @return Projection info + */ + public ProjectionInfo getProjectionInfo(){ + return this.projInfo; + } + + /** + * Set projection info + * @param value Projection info + */ + public void setProjectionInfo(ProjectionInfo value){ + this.projInfo = value; + } + + /** + * Get station column index + * @return Station column index + */ + public int getStationIndex(){ + return this.stIdx; + } + + /** + * Set station column index + * @param value Statin column index + */ + public void setStationIndex(int value){ + this.stIdx = value; + } + + /** + * Get longitude column index + * @return Longitude column index + */ + public int getLonIndex(){ + return this.lonIdx; + } + + /** + * Set longitude column index + * @param value Longitude column index + */ + public void setLonIndex(int value){ + this.latIdx = value; + } + + /** + * Get latitude column index + * @return Latitude column index + */ + public int getLatIndex(){ + return this.latIdx; + } + + /** + * Set Latitude column index + * @param value Latitude column index + */ + public void setLatIndex(int value){ + this.lonIdx = value; + } + // + // + /** + * Read data table from ASCII file + * + * @param fileName File name + * @param lonIdx Longitude index + * @param latIdx Latitude index + * @throws java.io.FileNotFoundException + */ + public void readASCIIFile(String fileName, int lonIdx, int latIdx) throws FileNotFoundException, IOException, Exception { + this.readASCIIFile(fileName, 0, lonIdx, latIdx); + } + + /** + * Read data table from ASCII file + * + * @param fileName File name + * @param stIdx Station column index + * @param lonIdx Longitude column index + * @param latIdx Latitude column index + * @throws java.io.FileNotFoundException + */ + public void readASCIIFile(String fileName, int stIdx, int lonIdx, int latIdx) throws FileNotFoundException, IOException, Exception { + this.lonIdx = lonIdx; + this.latIdx = latIdx; + //DataTable dTable = new DataTable(); + + BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "utf-8")); + String title = sr.readLine().trim(); + //Determine separator + String separator = GlobalUtil.getDelimiter(title); + String[] titleArray = GlobalUtil.split(title, separator); + if (titleArray.length < 2) { + JOptionPane.showMessageDialog(null, "File Format Error!"); + sr.close(); + } else { + //Get fields + List dataIdxs = new ArrayList<>(); + String fieldName; + for (int i = 0; i < titleArray.length; i++) { + fieldName = titleArray[i]; + if (i == lonIdx || i == latIdx) + this.addColumn(fieldName, DataType.FLOAT); + else + this.addColumn(fieldName, DataType.STRING); + dataIdxs.add(i); + } + + String[] dataArray; + int rn = 0; + String line = sr.readLine(); + while (line != null) { + line = line.trim(); + if (line.isEmpty()) { + continue; + } + dataArray = GlobalUtil.split(line, separator); + this.addRow(); + int cn = 0; + for (int idx : dataIdxs) { + if (idx == lonIdx || idx == latIdx) + this.setValue(rn, cn, Float.parseFloat(dataArray[idx])); + else + this.setValue(rn, cn, dataArray[idx]); + cn++; + } + + rn += 1; + line = sr.readLine(); + } + + //dataTable = dTable; + sr.close(); + } + } + + /** + * Clone + * @return Cloned StationTableData object + */ + @Override + public Object clone(){ + StationTableData std = new StationTableData(); + std = (StationTableData)super.clone(); + //std.dataTable = (DataTable)this.dataTable.clone(); + std.missingValue = this.missingValue; + std.projInfo = this.projInfo; + std.stIdx = this.stIdx; + std.lonIdx = this.lonIdx; + std.latIdx = this.latIdx; + + return std; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableData.java index 30b9dca1..130ba93c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableData.java @@ -26,9 +26,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.JOptionPane; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.analysis.Statistics; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataRow; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableUtil.java index 76759ed0..68659b78 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TableUtil.java @@ -15,8 +15,9 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; + +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.analysis.Statistics; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataRow; import org.meteoinfo.table.DataTable; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TimeTableData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TimeTableData.java index b8179fe1..73749c7e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/TimeTableData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/TimeTableData.java @@ -17,11 +17,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.JOptionPane; + +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.analysis.Statistics; import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataRow; import org.meteoinfo.table.DataTable; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.ndarray.DataType; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYArrayDataset.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYArrayDataset.java index b4332f19..9ff10728 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYArrayDataset.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYArrayDataset.java @@ -1,342 +1,343 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; - -/** - * - * @author wyq - */ -public class XYArrayDataset extends XYDataset { - - // - - private final double[][] xValues; - private final double[][] yValues; - private final int seriesCount; - private final int itemCount; - private String[] seriesKeys; - - // - // - - /** - * Constructor - * - * @param seriesNum Series number - * @param itemNum Item number - */ - public XYArrayDataset(int seriesNum, int itemNum) { - this.seriesCount = seriesNum; - this.itemCount = itemNum; - xValues = new double[seriesNum][itemNum]; - yValues = new double[seriesNum][itemNum]; - seriesKeys = new String[seriesNum]; - } - - /** - * Constructor - * - * @param xdata X station data - * @param ydata Y station data - * @param seriesKey Series key - */ - public XYArrayDataset(StationData xdata, StationData ydata, String seriesKey) { - List vdata = new ArrayList<>(); - double v1, v2; - for (int i = 0; i < xdata.getStNum(); i++) { - v1 = xdata.getValue(i); - if (MIMath.doubleEquals(v1, xdata.missingValue)) { - continue; - } - v2 = ydata.getValue(i); - if (MIMath.doubleEquals(v2, ydata.missingValue)) { - continue; - } - vdata.add(new double[]{v1, v2}); - } - seriesCount = 1; - seriesKeys = new String[seriesCount]; - seriesKeys[0] = seriesKey; - itemCount = vdata.size(); - xValues = new double[seriesCount][itemCount]; - yValues = new double[seriesCount][itemCount]; - for (int i = 0; i < seriesCount; i++) { - for (int j = 0; j < itemCount; j++) { - xValues[i][j] = vdata.get(j)[0]; - yValues[i][j] = vdata.get(j)[1]; - } - } - } - - /** - * Constructor - * - * @param xdata X data - * @param ydata Y data - * @param seriesKey Series key - */ - public XYArrayDataset(List xdata, List ydata, String seriesKey) { - List nxdata = new ArrayList<>(); - List nydata = new ArrayList<>(); - for (int i = 0; i < xdata.size(); i++) { - nxdata.add(Double.parseDouble(xdata.get(i).toString())); - nydata.add(Double.parseDouble(ydata.get(i).toString())); - } - - List vdata = new ArrayList<>(); - double v1, v2; - for (int i = 0; i < xdata.size(); i++) { - v1 = nxdata.get(i); - v2 = nydata.get(i); - vdata.add(new double[]{v1, v2}); - } - seriesCount = 1; - seriesKeys = new String[seriesCount]; - seriesKeys[0] = seriesKey; - itemCount = vdata.size(); - xValues = new double[seriesCount][itemCount]; - yValues = new double[seriesCount][itemCount]; - for (int i = 0; i < seriesCount; i++) { - for (int j = 0; j < itemCount; j++) { - xValues[i][j] = vdata.get(j)[0]; - yValues[i][j] = vdata.get(j)[1]; - } - } - } - - // - // - - /** - * Get series count - * @return Series count - */ - @Override - public int getSeriesCount() { - return this.seriesCount; - } - - /** - * Get series key by index - * @param seriesIdx Series index - * @return Series key - */ - @Override - public String getSeriesKey(int seriesIdx) { - return seriesKeys[seriesIdx]; - } - - /** - * Set series key by index - * @param seriesIdx Series index - * @param seriesKey Series key - */ - @Override - public void setSeriesKey(int seriesIdx, String seriesKey){ - this.seriesKeys[seriesIdx] = seriesKey; - } - - /** - * Get item count - * @return Item count - */ - @Override - public int getItemCount() { - return this.itemCount; - } - - /** - * Get item count - * @param seriesIdx Series index - * @return Item count - */ - @Override - public int getItemCount(int seriesIdx){ - return this.itemCount; - } - - /** - * Get x values - * @param seriesIdx Series index - * @return X values - */ - @Override - public double[] getXValues(int seriesIdx){ - return this.xValues[seriesIdx]; - } - - /** - * Get y values - * @param seriesIdx Series index - * @return Y values - */ - @Override - public double[] getYValues(int seriesIdx){ - return this.yValues[seriesIdx]; - } - - /** - * Get x value - * @param seriesIdx Series index - * @param itemIdx Item index - * @return X value - */ - @Override - public double getX(int seriesIdx, int itemIdx) { - return xValues[seriesIdx][itemIdx]; - } - - /** - * Set x value - * @param seriesIdx Series index - * @param itemIdx Item index - * @param value X value - */ - @Override - public void setX(int seriesIdx, int itemIdx, double value){ - xValues[seriesIdx][itemIdx] = value; - } - - /** - * Get Y value - * @param seriesIdx Series index - * @param itemIdx Item index - * @return Y value - */ - @Override - public double getY(int seriesIdx, int itemIdx) { - return yValues[seriesIdx][itemIdx]; - } - - /** - * Set Y value - * @param seriesIdx Series index - * @param itemIdx Item index - * @param value Y value - */ - @Override - public void setY(int seriesIdx, int itemIdx, double value){ - yValues[seriesIdx][itemIdx] = value; - } - - /** - * Get series keys - * @return Series keys - */ - @Override - public List getSeriesKeys(){ - return Arrays.asList(this.seriesKeys); - } - - /** - * Set series keys - * @param value Series keys - */ - public void setSeriesKeys(String[] value){ - this.seriesKeys = value; - } - - /** - * Set series keys - * @param value Series keys - */ - @Override - public void setSeriesKeys(List value){ - this.seriesKeys = (String[])value.toArray(new String[value.size()]); - } - - // - // - - /** - * Get data extent - * @return Data extent - */ - @Override - public Extent getDataExtent() { - Extent cET = new Extent(); - double x, y; - int n = 0; - for (int i = 0; i < this.seriesCount; i++) { - for (int j = 0; j < this.itemCount; j++) { - x = xValues[i][j]; - y = yValues[i][j]; - if (MIMath.doubleEquals(y, this.getMissingValue()) || MIMath.doubleEquals(x, this.getMissingValue())) - continue; - if (n == 0) { - cET.minX = x; - cET.maxX = x; - cET.minY = y; - cET.maxY = y; - } else { - if (cET.minX > x) { - cET.minX = x; - } else if (cET.maxX < x) { - cET.maxX = x; - } - - if (cET.minY > y) { - cET.minY = y; - } else if (cET.maxY < y) { - cET.maxY = y; - } - } - n ++; - } - } - - return cET; - } - - /** - * Select data points - * @param extent Selection extent - * @return Selected data points - */ - @Override - public List selectPoints(Extent extent){ - List selIdxs = new ArrayList(); - double x, y; - for (int i = 0; i < this.seriesCount; i++){ - for (int j = 0; j < this.itemCount; j++){ - x = this.getX(i, j); - if (x >= extent.minX && x <= extent.maxX){ - y = this.getY(i, j); - if (y >= extent.minY && y <= extent.maxY){ - selIdxs.add(new int[]{i, j}); - } - } - } - } - - return selIdxs; - } - - /** - * Get missing value index list - * @param seriesIdx Series index - * @return Missing value index list - */ - @Override - public List getMissingValueIndex(int seriesIdx){ - List mvidx = new ArrayList(); - double[] xvs = this.getXValues(seriesIdx); - double[] yvs = this.getYValues(seriesIdx); - for (int i = 0; i < this.itemCount; i++){ - if (MIMath.doubleEquals(xvs[i], this.getMissingValue()) || MIMath.doubleEquals(yvs[i], this.getMissingValue())) - mvidx.add(i); - } - - return mvidx; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author wyq + */ +public class XYArrayDataset extends XYDataset { + + // + + private final double[][] xValues; + private final double[][] yValues; + private final int seriesCount; + private final int itemCount; + private String[] seriesKeys; + + // + // + + /** + * Constructor + * + * @param seriesNum Series number + * @param itemNum Item number + */ + public XYArrayDataset(int seriesNum, int itemNum) { + this.seriesCount = seriesNum; + this.itemCount = itemNum; + xValues = new double[seriesNum][itemNum]; + yValues = new double[seriesNum][itemNum]; + seriesKeys = new String[seriesNum]; + } + + /** + * Constructor + * + * @param xdata X station data + * @param ydata Y station data + * @param seriesKey Series key + */ + public XYArrayDataset(StationData xdata, StationData ydata, String seriesKey) { + List vdata = new ArrayList<>(); + double v1, v2; + for (int i = 0; i < xdata.getStNum(); i++) { + v1 = xdata.getValue(i); + if (MIMath.doubleEquals(v1, xdata.missingValue)) { + continue; + } + v2 = ydata.getValue(i); + if (MIMath.doubleEquals(v2, ydata.missingValue)) { + continue; + } + vdata.add(new double[]{v1, v2}); + } + seriesCount = 1; + seriesKeys = new String[seriesCount]; + seriesKeys[0] = seriesKey; + itemCount = vdata.size(); + xValues = new double[seriesCount][itemCount]; + yValues = new double[seriesCount][itemCount]; + for (int i = 0; i < seriesCount; i++) { + for (int j = 0; j < itemCount; j++) { + xValues[i][j] = vdata.get(j)[0]; + yValues[i][j] = vdata.get(j)[1]; + } + } + } + + /** + * Constructor + * + * @param xdata X data + * @param ydata Y data + * @param seriesKey Series key + */ + public XYArrayDataset(List xdata, List ydata, String seriesKey) { + List nxdata = new ArrayList<>(); + List nydata = new ArrayList<>(); + for (int i = 0; i < xdata.size(); i++) { + nxdata.add(Double.parseDouble(xdata.get(i).toString())); + nydata.add(Double.parseDouble(ydata.get(i).toString())); + } + + List vdata = new ArrayList<>(); + double v1, v2; + for (int i = 0; i < xdata.size(); i++) { + v1 = nxdata.get(i); + v2 = nydata.get(i); + vdata.add(new double[]{v1, v2}); + } + seriesCount = 1; + seriesKeys = new String[seriesCount]; + seriesKeys[0] = seriesKey; + itemCount = vdata.size(); + xValues = new double[seriesCount][itemCount]; + yValues = new double[seriesCount][itemCount]; + for (int i = 0; i < seriesCount; i++) { + for (int j = 0; j < itemCount; j++) { + xValues[i][j] = vdata.get(j)[0]; + yValues[i][j] = vdata.get(j)[1]; + } + } + } + + // + // + + /** + * Get series count + * @return Series count + */ + @Override + public int getSeriesCount() { + return this.seriesCount; + } + + /** + * Get series key by index + * @param seriesIdx Series index + * @return Series key + */ + @Override + public String getSeriesKey(int seriesIdx) { + return seriesKeys[seriesIdx]; + } + + /** + * Set series key by index + * @param seriesIdx Series index + * @param seriesKey Series key + */ + @Override + public void setSeriesKey(int seriesIdx, String seriesKey){ + this.seriesKeys[seriesIdx] = seriesKey; + } + + /** + * Get item count + * @return Item count + */ + @Override + public int getItemCount() { + return this.itemCount; + } + + /** + * Get item count + * @param seriesIdx Series index + * @return Item count + */ + @Override + public int getItemCount(int seriesIdx){ + return this.itemCount; + } + + /** + * Get x values + * @param seriesIdx Series index + * @return X values + */ + @Override + public double[] getXValues(int seriesIdx){ + return this.xValues[seriesIdx]; + } + + /** + * Get y values + * @param seriesIdx Series index + * @return Y values + */ + @Override + public double[] getYValues(int seriesIdx){ + return this.yValues[seriesIdx]; + } + + /** + * Get x value + * @param seriesIdx Series index + * @param itemIdx Item index + * @return X value + */ + @Override + public double getX(int seriesIdx, int itemIdx) { + return xValues[seriesIdx][itemIdx]; + } + + /** + * Set x value + * @param seriesIdx Series index + * @param itemIdx Item index + * @param value X value + */ + @Override + public void setX(int seriesIdx, int itemIdx, double value){ + xValues[seriesIdx][itemIdx] = value; + } + + /** + * Get Y value + * @param seriesIdx Series index + * @param itemIdx Item index + * @return Y value + */ + @Override + public double getY(int seriesIdx, int itemIdx) { + return yValues[seriesIdx][itemIdx]; + } + + /** + * Set Y value + * @param seriesIdx Series index + * @param itemIdx Item index + * @param value Y value + */ + @Override + public void setY(int seriesIdx, int itemIdx, double value){ + yValues[seriesIdx][itemIdx] = value; + } + + /** + * Get series keys + * @return Series keys + */ + @Override + public List getSeriesKeys(){ + return Arrays.asList(this.seriesKeys); + } + + /** + * Set series keys + * @param value Series keys + */ + public void setSeriesKeys(String[] value){ + this.seriesKeys = value; + } + + /** + * Set series keys + * @param value Series keys + */ + @Override + public void setSeriesKeys(List value){ + this.seriesKeys = (String[])value.toArray(new String[value.size()]); + } + + // + // + + /** + * Get data extent + * @return Data extent + */ + @Override + public Extent getDataExtent() { + Extent cET = new Extent(); + double x, y; + int n = 0; + for (int i = 0; i < this.seriesCount; i++) { + for (int j = 0; j < this.itemCount; j++) { + x = xValues[i][j]; + y = yValues[i][j]; + if (MIMath.doubleEquals(y, this.getMissingValue()) || MIMath.doubleEquals(x, this.getMissingValue())) + continue; + if (n == 0) { + cET.minX = x; + cET.maxX = x; + cET.minY = y; + cET.maxY = y; + } else { + if (cET.minX > x) { + cET.minX = x; + } else if (cET.maxX < x) { + cET.maxX = x; + } + + if (cET.minY > y) { + cET.minY = y; + } else if (cET.maxY < y) { + cET.maxY = y; + } + } + n ++; + } + } + + return cET; + } + + /** + * Select data points + * @param extent Selection extent + * @return Selected data points + */ + @Override + public List selectPoints(Extent extent){ + List selIdxs = new ArrayList(); + double x, y; + for (int i = 0; i < this.seriesCount; i++){ + for (int j = 0; j < this.itemCount; j++){ + x = this.getX(i, j); + if (x >= extent.minX && x <= extent.maxX){ + y = this.getY(i, j); + if (y >= extent.minY && y <= extent.maxY){ + selIdxs.add(new int[]{i, j}); + } + } + } + } + + return selIdxs; + } + + /** + * Get missing value index list + * @param seriesIdx Series index + * @return Missing value index list + */ + @Override + public List getMissingValueIndex(int seriesIdx){ + List mvidx = new ArrayList(); + double[] xvs = this.getXValues(seriesIdx); + double[] yvs = this.getYValues(seriesIdx); + for (int i = 0; i < this.itemCount; i++){ + if (MIMath.doubleEquals(xvs[i], this.getMissingValue()) || MIMath.doubleEquals(yvs[i], this.getMissingValue())) + mvidx.add(i); + } + + return mvidx; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYDataset.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYDataset.java index db1936dd..12a741a0 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYDataset.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYDataset.java @@ -1,155 +1,156 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import java.util.List; -import org.meteoinfo.global.Extent; - -/** - * - * @author yaqiang - */ -public abstract class XYDataset extends Dataset{ - - private double missingValue = -9999.0; - - /** - * Get missing value - * @return Missing value - */ - public double getMissingValue(){ - return this.missingValue; - } - - /** - * Set missing value - * @param value Missing value - */ - public void setMissingValue(double value){ - this.missingValue = value; - } - - /** - * Get dataset type - * @return Dataset type - */ - @Override - public DatasetType getDatasetType() { - return DatasetType.XY; - } - - /** - * Get series count - * @return Series count - */ - public abstract int getSeriesCount(); - - /** - * Get item count - * @return Item count - */ - public abstract int getItemCount(); - - /** - * Get item count by series index - * @param seriesIdx Series index - * @return Item count - */ - public abstract int getItemCount(int seriesIdx); - - /** - * Get x value - * @param seriesIdx Series index - * @param itemIdx Item index - * @return X value - */ - public abstract double getX(int seriesIdx, int itemIdx); - - /** - * Get y value - * @param seriesIdx Series index - * @param itemIdx Item index - * @return Y value - */ - public abstract double getY(int seriesIdx, int itemIdx); - - /** - * Set x value - * @param seriesIdx Series index - * @param itemIdx Item index - * @param value X value - */ - public abstract void setX(int seriesIdx, int itemIdx, double value); - - /** - * Set y value - * @param seriesIdx Series index - * @param itemIdx Item index - * @param value Y value - */ - public abstract void setY(int seriesIdx, int itemIdx, double value); - - /** - * Get x values - * @param seriesIdx Series index - * @return X values - */ - public abstract double[] getXValues(int seriesIdx); - - /** - * Get y values - * @param seriesIdx Series index - * @return Y values - */ - public abstract double[] getYValues(int seriesIdx); - - /** - * Get series key by index - * @param seriesIdx Series index - * @return Series key - */ - public abstract String getSeriesKey(int seriesIdx); - - /** - * Set series key by index - * @param seriesIdx Series index - * @param seriesKey Series key - */ - public abstract void setSeriesKey(int seriesIdx, String seriesKey); - - /** - * Get series keys - * @return Series keys - */ - public abstract List getSeriesKeys(); - - /** - * Set series keys - * @param keys Keys - */ - public abstract void setSeriesKeys(List keys); - - /** - * Get data extent - * @return Data extent - */ - public abstract Extent getDataExtent(); - - /** - * Get missing value index list - * @param seriesIdx Series index - * @return Missing value index list - */ - public abstract List getMissingValueIndex(int seriesIdx); - - /** - * Select data points - * @param extent Selection extent - * @return Selected data points - */ - public abstract List selectPoints(Extent extent); - -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import org.meteoinfo.common.Extent; + +import java.util.List; + +/** + * + * @author yaqiang + */ +public abstract class XYDataset extends Dataset{ + + private double missingValue = -9999.0; + + /** + * Get missing value + * @return Missing value + */ + public double getMissingValue(){ + return this.missingValue; + } + + /** + * Set missing value + * @param value Missing value + */ + public void setMissingValue(double value){ + this.missingValue = value; + } + + /** + * Get dataset type + * @return Dataset type + */ + @Override + public DatasetType getDatasetType() { + return DatasetType.XY; + } + + /** + * Get series count + * @return Series count + */ + public abstract int getSeriesCount(); + + /** + * Get item count + * @return Item count + */ + public abstract int getItemCount(); + + /** + * Get item count by series index + * @param seriesIdx Series index + * @return Item count + */ + public abstract int getItemCount(int seriesIdx); + + /** + * Get x value + * @param seriesIdx Series index + * @param itemIdx Item index + * @return X value + */ + public abstract double getX(int seriesIdx, int itemIdx); + + /** + * Get y value + * @param seriesIdx Series index + * @param itemIdx Item index + * @return Y value + */ + public abstract double getY(int seriesIdx, int itemIdx); + + /** + * Set x value + * @param seriesIdx Series index + * @param itemIdx Item index + * @param value X value + */ + public abstract void setX(int seriesIdx, int itemIdx, double value); + + /** + * Set y value + * @param seriesIdx Series index + * @param itemIdx Item index + * @param value Y value + */ + public abstract void setY(int seriesIdx, int itemIdx, double value); + + /** + * Get x values + * @param seriesIdx Series index + * @return X values + */ + public abstract double[] getXValues(int seriesIdx); + + /** + * Get y values + * @param seriesIdx Series index + * @return Y values + */ + public abstract double[] getYValues(int seriesIdx); + + /** + * Get series key by index + * @param seriesIdx Series index + * @return Series key + */ + public abstract String getSeriesKey(int seriesIdx); + + /** + * Set series key by index + * @param seriesIdx Series index + * @param seriesKey Series key + */ + public abstract void setSeriesKey(int seriesIdx, String seriesKey); + + /** + * Get series keys + * @return Series keys + */ + public abstract List getSeriesKeys(); + + /** + * Set series keys + * @param keys Keys + */ + public abstract void setSeriesKeys(List keys); + + /** + * Get data extent + * @return Data extent + */ + public abstract Extent getDataExtent(); + + /** + * Get missing value index list + * @param seriesIdx Series index + * @return Missing value index list + */ + public abstract List getMissingValueIndex(int seriesIdx); + + /** + * Select data points + * @param extent Selection extent + * @return Selected data points + */ + public abstract List selectPoints(Extent extent); + +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYListDataset.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYListDataset.java index e8f7fe1c..258dcb5a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYListDataset.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYListDataset.java @@ -1,443 +1,444 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.ndarray.Array; - -/** - * - * @author wyq - */ -public class XYListDataset extends XYDataset { - // - //private List xValues; - //private List yValues; - //private List seriesKeys; - private List dataset; - // - // - /** - * Constructor - */ - public XYListDataset(){ - //xValues = new ArrayList<>(); - //yValues = new ArrayList<>(); - //seriesKeys = new ArrayList<>(); - dataset = new ArrayList<>(); - } - - /** - * Constructor - * - * @param seriesNum Series number - * @param itemNum Item number - */ - public XYListDataset(int seriesNum, int itemNum) { - this(); - - for (int i = 0; i < seriesNum; i++){ - //xValues.add(new double[itemNum]); - //yValues.add(new double[itemNum]); - //seriesKeys.add(""); - dataset.add(new XYSeriesData()); - } - } - - /** - * Constructor - * @param xdata X station data - * @param ydata Y station data - * @param seriesKey Series key - */ - public XYListDataset(StationData xdata, StationData ydata, String seriesKey){ - this(); - List vdata = new ArrayList<>(); - double v1, v2; - for (int i = 0; i < xdata.getStNum(); i++) { - v1 = xdata.getValue(i); - if (MIMath.doubleEquals(v1, xdata.missingValue)) { - continue; - } - v2 = ydata.getValue(i); - if (MIMath.doubleEquals(v2, ydata.missingValue)) { - continue; - } - vdata.add(new double[]{v1, v2}); - } - - int n = vdata.size(); - double[] xvs = new double[n]; - double[] yvs = new double[n]; - for (int i = 0; i < n; i++){ - xvs[i] = vdata.get(i)[0]; - yvs[i] = vdata.get(i)[1]; - } - //this.xValues.add(xvs); - //this.yValues.add(yvs); - //this.seriesKeys.add(seriesKey); - XYSeriesData sdata = new XYSeriesData(seriesKey, xvs, yvs); - this.dataset.add(sdata); - } - // - // - - /** - * Get series data - * @param seriesIdx Series index - * @return Series data - */ - public XYSeriesData getSeriesData(int seriesIdx){ - return this.dataset.get(seriesIdx); - } - - @Override - public int getSeriesCount() { - //return this.xValues.size(); - return this.dataset.size(); - } - - @Override - public String getSeriesKey(int seriesIdx) { - //return this.seriesKeys.get(seriesIdx); - return this.dataset.get(seriesIdx).getKey(); - } - - /** - * Set series key by index - * @param seriesIdx Series index - * @param seriesKey Series key - */ - @Override - public void setSeriesKey(int seriesIdx, String seriesKey){ - //this.seriesKeys.set(seriesIdx, seriesKey); - this.dataset.get(seriesIdx).setKey(seriesKey); - } - - /** - * Get series keys - * @return Series keys - */ - @Override - public List getSeriesKeys(){ - //return this.seriesKeys; - List keys = new ArrayList<>(); - for (XYSeriesData d :this.dataset){ - keys.add(d.getKey()); - } - return keys; - } - - /** - * Set series keys - * @param value Series keys - */ - @Override - public void setSeriesKeys(List value){ - //this.seriesKeys = value; - int i = 0; - for (XYSeriesData d :this.dataset){ - d.setKey(value.get(i)); - i++; - } - } - - @Override - public int getItemCount(){ - int n = this.getItemCount(0); - if (this.getSeriesCount() > 1){ - for (int i = 1; i < this.getSeriesCount(); i++){ - int nn = this.getItemCount(i); - if (n < nn) - n = nn; - } - } - - return n; - } - - @Override - public int getItemCount(int seriesIdx) { - //return this.xValues.get(seriesIdx).length; - return this.dataset.get(seriesIdx).dataLength(); - } - - @Override - public double[] getXValues(int seriesIdx){ - //return this.xValues.get(seriesIdx); - return this.dataset.get(seriesIdx).getXdata(); - } - - @Override - public double[] getYValues(int seriesIdx){ - //return this.yValues.get(seriesIdx); - return this.dataset.get(seriesIdx).getYdata(); - } - - @Override - public double getX(int seriesIdx, int itemIdx) { - //return this.xValues.get(seriesIdx)[itemIdx]; - return this.dataset.get(seriesIdx).getXdata()[itemIdx]; - } - - @Override - public double getY(int seriesIdx, int itemIdx) { - //return this.yValues.get(seriesIdx)[itemIdx]; - return this.dataset.get(seriesIdx).getYdata()[itemIdx]; - } - - @Override - public void setX(int seriesIdx, int itemIdx, double value){ - //this.xValues.get(seriesIdx)[itemIdx] = value; - this.dataset.get(seriesIdx).getXdata()[itemIdx] = value; - } - - @Override - public void setY(int seriesIdx, int itemIdx, double value){ - //this.yValues.get(seriesIdx)[itemIdx] = value; - this.dataset.get(seriesIdx).getYdata()[itemIdx] = value; - } - // - // - /** - * Add a series data - * @param sdata Series data - */ - public void addSeries(XYSeriesData sdata){ - this.dataset.add(sdata); - } - - /** - * Add a series data - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, double[] xvs, double[] yvs){ - //this.seriesKeys.add(seriesKey); - //this.xValues.add(xvs); - //this.yValues.add(yvs); - XYSeriesData sdata = new XYSeriesData(seriesKey, xvs, yvs); - this.dataset.add(sdata); - } - - /** - * Add a series data - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, List xvs, List yvs){ - double[] nxvs = new double[xvs.size()]; - double[] nyvs = new double[yvs.size()]; - double v; - for (int i = 0; i < xvs.size(); i++){ - v = xvs.get(i).doubleValue(); - if (Double.isNaN(v)) - nxvs[i] = this.getMissingValue(); - else - nxvs[i] = xvs.get(i).doubleValue(); - } - for (int i = 0; i < yvs.size(); i++){ - v = yvs.get(i).doubleValue(); - if (Double.isNaN(v)) - nyvs[i] = this.getMissingValue(); - else - nyvs[i] = v; - } - - this.addSeries(seriesKey, nxvs, nyvs); - } - - /** - * Add a series data - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, List xvs, Array yvs){ - int xn = (int)xvs.size(); - int yn = (int)yvs.getSize(); - double[] nxvs = new double[xn]; - double[] nyvs = new double[yn]; - double v; - for (int i = 0; i < xn; i++) - nxvs[i] = xvs.get(i).doubleValue(); - for (int i = 0; i < yn; i++) { - v = yvs.getDouble(i); - if (Double.isNaN(v)) - nyvs[i] = this.getMissingValue(); - else - nyvs[i] = v; - } - - this.addSeries(seriesKey, nxvs, nyvs); - } - - /** - * Add a series data - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, Array xvs, Array yvs){ - int xn = (int)xvs.getSize(); - int yn = (int)yvs.getSize(); - double[] nxvs = new double[xn]; - double[] nyvs = new double[yn]; - double v; - for (int i = 0; i < xn; i++) - nxvs[i] = xvs.getDouble(i); - for (int i = 0; i < yn; i++){ - v = yvs.getDouble(i); - if (Double.isNaN(v)) - nyvs[i] = this.getMissingValue(); - else - nyvs[i] = v; - } - - this.addSeries(seriesKey, nxvs, nyvs); - } - - /** - * Add a series data - * @param seriesKey Series key - * @param xvs X value array - * @param yvs Y value array - */ - public void addSeries(String seriesKey, Array xvs, List yvs){ - int xn = (int)xvs.getSize(); - int yn = yvs.size(); - double[] nxvs = new double[xn]; - double[] nyvs = new double[yn]; - double v; - for (int i = 0; i < xn; i++) - nxvs[i] = xvs.getDouble(i); - for (int i = 0; i < yn; i++){ - v = yvs.get(i).doubleValue(); - if (Double.isNaN(v)) - nyvs[i] = this.getMissingValue(); - else - nyvs[i] = v; - } - - this.addSeries(seriesKey, nxvs, nyvs); - } - - /** - * Remove a series data - * @param seriesIdx Series data - */ - public void removeSeries(int seriesIdx){ - //this.seriesKeys.remove(seriesIdx); - //this.xValues.remove(seriesIdx); - //this.yValues.remove(seriesIdx); - this.dataset.remove(seriesIdx); - } - - /** - * Remove a series data - * @param seriesKey Series key - */ - public void removeSeries(String seriesKey){ - List keys = this.getSeriesKeys(); - int idx = keys.indexOf(seriesKey); - if (idx >= 0){ - this.removeSeries(idx); - } - } - - /** - * Get data extent - * @return Data extent - */ - @Override - public Extent getDataExtent() { - Extent cET = new Extent(); - double xmin, xmax, ymin, ymax; - int n = 0; - for (int i = 0; i < this.getSeriesCount(); i++) { - XYSeriesData sdata = this.dataset.get(i); - for (int j = 0; j < this.getItemCount(i); j++) { - xmin = sdata.getX_min(j); - xmax = sdata.getX_max(j); - ymin = sdata.getY_min(j); - ymax = sdata.getY_max(j); - if (Double.isNaN(sdata.getX(j)) || Double.isNaN(sdata.getY(j))) - continue; - if (MIMath.doubleEquals(sdata.getX(j), this.getMissingValue()) || MIMath.doubleEquals(sdata.getY(j), this.getMissingValue())) - continue; - if (n == 0) { - cET.minX = xmin; - cET.maxX = xmax; - cET.minY = ymin; - cET.maxY = ymax; - } else { - if (cET.minX > xmin) { - cET.minX = xmin; - } else if (cET.maxX < xmax) { - cET.maxX = xmax; - } - - if (cET.minY > ymin) { - cET.minY = ymin; - } else if (cET.maxY < ymax) { - cET.maxY = ymax; - } - } - n ++; - } - } - - return cET; - } - - /** - * Get missing value index list - * @param seriesIdx Series index - * @return Missing value index list - */ - @Override - public List getMissingValueIndex(int seriesIdx){ - List mvidx = new ArrayList<>(); - double[] xvs = this.getXValues(seriesIdx); - double[] yvs = this.getYValues(seriesIdx); - for (int i = 0; i < yvs.length; i++){ - if (MIMath.doubleEquals(xvs[i], this.getMissingValue()) || MIMath.doubleEquals(yvs[i], this.getMissingValue())) - mvidx.add(i); - } - - return mvidx; - } - - /** - * Select data points - * @param extent Selection extent - * @return Selected data points - */ - @Override - public List selectPoints(Extent extent){ - List selIdxs = new ArrayList<>(); - double x, y; - for (int i = 0; i < this.getSeriesCount(); i++){ - for (int j = 0; j < this.getItemCount(i); j++){ - x = this.getX(i, j); - if (x >= extent.minX && x <= extent.maxX){ - y = this.getY(i, j); - if (y >= extent.minY && y <= extent.maxY){ - selIdxs.add(new int[]{i, j}); - } - } - } - } - - return selIdxs; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.ndarray.Array; + +/** + * + * @author wyq + */ +public class XYListDataset extends XYDataset { + // + //private List xValues; + //private List yValues; + //private List seriesKeys; + private List dataset; + // + // + /** + * Constructor + */ + public XYListDataset(){ + //xValues = new ArrayList<>(); + //yValues = new ArrayList<>(); + //seriesKeys = new ArrayList<>(); + dataset = new ArrayList<>(); + } + + /** + * Constructor + * + * @param seriesNum Series number + * @param itemNum Item number + */ + public XYListDataset(int seriesNum, int itemNum) { + this(); + + for (int i = 0; i < seriesNum; i++){ + //xValues.add(new double[itemNum]); + //yValues.add(new double[itemNum]); + //seriesKeys.add(""); + dataset.add(new XYSeriesData()); + } + } + + /** + * Constructor + * @param xdata X station data + * @param ydata Y station data + * @param seriesKey Series key + */ + public XYListDataset(StationData xdata, StationData ydata, String seriesKey){ + this(); + List vdata = new ArrayList<>(); + double v1, v2; + for (int i = 0; i < xdata.getStNum(); i++) { + v1 = xdata.getValue(i); + if (MIMath.doubleEquals(v1, xdata.missingValue)) { + continue; + } + v2 = ydata.getValue(i); + if (MIMath.doubleEquals(v2, ydata.missingValue)) { + continue; + } + vdata.add(new double[]{v1, v2}); + } + + int n = vdata.size(); + double[] xvs = new double[n]; + double[] yvs = new double[n]; + for (int i = 0; i < n; i++){ + xvs[i] = vdata.get(i)[0]; + yvs[i] = vdata.get(i)[1]; + } + //this.xValues.add(xvs); + //this.yValues.add(yvs); + //this.seriesKeys.add(seriesKey); + XYSeriesData sdata = new XYSeriesData(seriesKey, xvs, yvs); + this.dataset.add(sdata); + } + // + // + + /** + * Get series data + * @param seriesIdx Series index + * @return Series data + */ + public XYSeriesData getSeriesData(int seriesIdx){ + return this.dataset.get(seriesIdx); + } + + @Override + public int getSeriesCount() { + //return this.xValues.size(); + return this.dataset.size(); + } + + @Override + public String getSeriesKey(int seriesIdx) { + //return this.seriesKeys.get(seriesIdx); + return this.dataset.get(seriesIdx).getKey(); + } + + /** + * Set series key by index + * @param seriesIdx Series index + * @param seriesKey Series key + */ + @Override + public void setSeriesKey(int seriesIdx, String seriesKey){ + //this.seriesKeys.set(seriesIdx, seriesKey); + this.dataset.get(seriesIdx).setKey(seriesKey); + } + + /** + * Get series keys + * @return Series keys + */ + @Override + public List getSeriesKeys(){ + //return this.seriesKeys; + List keys = new ArrayList<>(); + for (XYSeriesData d :this.dataset){ + keys.add(d.getKey()); + } + return keys; + } + + /** + * Set series keys + * @param value Series keys + */ + @Override + public void setSeriesKeys(List value){ + //this.seriesKeys = value; + int i = 0; + for (XYSeriesData d :this.dataset){ + d.setKey(value.get(i)); + i++; + } + } + + @Override + public int getItemCount(){ + int n = this.getItemCount(0); + if (this.getSeriesCount() > 1){ + for (int i = 1; i < this.getSeriesCount(); i++){ + int nn = this.getItemCount(i); + if (n < nn) + n = nn; + } + } + + return n; + } + + @Override + public int getItemCount(int seriesIdx) { + //return this.xValues.get(seriesIdx).length; + return this.dataset.get(seriesIdx).dataLength(); + } + + @Override + public double[] getXValues(int seriesIdx){ + //return this.xValues.get(seriesIdx); + return this.dataset.get(seriesIdx).getXdata(); + } + + @Override + public double[] getYValues(int seriesIdx){ + //return this.yValues.get(seriesIdx); + return this.dataset.get(seriesIdx).getYdata(); + } + + @Override + public double getX(int seriesIdx, int itemIdx) { + //return this.xValues.get(seriesIdx)[itemIdx]; + return this.dataset.get(seriesIdx).getXdata()[itemIdx]; + } + + @Override + public double getY(int seriesIdx, int itemIdx) { + //return this.yValues.get(seriesIdx)[itemIdx]; + return this.dataset.get(seriesIdx).getYdata()[itemIdx]; + } + + @Override + public void setX(int seriesIdx, int itemIdx, double value){ + //this.xValues.get(seriesIdx)[itemIdx] = value; + this.dataset.get(seriesIdx).getXdata()[itemIdx] = value; + } + + @Override + public void setY(int seriesIdx, int itemIdx, double value){ + //this.yValues.get(seriesIdx)[itemIdx] = value; + this.dataset.get(seriesIdx).getYdata()[itemIdx] = value; + } + // + // + /** + * Add a series data + * @param sdata Series data + */ + public void addSeries(XYSeriesData sdata){ + this.dataset.add(sdata); + } + + /** + * Add a series data + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, double[] xvs, double[] yvs){ + //this.seriesKeys.add(seriesKey); + //this.xValues.add(xvs); + //this.yValues.add(yvs); + XYSeriesData sdata = new XYSeriesData(seriesKey, xvs, yvs); + this.dataset.add(sdata); + } + + /** + * Add a series data + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, List xvs, List yvs){ + double[] nxvs = new double[xvs.size()]; + double[] nyvs = new double[yvs.size()]; + double v; + for (int i = 0; i < xvs.size(); i++){ + v = xvs.get(i).doubleValue(); + if (Double.isNaN(v)) + nxvs[i] = this.getMissingValue(); + else + nxvs[i] = xvs.get(i).doubleValue(); + } + for (int i = 0; i < yvs.size(); i++){ + v = yvs.get(i).doubleValue(); + if (Double.isNaN(v)) + nyvs[i] = this.getMissingValue(); + else + nyvs[i] = v; + } + + this.addSeries(seriesKey, nxvs, nyvs); + } + + /** + * Add a series data + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, List xvs, Array yvs){ + int xn = (int)xvs.size(); + int yn = (int)yvs.getSize(); + double[] nxvs = new double[xn]; + double[] nyvs = new double[yn]; + double v; + for (int i = 0; i < xn; i++) + nxvs[i] = xvs.get(i).doubleValue(); + for (int i = 0; i < yn; i++) { + v = yvs.getDouble(i); + if (Double.isNaN(v)) + nyvs[i] = this.getMissingValue(); + else + nyvs[i] = v; + } + + this.addSeries(seriesKey, nxvs, nyvs); + } + + /** + * Add a series data + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, Array xvs, Array yvs){ + int xn = (int)xvs.getSize(); + int yn = (int)yvs.getSize(); + double[] nxvs = new double[xn]; + double[] nyvs = new double[yn]; + double v; + for (int i = 0; i < xn; i++) + nxvs[i] = xvs.getDouble(i); + for (int i = 0; i < yn; i++){ + v = yvs.getDouble(i); + if (Double.isNaN(v)) + nyvs[i] = this.getMissingValue(); + else + nyvs[i] = v; + } + + this.addSeries(seriesKey, nxvs, nyvs); + } + + /** + * Add a series data + * @param seriesKey Series key + * @param xvs X value array + * @param yvs Y value array + */ + public void addSeries(String seriesKey, Array xvs, List yvs){ + int xn = (int)xvs.getSize(); + int yn = yvs.size(); + double[] nxvs = new double[xn]; + double[] nyvs = new double[yn]; + double v; + for (int i = 0; i < xn; i++) + nxvs[i] = xvs.getDouble(i); + for (int i = 0; i < yn; i++){ + v = yvs.get(i).doubleValue(); + if (Double.isNaN(v)) + nyvs[i] = this.getMissingValue(); + else + nyvs[i] = v; + } + + this.addSeries(seriesKey, nxvs, nyvs); + } + + /** + * Remove a series data + * @param seriesIdx Series data + */ + public void removeSeries(int seriesIdx){ + //this.seriesKeys.remove(seriesIdx); + //this.xValues.remove(seriesIdx); + //this.yValues.remove(seriesIdx); + this.dataset.remove(seriesIdx); + } + + /** + * Remove a series data + * @param seriesKey Series key + */ + public void removeSeries(String seriesKey){ + List keys = this.getSeriesKeys(); + int idx = keys.indexOf(seriesKey); + if (idx >= 0){ + this.removeSeries(idx); + } + } + + /** + * Get data extent + * @return Data extent + */ + @Override + public Extent getDataExtent() { + Extent cET = new Extent(); + double xmin, xmax, ymin, ymax; + int n = 0; + for (int i = 0; i < this.getSeriesCount(); i++) { + XYSeriesData sdata = this.dataset.get(i); + for (int j = 0; j < this.getItemCount(i); j++) { + xmin = sdata.getX_min(j); + xmax = sdata.getX_max(j); + ymin = sdata.getY_min(j); + ymax = sdata.getY_max(j); + if (Double.isNaN(sdata.getX(j)) || Double.isNaN(sdata.getY(j))) + continue; + if (MIMath.doubleEquals(sdata.getX(j), this.getMissingValue()) || MIMath.doubleEquals(sdata.getY(j), this.getMissingValue())) + continue; + if (n == 0) { + cET.minX = xmin; + cET.maxX = xmax; + cET.minY = ymin; + cET.maxY = ymax; + } else { + if (cET.minX > xmin) { + cET.minX = xmin; + } else if (cET.maxX < xmax) { + cET.maxX = xmax; + } + + if (cET.minY > ymin) { + cET.minY = ymin; + } else if (cET.maxY < ymax) { + cET.maxY = ymax; + } + } + n ++; + } + } + + return cET; + } + + /** + * Get missing value index list + * @param seriesIdx Series index + * @return Missing value index list + */ + @Override + public List getMissingValueIndex(int seriesIdx){ + List mvidx = new ArrayList<>(); + double[] xvs = this.getXValues(seriesIdx); + double[] yvs = this.getYValues(seriesIdx); + for (int i = 0; i < yvs.length; i++){ + if (MIMath.doubleEquals(xvs[i], this.getMissingValue()) || MIMath.doubleEquals(yvs[i], this.getMissingValue())) + mvidx.add(i); + } + + return mvidx; + } + + /** + * Select data points + * @param extent Selection extent + * @return Selected data points + */ + @Override + public List selectPoints(Extent extent){ + List selIdxs = new ArrayList<>(); + double x, y; + for (int i = 0; i < this.getSeriesCount(); i++){ + for (int j = 0; j < this.getItemCount(i); j++){ + x = this.getX(i, j); + if (x >= extent.minX && x <= extent.maxX){ + y = this.getY(i, j); + if (y >= extent.minY && y <= extent.maxY){ + selIdxs.add(new int[]{i, j}); + } + } + } + } + + return selIdxs; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYSeriesData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYSeriesData.java index 39fb4e80..b34c15db 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYSeriesData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/XYSeriesData.java @@ -1,258 +1,259 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.MIMath; -import ucar.ma2.Array; - -/** - * - * @author yaqiang - */ -public class XYSeriesData { - // - private String key; - private double[] xdata; - private double[] ydata; - private double missingValue = -9999.0; - // - // - /** - * Constructor - */ - public XYSeriesData(){ - - } - - /** - * Constructor - * @param key Key - */ - public XYSeriesData(String key){ - this.key = key; - } - - /** - * Constructor - * @param key Series key - * @param xdata X data - * @param ydata Y data - */ - public XYSeriesData(String key, double[] xdata, double[] ydata){ - this.key = key; - this.xdata = xdata; - this.ydata = ydata; - } - // - // - /** - * Get series key - * @return Series key - */ - public String getKey(){ - return key; - } - - /** - * Set series key - * @param value Series key - */ - public void setKey(String value){ - key = value; - } - - /** - * Get X data - * @return X data - */ - public double[] getXdata(){ - return this.xdata; - } - - /** - * Set X data - * @param value X data - */ - public void setXdata(double[] value){ - this.xdata = value; - } - - /** - * Set X data - * @param value X data - */ - public void setXdata(List value){ - this.xdata = new double[value.size()]; - double v; - for (int i = 0; i < value.size(); i++){ - v = value.get(i).doubleValue(); - if (Double.isNaN(v)) - xdata[i] = this.missingValue; - else - xdata[i] = v; - } - } - - /** - * Set X data - * @param value X data - */ - public void setXdata(Array value){ - this.xdata = new double[(int)value.getSize()]; - double v; - for (int i = 0; i < xdata.length; i++){ - v = value.getDouble(i); - if (Double.isNaN(v)) - xdata[i] = this.missingValue; - else - xdata[i] = v; - } - } - - /** - * Get Y data - * @return Y data - */ - public double[] getYdata(){ - return this.ydata; - } - - /** - * Set Y data - * @param value Y data - */ - public void setYdata(double[] value){ - this.ydata = value; - } - - /** - * Set Y data - * @param value Y data - */ - public void setYdata(List value){ - this.ydata = new double[value.size()]; - double v; - for (int i = 0; i < value.size(); i++){ - v = value.get(i).doubleValue(); - if (Double.isNaN(v)) - ydata[i] = this.missingValue; - else - ydata[i] = v; - } - } - - /** - * Set Y data - * @param value Y data - */ - public void setYdata(Array value){ - this.ydata = new double[(int)value.getSize()]; - double v; - for (int i = 0; i < ydata.length; i++){ - v = value.getDouble(i); - if (Double.isNaN(v)) - ydata[i] = this.missingValue; - else - ydata[i] = v; - } - } - - /** - * Get missing value - * @return Missing value - */ - public double getMissingValue(){ - return this.missingValue; - } - - /** - * Set missing value - * @param value Missing value - */ - public void setMissingValue(double value){ - this.missingValue = value; - } - // - // - /** - * Get data length - * @return Data length - */ - public int dataLength(){ - return this.xdata.length; - } - - /** - * Get x value - * @param idx Index - * @return X value - */ - public double getX(int idx){ - return this.xdata[idx]; - } - - /** - * Get x - error value - * @param idx Index - * @return X - error value - */ - public double getX_min(int idx){ - return this.xdata[idx]; - } - - /** - * Get x + error value - * @param idx Index - * @return X + error value - */ - public double getX_max(int idx){ - return this.xdata[idx]; - } - - /** - * Get y value - * @param idx Index - * @return Y value - */ - public double getY(int idx){ - return this.ydata[idx]; - } - - /** - * Get y - error value - * @param idx Index - * @return Y - error value - */ - public double getY_min(int idx){ - return this.ydata[idx]; - } - - /** - * Get y + error value - * @param idx Index - * @return Y + error value - */ - public double getY_max(int idx){ - return this.ydata[idx]; - } - - /** - * Get missing value index list - * @return Missing value index list - */ - public List getMissingValueIndex(){ - List mvidx = new ArrayList<>(); - for (int i = 0; i < xdata.length; i++){ - if (MIMath.doubleEquals(xdata[i], this.missingValue) || MIMath.doubleEquals(ydata[i], this.missingValue)) - mvidx.add(i); - } - - return mvidx; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.MIMath; +import ucar.ma2.Array; + +/** + * + * @author yaqiang + */ +public class XYSeriesData { + // + private String key; + private double[] xdata; + private double[] ydata; + private double missingValue = -9999.0; + // + // + /** + * Constructor + */ + public XYSeriesData(){ + + } + + /** + * Constructor + * @param key Key + */ + public XYSeriesData(String key){ + this.key = key; + } + + /** + * Constructor + * @param key Series key + * @param xdata X data + * @param ydata Y data + */ + public XYSeriesData(String key, double[] xdata, double[] ydata){ + this.key = key; + this.xdata = xdata; + this.ydata = ydata; + } + // + // + /** + * Get series key + * @return Series key + */ + public String getKey(){ + return key; + } + + /** + * Set series key + * @param value Series key + */ + public void setKey(String value){ + key = value; + } + + /** + * Get X data + * @return X data + */ + public double[] getXdata(){ + return this.xdata; + } + + /** + * Set X data + * @param value X data + */ + public void setXdata(double[] value){ + this.xdata = value; + } + + /** + * Set X data + * @param value X data + */ + public void setXdata(List value){ + this.xdata = new double[value.size()]; + double v; + for (int i = 0; i < value.size(); i++){ + v = value.get(i).doubleValue(); + if (Double.isNaN(v)) + xdata[i] = this.missingValue; + else + xdata[i] = v; + } + } + + /** + * Set X data + * @param value X data + */ + public void setXdata(Array value){ + this.xdata = new double[(int)value.getSize()]; + double v; + for (int i = 0; i < xdata.length; i++){ + v = value.getDouble(i); + if (Double.isNaN(v)) + xdata[i] = this.missingValue; + else + xdata[i] = v; + } + } + + /** + * Get Y data + * @return Y data + */ + public double[] getYdata(){ + return this.ydata; + } + + /** + * Set Y data + * @param value Y data + */ + public void setYdata(double[] value){ + this.ydata = value; + } + + /** + * Set Y data + * @param value Y data + */ + public void setYdata(List value){ + this.ydata = new double[value.size()]; + double v; + for (int i = 0; i < value.size(); i++){ + v = value.get(i).doubleValue(); + if (Double.isNaN(v)) + ydata[i] = this.missingValue; + else + ydata[i] = v; + } + } + + /** + * Set Y data + * @param value Y data + */ + public void setYdata(Array value){ + this.ydata = new double[(int)value.getSize()]; + double v; + for (int i = 0; i < ydata.length; i++){ + v = value.getDouble(i); + if (Double.isNaN(v)) + ydata[i] = this.missingValue; + else + ydata[i] = v; + } + } + + /** + * Get missing value + * @return Missing value + */ + public double getMissingValue(){ + return this.missingValue; + } + + /** + * Set missing value + * @param value Missing value + */ + public void setMissingValue(double value){ + this.missingValue = value; + } + // + // + /** + * Get data length + * @return Data length + */ + public int dataLength(){ + return this.xdata.length; + } + + /** + * Get x value + * @param idx Index + * @return X value + */ + public double getX(int idx){ + return this.xdata[idx]; + } + + /** + * Get x - error value + * @param idx Index + * @return X - error value + */ + public double getX_min(int idx){ + return this.xdata[idx]; + } + + /** + * Get x + error value + * @param idx Index + * @return X + error value + */ + public double getX_max(int idx){ + return this.xdata[idx]; + } + + /** + * Get y value + * @param idx Index + * @return Y value + */ + public double getY(int idx){ + return this.ydata[idx]; + } + + /** + * Get y - error value + * @param idx Index + * @return Y - error value + */ + public double getY_min(int idx){ + return this.ydata[idx]; + } + + /** + * Get y + error value + * @param idx Index + * @return Y + error value + */ + public double getY_max(int idx){ + return this.ydata[idx]; + } + + /** + * Get missing value index list + * @return Missing value index list + */ + public List getMissingValueIndex(){ + List mvidx = new ArrayList<>(); + for (int i = 0; i < xdata.length; i++){ + if (MIMath.doubleEquals(xdata[i], this.missingValue) || MIMath.doubleEquals(ydata[i], this.missingValue)) + mvidx.add(i); + } + + return mvidx; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Column.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Column.java index 3830d909..e28598e6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Column.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Column.java @@ -1,267 +1,267 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data.dataframe; - -import java.text.DecimalFormat; -import org.joda.time.DateTime; -import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.ndarray.Array; -import org.meteoinfo.ndarray.DataType; - -/** - * - * @author Yaqiang Wang - */ -public class Column { - // - protected String name; - protected DataType dataType; - protected String format; - protected int formatLen; - // - // - /** - * Constructor - */ - public Column(){ - this("Column", DataType.OBJECT); - } - - /** - * Constructor - * @param name Name - */ - public Column(String name){ - this(name, DataType.OBJECT); - } - - /** - * Constructor - * @param name Name - * @param dataType Data type - */ - public Column(String name, DataType dataType) { - this.name = name; - this.dataType = dataType; - this.updateFormat(); - } - // - // - /** - * Get name - * @return Name - */ - public String getName(){ - return this.name; - } - - /** - * Set name - * @param value Name - */ - public void setName(String value){ - this.name = value; - } - - /** - * Get data type - * @return Data type - */ - public DataType getDataType(){ - return this.dataType; - } - - /** - * Set data type - * @param value Data type - */ - public void setDataType(DataType value) { - this.dataType = value; - } - - /** - * Get format - * @return Format - */ - public String getFormat(){ - return this.format; - } - - /** - * Get Name format - * @return - */ - public String getNameFormat() { - return "%" + String.valueOf(this.formatLen) + "s"; - } - - /** - * Set format - * @param value Format - */ - public void setFormat(String value){ - this.format = value; - } - - /** - * Get format length - * @return Format length - */ - public int getFormatLen(){ - return this.formatLen; - } - - /** - * Set format length - * @param value Format length - */ - public void setFormatLen(int value) { - this.formatLen = value; - } - - // - // - /** - * Factory method - * @param name Name - * @param dtype Data type - * @return Column - */ - public static Column factory(String name, DataType dtype){ - return new Column(name, dtype); - } - - /** - * Factory method - * @param name Name - * @param array Data array - * @return Column - */ - public static Column factory(String name, Array array){ - DataType dtype = array.getDataType(); - if (dtype == DataType.OBJECT && (array.getObject(0) instanceof DateTime)){ - DateTimeColumn col = new DateTimeColumn(name); - col.updateFormat(array); - return col; - } - return new Column(name, dtype); - } - - /** - * Update format - */ - public void updateFormat(){ - this.format = null; - switch (this.dataType){ - case FLOAT: - case DOUBLE: - this.format = "%f"; - break; - } - this.formatLen = this.name.length(); - } - - /** - * Update format - * @param data Data array - */ - public void updateFormat(Array data) { - this.formatLen = this.name.length(); - switch(this.dataType) { - case DOUBLE: - case FLOAT: - double dmax = ArrayMath.max(data).doubleValue(); - DecimalFormat df = new DecimalFormat("0.0"); - df.setMaximumFractionDigits(6); - int nf = 1, ci, nn; - String str; - for (int i = 0; i < data.getSize(); i++){ - str = df.format(data.getDouble(i)); - ci = str.indexOf("."); - nn = str.length() - ci - 1; - if (nf < nn) { - nf = nn; - if (nf == 6) - break; - } - } - String smax = df.format(dmax); - ci = smax.indexOf("."); - int len = ci + nf + 2; - formatLen = Math.max(formatLen, len); - this.format = "%" + String.valueOf(formatLen) + "." + String.valueOf(nf) + "f"; - break; - case INT: - int imax = (int)ArrayMath.max(data); - smax = Integer.toString(imax); - formatLen = Math.max(formatLen, smax.length()); - this.format = "%" + String.valueOf(formatLen) + "d"; - break; - default: - String v; - for (int i = 0; i < data.getSize(); i++){ - if (data.getObject(i) == null) - v = "null"; - else - v = data.getObject(i).toString(); - if (formatLen < v.length()) - formatLen = v.length(); - } - this.format = "%" + String.valueOf(formatLen) + "s"; - break; - } - } - - /** - * Convert input data to current data type - * - * @param value Object value - * @return Result object - */ - public Object convertTo(Object value) { - return DataConvert.convertTo(value, this.dataType, this.format); - } - - /** - * Convert input data to current data type - * @param s Input string - * @return Result object - */ - public Object convertStringTo(String s) { - return DataConvert.convertStringTo(s, dataType, format); - } - - @Override - public String toString(){ - return this.name; - } - - /** - * Convert an object (same datatype with this column) to string - * @param o - * @return String - */ - public String toString(Object o){ - if (format == null) - return o.toString(); - else - return String.format(format, o); - } - - /** - * - * @return Column - */ - @Override - public Object clone() { - Column col = new Column(this.name, this.dataType); - col.setFormat(this.format); - col.setFormatLen(this.formatLen); - return col; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data.dataframe; + +import java.text.DecimalFormat; +import org.joda.time.DateTime; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.ndarray.Array; +import org.meteoinfo.ndarray.DataType; + +/** + * + * @author Yaqiang Wang + */ +public class Column { + // + protected String name; + protected DataType dataType; + protected String format; + protected int formatLen; + // + // + /** + * Constructor + */ + public Column(){ + this("Column", DataType.OBJECT); + } + + /** + * Constructor + * @param name Name + */ + public Column(String name){ + this(name, DataType.OBJECT); + } + + /** + * Constructor + * @param name Name + * @param dataType Data type + */ + public Column(String name, DataType dataType) { + this.name = name; + this.dataType = dataType; + this.updateFormat(); + } + // + // + /** + * Get name + * @return Name + */ + public String getName(){ + return this.name; + } + + /** + * Set name + * @param value Name + */ + public void setName(String value){ + this.name = value; + } + + /** + * Get data type + * @return Data type + */ + public DataType getDataType(){ + return this.dataType; + } + + /** + * Set data type + * @param value Data type + */ + public void setDataType(DataType value) { + this.dataType = value; + } + + /** + * Get format + * @return Format + */ + public String getFormat(){ + return this.format; + } + + /** + * Get Name format + * @return + */ + public String getNameFormat() { + return "%" + String.valueOf(this.formatLen) + "s"; + } + + /** + * Set format + * @param value Format + */ + public void setFormat(String value){ + this.format = value; + } + + /** + * Get format length + * @return Format length + */ + public int getFormatLen(){ + return this.formatLen; + } + + /** + * Set format length + * @param value Format length + */ + public void setFormatLen(int value) { + this.formatLen = value; + } + + // + // + /** + * Factory method + * @param name Name + * @param dtype Data type + * @return Column + */ + public static Column factory(String name, DataType dtype){ + return new Column(name, dtype); + } + + /** + * Factory method + * @param name Name + * @param array Data array + * @return Column + */ + public static Column factory(String name, Array array){ + DataType dtype = array.getDataType(); + if (dtype == DataType.OBJECT && (array.getObject(0) instanceof DateTime)){ + DateTimeColumn col = new DateTimeColumn(name); + col.updateFormat(array); + return col; + } + return new Column(name, dtype); + } + + /** + * Update format + */ + public void updateFormat(){ + this.format = null; + switch (this.dataType){ + case FLOAT: + case DOUBLE: + this.format = "%f"; + break; + } + this.formatLen = this.name.length(); + } + + /** + * Update format + * @param data Data array + */ + public void updateFormat(Array data) { + this.formatLen = this.name.length(); + switch(this.dataType) { + case DOUBLE: + case FLOAT: + double dmax = ArrayMath.max(data).doubleValue(); + DecimalFormat df = new DecimalFormat("0.0"); + df.setMaximumFractionDigits(6); + int nf = 1, ci, nn; + String str; + for (int i = 0; i < data.getSize(); i++){ + str = df.format(data.getDouble(i)); + ci = str.indexOf("."); + nn = str.length() - ci - 1; + if (nf < nn) { + nf = nn; + if (nf == 6) + break; + } + } + String smax = df.format(dmax); + ci = smax.indexOf("."); + int len = ci + nf + 2; + formatLen = Math.max(formatLen, len); + this.format = "%" + String.valueOf(formatLen) + "." + String.valueOf(nf) + "f"; + break; + case INT: + int imax = (int)ArrayMath.max(data); + smax = Integer.toString(imax); + formatLen = Math.max(formatLen, smax.length()); + this.format = "%" + String.valueOf(formatLen) + "d"; + break; + default: + String v; + for (int i = 0; i < data.getSize(); i++){ + if (data.getObject(i) == null) + v = "null"; + else + v = data.getObject(i).toString(); + if (formatLen < v.length()) + formatLen = v.length(); + } + this.format = "%" + String.valueOf(formatLen) + "s"; + break; + } + } + + /** + * Convert input data to current data type + * + * @param value Object value + * @return Result object + */ + public Object convertTo(Object value) { + return DataConvert.convertTo(value, this.dataType, this.format); + } + + /** + * Convert input data to current data type + * @param s Input string + * @return Result object + */ + public Object convertStringTo(String s) { + return DataConvert.convertStringTo(s, dataType, format); + } + + @Override + public String toString(){ + return this.name; + } + + /** + * Convert an object (same datatype with this column) to string + * @param o + * @return String + */ + public String toString(Object o){ + if (format == null) + return o.toString(); + else + return String.format(format, o); + } + + /** + * + * @return Column + */ + @Override + public Object clone() { + Column col = new Column(this.name, this.dataType); + col.setFormat(this.format); + col.setFormatLen(this.formatLen); + return col; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DataFrame.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DataFrame.java index 37725769..a89ea9af 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DataFrame.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DataFrame.java @@ -28,9 +28,9 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.global.util.JDateUtil; -import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.math.ArrayUtil; +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.common.util.TypeUtils; import org.meteoinfo.data.dataframe.impl.Aggregation; import org.meteoinfo.data.dataframe.impl.Function; import org.meteoinfo.data.dataframe.impl.Grouping; @@ -40,8 +40,8 @@ import org.meteoinfo.data.dataframe.impl.Sorting; import org.meteoinfo.data.dataframe.impl.Views; import org.meteoinfo.data.dataframe.impl.WindowFunction; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.global.util.TypeUtils; +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.InvalidRangeException; import org.meteoinfo.ndarray.Range; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DateTimeIndex.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DateTimeIndex.java index 01fecda5..73c041fe 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DateTimeIndex.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/DateTimeIndex.java @@ -13,11 +13,11 @@ import java.util.List; import java.time.LocalDateTime; import java.time.temporal.TemporalAmount; -import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; +import org.meteoinfo.math.ArrayMath; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Index.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Index.java index 0d25d6a6..f64e117e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Index.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Index.java @@ -10,8 +10,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; + +import org.meteoinfo.common.MIMath; import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.global.MIMath; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Series.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Series.java index 64ca6880..f40dd942 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Series.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/Series.java @@ -15,14 +15,15 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import org.meteoinfo.global.util.JDateUtil; -import org.meteoinfo.math.ArrayMath; + +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.dataframe.impl.Grouping; import org.meteoinfo.data.dataframe.impl.KeyFunction; import org.meteoinfo.data.dataframe.impl.TimeFunction; import org.meteoinfo.data.dataframe.impl.TimeFunctions; import org.meteoinfo.data.dataframe.impl.Views; import org.meteoinfo.data.dataframe.impl.WindowFunction; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.InvalidRangeException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/Grouping.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/Grouping.java index b49ce188..a15fb6bf 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/Grouping.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/Grouping.java @@ -26,10 +26,11 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import org.meteoinfo.math.ArrayUtil; + import org.meteoinfo.data.dataframe.DataFrame; import org.meteoinfo.data.dataframe.Series; import org.meteoinfo.data.dataframe.impl.Transforms.CumulativeFunction; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.Array; public class Grouping diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/WindowFunction.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/WindowFunction.java index 06aec174..2a8bda08 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/WindowFunction.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/dataframe/impl/WindowFunction.java @@ -5,7 +5,7 @@ */ package org.meteoinfo.data.dataframe.impl; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.common.util.JDateUtil; import java.time.LocalDateTime; import java.time.Period; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/AttributeTable.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/AttributeTable.java index 4a8f3147..ceb7038f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/AttributeTable.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/AttributeTable.java @@ -17,7 +17,7 @@ import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataRow; import org.meteoinfo.table.DataTable; import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.io.EndianDataOutputStream; +import org.meteoinfo.common.io.EndianDataOutputStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/MapDataManage.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/MapDataManage.java index ba8ebff9..826bfcb7 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/MapDataManage.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/MapDataManage.java @@ -13,13 +13,13 @@ */ package org.meteoinfo.data.mapdata; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.GridData; import org.meteoinfo.data.mapdata.geotiff.GeoTiff; import org.meteoinfo.data.meteodata.DrawMeteoData; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.layer.ImageLayer; import org.meteoinfo.layer.LayerDrawType; @@ -53,7 +53,7 @@ import org.meteoinfo.data.meteodata.ascii.ASCIIGridDataInfo; import org.meteoinfo.data.meteodata.ascii.SurferGridDataInfo; import org.meteoinfo.data.meteodata.bandraster.BILDataInfo; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.io.IOUtil; +import org.meteoinfo.common.io.IOUtil; import org.meteoinfo.layer.RasterLayer; import org.meteoinfo.legend.LegendScheme; import org.meteoinfo.legend.LegendType; @@ -293,7 +293,7 @@ public class MapDataManage { PolylineShape aPolyline = new PolylineShape(); aPolyline.setValue(lineNum); aPolyline.setPoints(pList); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); aPolyline.setPartNum(1); aPolyline.parts = new int[1]; aPolyline.parts[0] = 0; @@ -521,7 +521,7 @@ public class MapDataManage { } PolylineShape aPLS = new PolylineShape(); aPLS.setValue(i); - aPLS.setExtent(MIMath.getPointsExtent(pList)); + aPLS.setExtent(GeometryUtil.getPointsExtent(pList)); aPLS.setPoints(pList); int sNum = aLayer.getShapeNum(); @@ -554,7 +554,7 @@ public class MapDataManage { PolygonShape aPGS = new PolygonShape(); aPGS.lowValue = i; aPGS.highValue = i; - aPGS.setExtent(MIMath.getPointsExtent(pList)); + aPGS.setExtent(GeometryUtil.getPointsExtent(pList)); aPGS.setPoints(pList); int sNum = aLayer.getShapeNum(); diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/ShapeFileManage.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/ShapeFileManage.java index e355f4ee..dea8df10 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/ShapeFileManage.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/ShapeFileManage.java @@ -1,1053 +1,1051 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.data.mapdata; - -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; -import org.meteoinfo.io.EndianDataOutputStream; -import org.meteoinfo.layer.LayerDrawType; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.legend.LegendManage; -import org.meteoinfo.shape.PointShape; -import org.meteoinfo.shape.PointZ; -import org.meteoinfo.shape.PolygonShape; -import org.meteoinfo.shape.PolylineShape; -import org.meteoinfo.shape.PolylineZShape; -import org.meteoinfo.shape.Shape; -import org.meteoinfo.shape.ShapeTypes; -import java.awt.Color; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.meteoinfo.projection.info.ProjectionInfo; -import org.locationtech.proj4j.CRSFactory; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PointM; -import org.meteoinfo.shape.PointZShape; -import org.meteoinfo.shape.PolygonMShape; -import org.meteoinfo.shape.PolygonZShape; - -/** - * Shape file read and write - * - * @author yaqiang - */ -public class ShapeFileManage { - - private final static String ENCODING = "UTF-8"; - - /** - * Load shape file - * - * @param shpfilepath Shape file path - * @return Vector layer - * @throws IOException - * @throws java.io.FileNotFoundException - */ - public static VectorLayer loadShapeFile(String shpfilepath) throws IOException, FileNotFoundException, Exception { - String cpgfilepath = shpfilepath.replaceFirst(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".cpg"); - File cpgFile = new File(cpgfilepath); - String encoding = ENCODING; - if (cpgFile.exists()){ - BufferedReader sr = new BufferedReader(new FileReader(cpgFile)); - String ec = sr.readLine().trim(); - sr.close(); - encoding = ec; - } - return loadShapeFile(shpfilepath, encoding); - } - - /** - * Load shape file - * - * @param shpfilepath Shape file path - * @param encoding Encoding - * @return Vector layer - * @throws IOException - * @throws java.io.FileNotFoundException - */ - public static VectorLayer loadShapeFile(String shpfilepath, String encoding) throws IOException, FileNotFoundException, Exception { - //Set file names - String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); - String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); - String projfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); - File shpFile = new File(shpfilepath); - File dbfFile = new File(dbffilepath); - File shxFile = new File(shxfilepath); - File prjFile = new File(projfilepath); - if (!shxFile.exists()) { - shxfilepath = shxfilepath.replace(".shx", ".SHX"); - shxFile = new File(shxfilepath); - } - if (!dbfFile.exists()) { - dbffilepath = dbffilepath.replace(".dbf", ".DBF"); - dbfFile = new File(dbffilepath); - } - if (!prjFile.exists()) { - projfilepath = projfilepath.replace(".prj", ".PRJ"); - prjFile = new File(projfilepath); - } - - //Read shx file - if ("".equals(shxfilepath)) { - // MessageBox.Show("Open shx file error"); - return null; - } - - long BytesSum = shxFile.length(); //Get file byte length - int shapeNum = (int) (BytesSum - 100) / 8; //Get total number of records - loadShxFile(shxFile); - - //Open shp file - DataInputStream br = new DataInputStream(new BufferedInputStream(new FileInputStream(shpFile))); - VectorLayer aLayer; - //byte[] arr = new byte[(int)shpFile.length()]; - byte[] arr = new byte[100]; - br.read(arr); - ByteBuffer buffer = ByteBuffer.wrap(arr); - buffer.order(ByteOrder.LITTLE_ENDIAN); - ((Buffer)buffer).position(32); - //br.skipBytes(32); //先读出36个字节,紧接着是Box边界合 - int aShapeType = buffer.getInt(); - ShapeTypes aST = ShapeTypes.valueOf(aShapeType); - //aLayer = new VectorLayer(aST); - Extent aExtent = new Extent(); - aExtent.minX = buffer.getDouble(); //读出整个shp图层的边界合 - aExtent.minY = buffer.getDouble(); - aExtent.maxX = buffer.getDouble(); - aExtent.maxY = buffer.getDouble(); - - //br.skipBytes(32); // shp中尚未使用的边界盒 - //buffer.position(buffer.position() + 32); - - //Get Shape Data - switch (aST) { - case Point://single point - aLayer = readPointShapes(br, shapeNum); - break; - case PointZ: - aLayer = readPointZShapes(br, shapeNum); - break; - case Polyline: //Polyline layer - aLayer = readPolylineShapes(br, shapeNum); - break; - case PolylineZ: - aLayer = readPolylineZShapes(br, shapeNum); - break; - case Polygon: //Polygon layer - aLayer = readPolygonShapes(br, shapeNum); - break; - case PolygonM: - aLayer = readPolygonMShapes(br, shapeNum); - break; - case PolygonZ: - aLayer = readPolygonZShapes(br, shapeNum); - break; - default: - System.out.println("The shape type is not supported: " + aST.toString()); - return null; - } - br.close(); - - if (aLayer != null) { - aLayer.setExtent(aExtent); - - //Layer property - aLayer.setLayerDrawType(LayerDrawType.Map); - aLayer.setFileName(shpfilepath); - aLayer.setLayerName(shpFile.getName()); - aLayer.setVisible(true); - - //read out the layer attribute information - AttributeTable attrTable = loadDbfFile(shpfilepath, encoding); - aLayer.setAttributeTable(attrTable); - - //Get projection information - if (prjFile.exists()) { - aLayer.setProjInfo(loadProjFile(prjFile)); - } - } - - return aLayer; - - } - - private static void readHeader(DataInputStream br) throws IOException { - int i; - - int FileCode = swapByteOrder(br.readInt()); - for (i = 0; i < 5; i++) { - br.readInt(); - } - int FileLength = swapByteOrder(br.readInt()); - int Version = br.readInt(); - int aShapeType = br.readInt(); - Extent aExtent = new Extent(); - aExtent.minX = br.readDouble(); - aExtent.minY = br.readDouble(); - aExtent.maxX = br.readDouble(); - aExtent.maxY = br.readDouble(); - for (i = 0; i < 4; i++) { - br.readDouble(); - } - } - - private static VectorLayer readPointShapes(DataInputStream br, int shapeNum) throws IOException { - int RecordNum, ContentLength, aShapeType; - double x, y; - VectorLayer aLayer = new VectorLayer(ShapeTypes.Point); - byte[] bytes = new byte[28 * shapeNum]; - br.read(bytes); - ByteBuffer buffer = ByteBuffer.wrap(bytes); - - for (int i = 0; i < shapeNum; i++) { - - //br.ReadBytes(12); //记录头8个字节和一个int(4个字节)的shapetype - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - x = buffer.getDouble(); - y = buffer.getDouble(); - - PointShape aP = new PointShape(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - aP.setPoint(aPoint); - aLayer.addShape(aP); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Point, Color.black, 5)); - return aLayer; - } - - private static VectorLayer readPointZShapes(DataInputStream br, int shapeNum) throws IOException { - int RecordNum, ContentLength, aShapeType; - double x, y, z, m; - VectorLayer aLayer = new VectorLayer(ShapeTypes.PointZ); - byte[] bytes = new byte[44 * shapeNum]; - br.read(bytes); - ByteBuffer buffer = ByteBuffer.wrap(bytes); - - for (int i = 0; i < shapeNum; i++) { - - //br.ReadBytes(12); //记录头8个字节和一个int(4个字节)的shapetype - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - x = buffer.getDouble(); - y = buffer.getDouble(); - z = buffer.getDouble(); - m = buffer.getDouble(); - - PointZShape aP = new PointZShape(); - PointZ aPoint = new PointZ(); - aPoint.X = x; - aPoint.Y = y; - aPoint.Z = z; - aPoint.M = m; - aP.setPoint(aPoint); - aLayer.addShape(aP); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Point, Color.black, 5)); - return aLayer; - } - - private static VectorLayer readPolylineShapes(DataInputStream br, int shapeNum) throws IOException { - VectorLayer aLayer = new VectorLayer(ShapeTypes.Polyline); - int RecordNum, ContentLength, aShapeType; - double x, y; - byte[] bytes; - ByteBuffer buffer; - - //PointD aPoint; - for (int i = 0; i < shapeNum; i++) { - bytes = new byte[8]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - //br.skipBytes(12); - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - bytes = new byte[ContentLength * 2]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - PolylineShape aPL = new PolylineShape(); - Extent extent = new Extent(); - extent.minX = buffer.getDouble(); - extent.minY = buffer.getDouble(); - extent.maxX = buffer.getDouble(); - extent.maxY = buffer.getDouble(); - aPL.setExtent(extent); - - aPL.setPartNum(buffer.getInt()); - int numPoints = buffer.getInt(); - aPL.parts = new int[aPL.getPartNum()]; - List points = new ArrayList<>(); - - //firstly read out parts begin pos in file - for (int j = 0; j < aPL.getPartNum(); j++) { - aPL.parts[j] = buffer.getInt(); - } - - //read out coordinates - for (int j = 0; j < numPoints; j++) { - x = buffer.getDouble(); - y = buffer.getDouble(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - points.add(aPoint); - } - aPL.setPoints(points); - aLayer.addShape(aPL); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polyline, Color.darkGray, 1.0F)); - - return aLayer; - } - - private static VectorLayer readPolylineZShapes(DataInputStream br, int shapeNum) throws IOException { - VectorLayer aLayer = new VectorLayer(ShapeTypes.PolylineZ); - int RecordNum, ContentLength, aShapeType; - double x, y; - byte[] bytes; - ByteBuffer buffer; - - //PointD aPoint; - for (int i = 0; i < shapeNum; i++) { - //br.skipBytes(12); - bytes = new byte[8]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - //br.skipBytes(12); - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - bytes = new byte[ContentLength * 2]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - //Read bounding box - PolylineZShape aPL = new PolylineZShape(); - Extent extent = new Extent(); - extent.minX = buffer.getDouble(); - extent.minY = buffer.getDouble(); - extent.maxX = buffer.getDouble(); - extent.maxY = buffer.getDouble(); - aPL.setExtent(extent); - - aPL.setPartNum(buffer.getInt()); - int numPoints = buffer.getInt(); - aPL.parts = new int[aPL.getPartNum()]; - List points = new ArrayList<>(); - - //firstly read out parts begin position in file - for (int j = 0; j < aPL.getPartNum(); j++) { - aPL.parts[j] = buffer.getInt(); - } - - //read out coordinates - for (int j = 0; j < numPoints; j++) { - x = buffer.getDouble(); - y = buffer.getDouble(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - points.add(aPoint); - } - //aPL.Points = points; - - //Read Z - double zmin = buffer.getDouble(); - double zmax = buffer.getDouble(); - double[] zArray = new double[numPoints]; - for (int j = 0; j < numPoints; j++) { - zArray[j] = buffer.getDouble(); - } - - //Read measure - double mmin = buffer.getDouble(); - double mmax = buffer.getDouble(); - double[] mArray = new double[numPoints]; - for (int j = 0; j < numPoints; j++) { - mArray[j] = buffer.getDouble(); - } - - //Get pointZ list - List pointZs = new ArrayList<>(); - for (int j = 0; j < numPoints; j++) { - pointZs.add(new PointZ(points.get(j).X, points.get(j).Y, zArray[j], mArray[j])); - } - - aPL.setPoints(pointZs); - aLayer.addShape(aPL); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polyline, Color.darkGray, 1.0F)); - - return aLayer; - } - - private static VectorLayer readPolygonShapes(DataInputStream br, int shapeNum) throws IOException { - VectorLayer aLayer = new VectorLayer(ShapeTypes.Polygon); - int RecordNum, ContentLength, aShapeType; - double x, y; - byte[] bytes; - ByteBuffer buffer; - - for (int i = 0; i < shapeNum; i++) { - //br.skipBytes(12); - bytes = new byte[8]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - //br.skipBytes(12); - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - bytes = new byte[ContentLength * 2]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - PolygonShape aSPG = new PolygonShape(); - Extent extent = new Extent(); - extent.minX = buffer.getDouble(); - extent.minY = buffer.getDouble(); - extent.maxX = buffer.getDouble(); - extent.maxY = buffer.getDouble(); - aSPG.setExtent(extent); - aSPG.setPartNum(buffer.getInt()); - int numPoints = buffer.getInt(); - aSPG.parts = new int[aSPG.getPartNum()]; - List points = new ArrayList<>(); - - //firstly read out parts begin pos in file - for (int j = 0; j < aSPG.getPartNum(); j++) { - aSPG.parts[j] = buffer.getInt(); - } - - //read out coordinates - for (int j = 0; j < numPoints; j++) { - x = buffer.getDouble(); - y = buffer.getDouble(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - points.add(aPoint); - } - aSPG.setPoints(points); - aLayer.addShape(aSPG); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); - - return aLayer; - } - - private static VectorLayer readPolygonMShapes(DataInputStream br, int shapeNum) throws IOException { - VectorLayer aLayer = new VectorLayer(ShapeTypes.PolygonM); - int RecordNum, ContentLength, aShapeType; - double x, y; - byte[] bytes; - ByteBuffer buffer; - - for (int i = 0; i < shapeNum; i++) { - //br.skipBytes(12); - bytes = new byte[8]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - //br.skipBytes(12); - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - bytes = new byte[ContentLength * 2]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - PolygonMShape aSPG = new PolygonMShape(); - Extent extent = new Extent(); - extent.minX = buffer.getDouble(); - extent.minY = buffer.getDouble(); - extent.maxX = buffer.getDouble(); - extent.maxY = buffer.getDouble(); - aSPG.setExtent(extent); - aSPG.setPartNum(buffer.getInt()); - int numPoints = buffer.getInt(); - aSPG.parts = new int[aSPG.getPartNum()]; - List points = new ArrayList<>(); - - //firstly read out parts begin pos in file - for (int j = 0; j < aSPG.getPartNum(); j++) { - aSPG.parts[j] = buffer.getInt(); - } - - //read out coordinates - for (int j = 0; j < numPoints; j++) { - x = buffer.getDouble(); - y = buffer.getDouble(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - points.add(aPoint); - } - - //Read measure - double mmin = buffer.getDouble(); - double mmax = buffer.getDouble(); - double[] mArray = new double[numPoints]; - for (int j = 0; j < numPoints; j++) { - mArray[j] = buffer.getDouble(); - } - - //Get pointM list - List pointMs = new ArrayList<>(); - for (int j = 0; j < numPoints; j++) { - pointMs.add(new PointM(points.get(j).X, points.get(j).Y, mArray[j])); - } - - aSPG.setPoints(pointMs); - aLayer.addShape(aSPG); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); - - return aLayer; - } - - private static VectorLayer readPolygonZShapes(DataInputStream br, int shapeNum) throws IOException { - VectorLayer aLayer = new VectorLayer(ShapeTypes.PolygonZ); - int RecordNum, ContentLength, aShapeType; - double x, y; - byte[] bytes; - ByteBuffer buffer; - - for (int i = 0; i < shapeNum; i++) { - //br.skipBytes(12); - bytes = new byte[8]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - //br.skipBytes(12); - buffer.order(ByteOrder.BIG_ENDIAN); - RecordNum = buffer.getInt(); - ContentLength = buffer.getInt(); - - bytes = new byte[ContentLength * 2]; - br.read(bytes); - buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - aShapeType = buffer.getInt(); - - PolygonZShape aSPG = new PolygonZShape(); - Extent extent = new Extent(); - extent.minX = buffer.getDouble(); - extent.minY = buffer.getDouble(); - extent.maxX = buffer.getDouble(); - extent.maxY = buffer.getDouble(); - aSPG.setExtent(extent); - aSPG.setPartNum(buffer.getInt()); - int numPoints = buffer.getInt(); - aSPG.parts = new int[aSPG.getPartNum()]; - List points = new ArrayList<>(); - - //firstly read out parts begin pos in file - for (int j = 0; j < aSPG.getPartNum(); j++) { - aSPG.parts[j] = buffer.getInt(); - } - - //read out coordinates - for (int j = 0; j < numPoints; j++) { - x = buffer.getDouble(); - y = buffer.getDouble(); - PointD aPoint = new PointD(); - aPoint.X = x; - aPoint.Y = y; - points.add(aPoint); - } - - //Read Z - double zmin = buffer.getDouble(); - double zmax = buffer.getDouble(); - double[] zArray = new double[numPoints]; - for (int j = 0; j < numPoints; j++) { - zArray[j] = buffer.getDouble(); - } - - //Read measure - double mmin = buffer.getDouble(); - double mmax = buffer.getDouble(); - double[] mArray = new double[numPoints]; - for (int j = 0; j < numPoints; j++) { - mArray[j] = buffer.getDouble(); - } - - //Get pointZ list - List pointZs = new ArrayList<>(); - for (int j = 0; j < numPoints; j++) { - pointZs.add(new PointZ(points.get(j).X, points.get(j).Y, zArray[j], mArray[j])); - } - - aSPG.setPoints(pointZs); - aLayer.addShape(aSPG); - } - - //Create legend scheme - aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); - - return aLayer; - } - - private static void loadShxFile(File shxFile) throws FileNotFoundException, IOException { - DataInputStream bridx = new DataInputStream(new BufferedInputStream(new FileInputStream(shxFile))); - long BytesSum = shxFile.length(); //Get file byte length - int shapeNum = (int) (BytesSum - 100) / 8; //Get total number of records - readHeader(bridx); - - int OffSet = 0, ContentLength = 0; - for (int i = 0; i < shapeNum; i++) { - OffSet = swapByteOrder(bridx.readInt()); - ContentLength = swapByteOrder(bridx.readInt()); - } - - bridx.close(); - } - -// /** -// * Load DBF data file -// * @param shpFileName Shape file name -// * @return Attribute table -// * @throws Exception -// */ -// public static AttributeTable loadDbfFile(String shpFileName) throws Exception{ -// AttributeTable attrTable = new AttributeTable(); -// attrTable.open(shpFileName); -// attrTable.fill(attrTable.getNumRecords()); -// -// return attrTable; -// } - - /** - * Load DBF data file - * @param shpFileName Shape file name - * @param encoding Encoding - * @return Attribute table - * @throws Exception - */ - public static AttributeTable loadDbfFile(String shpFileName, String encoding) throws Exception{ - AttributeTable attrTable = new AttributeTable(); - attrTable.setEncoding(encoding); - attrTable.open(shpFileName); - attrTable.fill(attrTable.getNumRecords()); - - return attrTable; - } - - /** - * Load projection file - * @param projFile Projection file - * @return Projection infomation - * @throws FileNotFoundException - * @throws IOException - */ - public static ProjectionInfo loadProjFile(File projFile) throws FileNotFoundException, IOException { - BufferedReader sr = new BufferedReader(new FileReader(projFile)); - String line; - StringBuilder buffer = new StringBuilder(); - while ((line = sr.readLine()) != null) { - buffer.append(line); - } - - String esriString = buffer.toString(); - sr.close(); - - ProjectionInfo projInfo = ProjectionInfo.factoryESRI(esriString); - - return projInfo; - } - - /** - * Save shape file - * @param shpfilepath Shape file path - * @param aLayer Vector layer - * @return Boolean - * @throws java.io.IOException*/ - public static boolean saveShapeFile(String shpfilepath, VectorLayer aLayer) throws IOException { - String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); - String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); - String projFilePath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); - - switch (aLayer.getShapeType()) { - case Point: - case PointZ: - case Polyline: - case PolylineZ: - case Polygon: - case PolygonZ: - writeShxFile(shxfilepath, aLayer); - writeShpFile(shpfilepath, aLayer); - writeDbfFile(dbffilepath, aLayer); - writeProjFile(projFilePath, aLayer); - return true; - - default: - return false; - } - } - - /** - * Save shape file - * @param shpfilepath Shape file path - * @param aLayer Vector layer - * @param encoding Encoding - * @return Boolean - * @throws java.io.IOException*/ - public static boolean saveShapeFile(String shpfilepath, VectorLayer aLayer, String encoding) throws IOException { - String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); - String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); - String projFilePath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); - - switch (aLayer.getShapeType()) { - case Point: - case PointZ: - case Polyline: - case PolylineZ: - case Polygon: - case PolygonZ: - writeShxFile(shxfilepath, aLayer); - writeShpFile(shpfilepath, aLayer); - writeDbfFile(dbffilepath, aLayer, encoding); - writeProjFile(projFilePath, aLayer); - return true; - - default: - return false; - } - } - - private static void writeShpFile(String shpfilepath, VectorLayer aLayer) throws FileNotFoundException, IOException { - File shpFile = new File(shpfilepath); - EndianDataOutputStream bw = new EndianDataOutputStream(new BufferedOutputStream(new FileOutputStream(shpFile))); - - //Write header - int FileLength = getShpFileLength(aLayer); - writeHeader(bw, aLayer, FileLength); - - //Write records - int RecordNumber; - - for (int i = 0; i < aLayer.getShapeNum(); i++) { - Shape aShape = aLayer.getShapes().get(i); - RecordNumber = i + 1; - writeRecord(bw, RecordNumber, aShape, aLayer.getShapeType()); - } - - //Close - bw.close(); - } - - private static int getShpFileLength(VectorLayer aLayer) { - int fileLength = 50; - - for (int i = 0; i < aLayer.getShapeNum(); i++) { - Shape aShape = aLayer.getShapes().get(i); - int cLen = getContentLength(aShape, aLayer.getShapeType()); - fileLength += 4 + cLen; - } - - return fileLength; - } - - private static int getContentLength(Shape aShape, ShapeTypes aST) { - int contentLength = 0; - switch (aST) { - case Point: - contentLength = 2 + 4 * 2; - break; - case PointZ: - contentLength = 2 + 4 * 4; - break; - case Polyline: - PolylineShape aPLS = (PolylineShape) aShape; - contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPLS.getPartNum() + 4 * 2 * aPLS.getPointNum(); - break; - case PolylineZ: - PolylineZShape aPLZS = (PolylineZShape) aShape; - contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPLZS.getPartNum() + 4 * 2 * aPLZS.getPointNum() - + 4 + 4 + 4 * aPLZS.getPointNum() + 4 + 4 + 4 * aPLZS.getPointNum(); - break; - case Polygon: - PolygonShape aPGS = (PolygonShape) aShape; - contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPGS.getPartNum() + 4 * 2 * aPGS.getPointNum(); - break; - case PolygonZ: - PolygonZShape aPGZS = (PolygonZShape) aShape; - contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPGZS.getPartNum() + 4 * 2 * aPGZS.getPointNum() - + 4 + 4 + 4 * aPGZS.getPointNum() + 4 + 4 + 4 * aPGZS.getPointNum(); - break; - } - - return contentLength; - } - - private static void writeRecord(EndianDataOutputStream bw, int RecordNumber, Shape aShape, ShapeTypes aST) throws IOException { - int ContentLength, i; - - ContentLength = getContentLength(aShape, aST); - bw.writeIntBE(RecordNumber); - bw.writeIntBE(ContentLength); - bw.writeIntLE(aST.getValue()); - switch (aST) { - case Point: - PointShape aPS = (PointShape) aShape; - bw.writeDoubleLE(aPS.getPoint().X); - bw.writeDoubleLE(aPS.getPoint().Y); - break; - case Polyline: - PolylineShape aPLS = (PolylineShape) aShape; - bw.writeDoubleLE(aPLS.getExtent().minX); - bw.writeDoubleLE(aPLS.getExtent().minY); - bw.writeDoubleLE(aPLS.getExtent().maxX); - bw.writeDoubleLE(aPLS.getExtent().maxY); - bw.writeIntLE(aPLS.getPartNum()); - bw.writeIntLE(aPLS.getPointNum()); - for (i = 0; i < aPLS.getPartNum(); i++) { - bw.writeIntLE(aPLS.parts[i]); - } - for (i = 0; i < aPLS.getPointNum(); i++) { - bw.writeDoubleLE((aPLS.getPoints().get(i)).X); - bw.writeDoubleLE((aPLS.getPoints().get(i)).Y); - } - break; - case PolylineZ: - PolylineZShape aPLZS = (PolylineZShape) aShape; - bw.writeDoubleLE(aPLZS.getExtent().minX); - bw.writeDoubleLE(aPLZS.getExtent().minY); - bw.writeDoubleLE(aPLZS.getExtent().maxX); - bw.writeDoubleLE(aPLZS.getExtent().maxY); - bw.writeIntLE(aPLZS.getPartNum()); - bw.writeIntLE(aPLZS.getPointNum()); - for (i = 0; i < aPLZS.getPartNum(); i++) { - bw.writeIntLE(aPLZS.parts[i]); - } - for (i = 0; i < aPLZS.getPointNum(); i++) { - bw.writeDoubleLE((aPLZS.getPoints().get(i)).X); - bw.writeDoubleLE((aPLZS.getPoints().get(i)).Y); - } - bw.writeDoubleLE(aPLZS.getZRange()[0]); - bw.writeDoubleLE(aPLZS.getZRange()[1]); - for (i = 0; i < aPLZS.getPointNum(); i++) { - bw.writeDoubleLE(aPLZS.getZArray()[i]); - } - bw.writeDoubleLE(aPLZS.getMRange()[0]); - bw.writeDoubleLE(aPLZS.getMRange()[1]); - for (i = 0; i < aPLZS.getPointNum(); i++) { - bw.writeDoubleLE(aPLZS.getMArray()[i]); - } - break; - case Polygon: - PolygonShape aPGS = (PolygonShape) aShape; - bw.writeDoubleLE(aPGS.getExtent().minX); - bw.writeDoubleLE(aPGS.getExtent().minY); - bw.writeDoubleLE(aPGS.getExtent().maxX); - bw.writeDoubleLE(aPGS.getExtent().maxY); - bw.writeIntLE(aPGS.getPartNum()); - bw.writeIntLE(aPGS.getPointNum()); - for (i = 0; i < aPGS.getPartNum(); i++) { - bw.writeIntLE(aPGS.parts[i]); - } - for (i = 0; i < aPGS.getPointNum(); i++) { - bw.writeDoubleLE((aPGS.getPoints().get(i)).X); - bw.writeDoubleLE((aPGS.getPoints().get(i)).Y); - } - break; - case PolygonZ: - PolygonZShape aPGZS = (PolygonZShape) aShape; - bw.writeDoubleLE(aPGZS.getExtent().minX); - bw.writeDoubleLE(aPGZS.getExtent().minY); - bw.writeDoubleLE(aPGZS.getExtent().maxX); - bw.writeDoubleLE(aPGZS.getExtent().maxY); - bw.writeIntLE(aPGZS.getPartNum()); - bw.writeIntLE(aPGZS.getPointNum()); - for (i = 0; i < aPGZS.getPartNum(); i++) { - bw.writeIntLE(aPGZS.parts[i]); - } - for (i = 0; i < aPGZS.getPointNum(); i++) { - bw.writeDoubleLE((aPGZS.getPoints().get(i)).X); - bw.writeDoubleLE((aPGZS.getPoints().get(i)).Y); - } - bw.writeDoubleLE(aPGZS.getZRange()[0]); - bw.writeDoubleLE(aPGZS.getZRange()[1]); - for (i = 0; i < aPGZS.getPointNum(); i++) { - bw.writeDoubleLE(aPGZS.getZArray()[i]); - } - bw.writeDoubleLE(aPGZS.getMRange()[0]); - bw.writeDoubleLE(aPGZS.getMRange()[1]); - for (i = 0; i < aPGZS.getPointNum(); i++) { - bw.writeDoubleLE(aPGZS.getMArray()[i]); - } - break; - } - } - - private static void writeHeader(EndianDataOutputStream bw, VectorLayer aLayer, int FileLength) throws IOException { - int i; - int FileCode = 9994; - //FileCode = swapByteOrder(FileCode); - int Unused = 0; - //Unused = swapByteOrder(Unused); - //FileLength = swapByteOrder(FileLength); - int Version = 1000; - int aShapeType = aLayer.getShapeType().getValue(); - - bw.writeIntBE(FileCode); - for (i = 0; i < 5; i++) { - bw.writeIntBE(Unused); - } - bw.writeIntBE(FileLength); - bw.writeIntLE(Version); - bw.writeIntLE(aShapeType); - bw.writeDoubleLE(aLayer.getExtent().minX); - bw.writeDoubleLE(aLayer.getExtent().minY); - bw.writeDoubleLE(aLayer.getExtent().maxX); - bw.writeDoubleLE(aLayer.getExtent().maxY); - for (i = 0; i < 4; i++) { - bw.writeDoubleLE(0.0); - } - } - - private static void writeShxFile(String shxfilepath, VectorLayer aLayer) throws IOException { - File shxFile = new File(shxfilepath); - EndianDataOutputStream bw = new EndianDataOutputStream(new BufferedOutputStream(new FileOutputStream(shxFile))); - - //Write header - int FileLength = aLayer.getShapeNum() * 4 + 50; - writeHeader(bw, aLayer, FileLength); - - //Write content - int OffSet, ContentLength; - OffSet = 50; - - for (int i = 0; i < aLayer.getShapeNum(); i++) { - Shape aShape = aLayer.getShapes().get(i); - ContentLength = getContentLength(aShape, aLayer.getShapeType()); - - bw.writeIntBE(OffSet); - bw.writeIntBE(ContentLength); - - OffSet = OffSet + 4 + ContentLength; - } - - //Close - bw.close(); - } - - private static void writeDbfFile(String dbffilepath, VectorLayer aLayer) { - aLayer.getAttributeTable().saveAs(dbffilepath, true); - } - - private static void writeDbfFile(String dbffilepath, VectorLayer aLayer, String encoding) { - AttributeTable attTable = aLayer.getAttributeTable(); - attTable.setEncoding(encoding); - attTable.saveAs(dbffilepath, true); - } - - private static void writeProjFile(String projFilePath, VectorLayer aLayer) { - BufferedWriter sw = null; - try { - String esriString = aLayer.getProjInfo().toEsriString(); - sw = new BufferedWriter(new FileWriter(new File(projFilePath))); - sw.write(esriString); - sw.flush(); - sw.close(); - } catch (IOException ex) { - Logger.getLogger(ShapeFileManage.class.getName()).log(Level.SEVERE, null, ex); - } finally { - try { - sw.close(); - } catch (IOException ex) { - Logger.getLogger(ShapeFileManage.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - /** - * Swaps the byte order of an int32 - * - * @param i Integer - * @return Byte order swapped int - */ - private static int swapByteOrder(int i) { - byte[] buffer = intToBytes(i); - return ((buffer[3] & 0xff) << 24) | ((buffer[2] & 0xff) << 16) - | ((buffer[1] & 0xff) << 8) | (buffer[0] & 0xff); - } - - private static byte[] intToBytes(int i) { - byte[] result = new byte[4]; - result[0] = (byte) ((i >> 24) & 0xFF); - result[1] = (byte) ((i >> 16) & 0xFF); - result[2] = (byte) ((i >> 8) & 0xFF); - result[3] = (byte) (i & 0xFF); - return result; - } - - private static int bytesToInt(byte[] buffer){ - return ((buffer[3] & 0xff) << 24) | ((buffer[2] & 0xff) << 16) - | ((buffer[1] & 0xff) << 8) | (buffer[0] & 0xff); - } -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.data.mapdata; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.io.EndianDataOutputStream; +import org.meteoinfo.layer.LayerDrawType; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.legend.LegendManage; +import org.meteoinfo.shape.PointShape; +import org.meteoinfo.shape.PointZ; +import org.meteoinfo.shape.PolygonShape; +import org.meteoinfo.shape.PolylineShape; +import org.meteoinfo.shape.PolylineZShape; +import org.meteoinfo.shape.Shape; +import org.meteoinfo.shape.ShapeTypes; +import java.awt.Color; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.meteoinfo.projection.info.ProjectionInfo; +import org.meteoinfo.shape.PointM; +import org.meteoinfo.shape.PointZShape; +import org.meteoinfo.shape.PolygonMShape; +import org.meteoinfo.shape.PolygonZShape; + +/** + * Shape file read and write + * + * @author yaqiang + */ +public class ShapeFileManage { + + private final static String ENCODING = "UTF-8"; + + /** + * Load shape file + * + * @param shpfilepath Shape file path + * @return Vector layer + * @throws IOException + * @throws java.io.FileNotFoundException + */ + public static VectorLayer loadShapeFile(String shpfilepath) throws IOException, FileNotFoundException, Exception { + String cpgfilepath = shpfilepath.replaceFirst(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".cpg"); + File cpgFile = new File(cpgfilepath); + String encoding = ENCODING; + if (cpgFile.exists()){ + BufferedReader sr = new BufferedReader(new FileReader(cpgFile)); + String ec = sr.readLine().trim(); + sr.close(); + encoding = ec; + } + return loadShapeFile(shpfilepath, encoding); + } + + /** + * Load shape file + * + * @param shpfilepath Shape file path + * @param encoding Encoding + * @return Vector layer + * @throws IOException + * @throws java.io.FileNotFoundException + */ + public static VectorLayer loadShapeFile(String shpfilepath, String encoding) throws IOException, FileNotFoundException, Exception { + //Set file names + String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); + String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); + String projfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); + File shpFile = new File(shpfilepath); + File dbfFile = new File(dbffilepath); + File shxFile = new File(shxfilepath); + File prjFile = new File(projfilepath); + if (!shxFile.exists()) { + shxfilepath = shxfilepath.replace(".shx", ".SHX"); + shxFile = new File(shxfilepath); + } + if (!dbfFile.exists()) { + dbffilepath = dbffilepath.replace(".dbf", ".DBF"); + dbfFile = new File(dbffilepath); + } + if (!prjFile.exists()) { + projfilepath = projfilepath.replace(".prj", ".PRJ"); + prjFile = new File(projfilepath); + } + + //Read shx file + if ("".equals(shxfilepath)) { + // MessageBox.Show("Open shx file error"); + return null; + } + + long BytesSum = shxFile.length(); //Get file byte length + int shapeNum = (int) (BytesSum - 100) / 8; //Get total number of records + loadShxFile(shxFile); + + //Open shp file + DataInputStream br = new DataInputStream(new BufferedInputStream(new FileInputStream(shpFile))); + VectorLayer aLayer; + //byte[] arr = new byte[(int)shpFile.length()]; + byte[] arr = new byte[100]; + br.read(arr); + ByteBuffer buffer = ByteBuffer.wrap(arr); + buffer.order(ByteOrder.LITTLE_ENDIAN); + ((Buffer)buffer).position(32); + //br.skipBytes(32); //先读出36个字节,紧接着是Box边界合 + int aShapeType = buffer.getInt(); + ShapeTypes aST = ShapeTypes.valueOf(aShapeType); + //aLayer = new VectorLayer(aST); + Extent aExtent = new Extent(); + aExtent.minX = buffer.getDouble(); //读出整个shp图层的边界合 + aExtent.minY = buffer.getDouble(); + aExtent.maxX = buffer.getDouble(); + aExtent.maxY = buffer.getDouble(); + + //br.skipBytes(32); // shp中尚未使用的边界盒 + //buffer.position(buffer.position() + 32); + + //Get Shape Data + switch (aST) { + case Point://single point + aLayer = readPointShapes(br, shapeNum); + break; + case PointZ: + aLayer = readPointZShapes(br, shapeNum); + break; + case Polyline: //Polyline layer + aLayer = readPolylineShapes(br, shapeNum); + break; + case PolylineZ: + aLayer = readPolylineZShapes(br, shapeNum); + break; + case Polygon: //Polygon layer + aLayer = readPolygonShapes(br, shapeNum); + break; + case PolygonM: + aLayer = readPolygonMShapes(br, shapeNum); + break; + case PolygonZ: + aLayer = readPolygonZShapes(br, shapeNum); + break; + default: + System.out.println("The shape type is not supported: " + aST.toString()); + return null; + } + br.close(); + + if (aLayer != null) { + aLayer.setExtent(aExtent); + + //Layer property + aLayer.setLayerDrawType(LayerDrawType.Map); + aLayer.setFileName(shpfilepath); + aLayer.setLayerName(shpFile.getName()); + aLayer.setVisible(true); + + //read out the layer attribute information + AttributeTable attrTable = loadDbfFile(shpfilepath, encoding); + aLayer.setAttributeTable(attrTable); + + //Get projection information + if (prjFile.exists()) { + aLayer.setProjInfo(loadProjFile(prjFile)); + } + } + + return aLayer; + + } + + private static void readHeader(DataInputStream br) throws IOException { + int i; + + int FileCode = swapByteOrder(br.readInt()); + for (i = 0; i < 5; i++) { + br.readInt(); + } + int FileLength = swapByteOrder(br.readInt()); + int Version = br.readInt(); + int aShapeType = br.readInt(); + Extent aExtent = new Extent(); + aExtent.minX = br.readDouble(); + aExtent.minY = br.readDouble(); + aExtent.maxX = br.readDouble(); + aExtent.maxY = br.readDouble(); + for (i = 0; i < 4; i++) { + br.readDouble(); + } + } + + private static VectorLayer readPointShapes(DataInputStream br, int shapeNum) throws IOException { + int RecordNum, ContentLength, aShapeType; + double x, y; + VectorLayer aLayer = new VectorLayer(ShapeTypes.Point); + byte[] bytes = new byte[28 * shapeNum]; + br.read(bytes); + ByteBuffer buffer = ByteBuffer.wrap(bytes); + + for (int i = 0; i < shapeNum; i++) { + + //br.ReadBytes(12); //记录头8个字节和一个int(4个字节)的shapetype + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + x = buffer.getDouble(); + y = buffer.getDouble(); + + PointShape aP = new PointShape(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + aP.setPoint(aPoint); + aLayer.addShape(aP); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Point, Color.black, 5)); + return aLayer; + } + + private static VectorLayer readPointZShapes(DataInputStream br, int shapeNum) throws IOException { + int RecordNum, ContentLength, aShapeType; + double x, y, z, m; + VectorLayer aLayer = new VectorLayer(ShapeTypes.PointZ); + byte[] bytes = new byte[44 * shapeNum]; + br.read(bytes); + ByteBuffer buffer = ByteBuffer.wrap(bytes); + + for (int i = 0; i < shapeNum; i++) { + + //br.ReadBytes(12); //记录头8个字节和一个int(4个字节)的shapetype + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + x = buffer.getDouble(); + y = buffer.getDouble(); + z = buffer.getDouble(); + m = buffer.getDouble(); + + PointZShape aP = new PointZShape(); + PointZ aPoint = new PointZ(); + aPoint.X = x; + aPoint.Y = y; + aPoint.Z = z; + aPoint.M = m; + aP.setPoint(aPoint); + aLayer.addShape(aP); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Point, Color.black, 5)); + return aLayer; + } + + private static VectorLayer readPolylineShapes(DataInputStream br, int shapeNum) throws IOException { + VectorLayer aLayer = new VectorLayer(ShapeTypes.Polyline); + int RecordNum, ContentLength, aShapeType; + double x, y; + byte[] bytes; + ByteBuffer buffer; + + //PointD aPoint; + for (int i = 0; i < shapeNum; i++) { + bytes = new byte[8]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + //br.skipBytes(12); + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + bytes = new byte[ContentLength * 2]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + PolylineShape aPL = new PolylineShape(); + Extent extent = new Extent(); + extent.minX = buffer.getDouble(); + extent.minY = buffer.getDouble(); + extent.maxX = buffer.getDouble(); + extent.maxY = buffer.getDouble(); + aPL.setExtent(extent); + + aPL.setPartNum(buffer.getInt()); + int numPoints = buffer.getInt(); + aPL.parts = new int[aPL.getPartNum()]; + List points = new ArrayList<>(); + + //firstly read out parts begin pos in file + for (int j = 0; j < aPL.getPartNum(); j++) { + aPL.parts[j] = buffer.getInt(); + } + + //read out coordinates + for (int j = 0; j < numPoints; j++) { + x = buffer.getDouble(); + y = buffer.getDouble(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + points.add(aPoint); + } + aPL.setPoints(points); + aLayer.addShape(aPL); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polyline, Color.darkGray, 1.0F)); + + return aLayer; + } + + private static VectorLayer readPolylineZShapes(DataInputStream br, int shapeNum) throws IOException { + VectorLayer aLayer = new VectorLayer(ShapeTypes.PolylineZ); + int RecordNum, ContentLength, aShapeType; + double x, y; + byte[] bytes; + ByteBuffer buffer; + + //PointD aPoint; + for (int i = 0; i < shapeNum; i++) { + //br.skipBytes(12); + bytes = new byte[8]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + //br.skipBytes(12); + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + bytes = new byte[ContentLength * 2]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + //Read bounding box + PolylineZShape aPL = new PolylineZShape(); + Extent extent = new Extent(); + extent.minX = buffer.getDouble(); + extent.minY = buffer.getDouble(); + extent.maxX = buffer.getDouble(); + extent.maxY = buffer.getDouble(); + aPL.setExtent(extent); + + aPL.setPartNum(buffer.getInt()); + int numPoints = buffer.getInt(); + aPL.parts = new int[aPL.getPartNum()]; + List points = new ArrayList<>(); + + //firstly read out parts begin position in file + for (int j = 0; j < aPL.getPartNum(); j++) { + aPL.parts[j] = buffer.getInt(); + } + + //read out coordinates + for (int j = 0; j < numPoints; j++) { + x = buffer.getDouble(); + y = buffer.getDouble(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + points.add(aPoint); + } + //aPL.Points = points; + + //Read Z + double zmin = buffer.getDouble(); + double zmax = buffer.getDouble(); + double[] zArray = new double[numPoints]; + for (int j = 0; j < numPoints; j++) { + zArray[j] = buffer.getDouble(); + } + + //Read measure + double mmin = buffer.getDouble(); + double mmax = buffer.getDouble(); + double[] mArray = new double[numPoints]; + for (int j = 0; j < numPoints; j++) { + mArray[j] = buffer.getDouble(); + } + + //Get pointZ list + List pointZs = new ArrayList<>(); + for (int j = 0; j < numPoints; j++) { + pointZs.add(new PointZ(points.get(j).X, points.get(j).Y, zArray[j], mArray[j])); + } + + aPL.setPoints(pointZs); + aLayer.addShape(aPL); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polyline, Color.darkGray, 1.0F)); + + return aLayer; + } + + private static VectorLayer readPolygonShapes(DataInputStream br, int shapeNum) throws IOException { + VectorLayer aLayer = new VectorLayer(ShapeTypes.Polygon); + int RecordNum, ContentLength, aShapeType; + double x, y; + byte[] bytes; + ByteBuffer buffer; + + for (int i = 0; i < shapeNum; i++) { + //br.skipBytes(12); + bytes = new byte[8]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + //br.skipBytes(12); + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + bytes = new byte[ContentLength * 2]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + PolygonShape aSPG = new PolygonShape(); + Extent extent = new Extent(); + extent.minX = buffer.getDouble(); + extent.minY = buffer.getDouble(); + extent.maxX = buffer.getDouble(); + extent.maxY = buffer.getDouble(); + aSPG.setExtent(extent); + aSPG.setPartNum(buffer.getInt()); + int numPoints = buffer.getInt(); + aSPG.parts = new int[aSPG.getPartNum()]; + List points = new ArrayList<>(); + + //firstly read out parts begin pos in file + for (int j = 0; j < aSPG.getPartNum(); j++) { + aSPG.parts[j] = buffer.getInt(); + } + + //read out coordinates + for (int j = 0; j < numPoints; j++) { + x = buffer.getDouble(); + y = buffer.getDouble(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + points.add(aPoint); + } + aSPG.setPoints(points); + aLayer.addShape(aSPG); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); + + return aLayer; + } + + private static VectorLayer readPolygonMShapes(DataInputStream br, int shapeNum) throws IOException { + VectorLayer aLayer = new VectorLayer(ShapeTypes.PolygonM); + int RecordNum, ContentLength, aShapeType; + double x, y; + byte[] bytes; + ByteBuffer buffer; + + for (int i = 0; i < shapeNum; i++) { + //br.skipBytes(12); + bytes = new byte[8]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + //br.skipBytes(12); + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + bytes = new byte[ContentLength * 2]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + PolygonMShape aSPG = new PolygonMShape(); + Extent extent = new Extent(); + extent.minX = buffer.getDouble(); + extent.minY = buffer.getDouble(); + extent.maxX = buffer.getDouble(); + extent.maxY = buffer.getDouble(); + aSPG.setExtent(extent); + aSPG.setPartNum(buffer.getInt()); + int numPoints = buffer.getInt(); + aSPG.parts = new int[aSPG.getPartNum()]; + List points = new ArrayList<>(); + + //firstly read out parts begin pos in file + for (int j = 0; j < aSPG.getPartNum(); j++) { + aSPG.parts[j] = buffer.getInt(); + } + + //read out coordinates + for (int j = 0; j < numPoints; j++) { + x = buffer.getDouble(); + y = buffer.getDouble(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + points.add(aPoint); + } + + //Read measure + double mmin = buffer.getDouble(); + double mmax = buffer.getDouble(); + double[] mArray = new double[numPoints]; + for (int j = 0; j < numPoints; j++) { + mArray[j] = buffer.getDouble(); + } + + //Get pointM list + List pointMs = new ArrayList<>(); + for (int j = 0; j < numPoints; j++) { + pointMs.add(new PointM(points.get(j).X, points.get(j).Y, mArray[j])); + } + + aSPG.setPoints(pointMs); + aLayer.addShape(aSPG); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); + + return aLayer; + } + + private static VectorLayer readPolygonZShapes(DataInputStream br, int shapeNum) throws IOException { + VectorLayer aLayer = new VectorLayer(ShapeTypes.PolygonZ); + int RecordNum, ContentLength, aShapeType; + double x, y; + byte[] bytes; + ByteBuffer buffer; + + for (int i = 0; i < shapeNum; i++) { + //br.skipBytes(12); + bytes = new byte[8]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + //br.skipBytes(12); + buffer.order(ByteOrder.BIG_ENDIAN); + RecordNum = buffer.getInt(); + ContentLength = buffer.getInt(); + + bytes = new byte[ContentLength * 2]; + br.read(bytes); + buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + aShapeType = buffer.getInt(); + + PolygonZShape aSPG = new PolygonZShape(); + Extent extent = new Extent(); + extent.minX = buffer.getDouble(); + extent.minY = buffer.getDouble(); + extent.maxX = buffer.getDouble(); + extent.maxY = buffer.getDouble(); + aSPG.setExtent(extent); + aSPG.setPartNum(buffer.getInt()); + int numPoints = buffer.getInt(); + aSPG.parts = new int[aSPG.getPartNum()]; + List points = new ArrayList<>(); + + //firstly read out parts begin pos in file + for (int j = 0; j < aSPG.getPartNum(); j++) { + aSPG.parts[j] = buffer.getInt(); + } + + //read out coordinates + for (int j = 0; j < numPoints; j++) { + x = buffer.getDouble(); + y = buffer.getDouble(); + PointD aPoint = new PointD(); + aPoint.X = x; + aPoint.Y = y; + points.add(aPoint); + } + + //Read Z + double zmin = buffer.getDouble(); + double zmax = buffer.getDouble(); + double[] zArray = new double[numPoints]; + for (int j = 0; j < numPoints; j++) { + zArray[j] = buffer.getDouble(); + } + + //Read measure + double mmin = buffer.getDouble(); + double mmax = buffer.getDouble(); + double[] mArray = new double[numPoints]; + for (int j = 0; j < numPoints; j++) { + mArray[j] = buffer.getDouble(); + } + + //Get pointZ list + List pointZs = new ArrayList<>(); + for (int j = 0; j < numPoints; j++) { + pointZs.add(new PointZ(points.get(j).X, points.get(j).Y, zArray[j], mArray[j])); + } + + aSPG.setPoints(pointZs); + aLayer.addShape(aSPG); + } + + //Create legend scheme + aLayer.setLegendScheme(LegendManage.createSingleSymbolLegendScheme(ShapeTypes.Polygon, new Color(255, 251, 195), 1.0F)); + + return aLayer; + } + + private static void loadShxFile(File shxFile) throws FileNotFoundException, IOException { + DataInputStream bridx = new DataInputStream(new BufferedInputStream(new FileInputStream(shxFile))); + long BytesSum = shxFile.length(); //Get file byte length + int shapeNum = (int) (BytesSum - 100) / 8; //Get total number of records + readHeader(bridx); + + int OffSet = 0, ContentLength = 0; + for (int i = 0; i < shapeNum; i++) { + OffSet = swapByteOrder(bridx.readInt()); + ContentLength = swapByteOrder(bridx.readInt()); + } + + bridx.close(); + } + +// /** +// * Load DBF data file +// * @param shpFileName Shape file name +// * @return Attribute table +// * @throws Exception +// */ +// public static AttributeTable loadDbfFile(String shpFileName) throws Exception{ +// AttributeTable attrTable = new AttributeTable(); +// attrTable.open(shpFileName); +// attrTable.fill(attrTable.getNumRecords()); +// +// return attrTable; +// } + + /** + * Load DBF data file + * @param shpFileName Shape file name + * @param encoding Encoding + * @return Attribute table + * @throws Exception + */ + public static AttributeTable loadDbfFile(String shpFileName, String encoding) throws Exception{ + AttributeTable attrTable = new AttributeTable(); + attrTable.setEncoding(encoding); + attrTable.open(shpFileName); + attrTable.fill(attrTable.getNumRecords()); + + return attrTable; + } + + /** + * Load projection file + * @param projFile Projection file + * @return Projection infomation + * @throws FileNotFoundException + * @throws IOException + */ + public static ProjectionInfo loadProjFile(File projFile) throws FileNotFoundException, IOException { + BufferedReader sr = new BufferedReader(new FileReader(projFile)); + String line; + StringBuilder buffer = new StringBuilder(); + while ((line = sr.readLine()) != null) { + buffer.append(line); + } + + String esriString = buffer.toString(); + sr.close(); + + ProjectionInfo projInfo = ProjectionInfo.factoryESRI(esriString); + + return projInfo; + } + + /** + * Save shape file + * @param shpfilepath Shape file path + * @param aLayer Vector layer + * @return Boolean + * @throws java.io.IOException*/ + public static boolean saveShapeFile(String shpfilepath, VectorLayer aLayer) throws IOException { + String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); + String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); + String projFilePath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); + + switch (aLayer.getShapeType()) { + case Point: + case PointZ: + case Polyline: + case PolylineZ: + case Polygon: + case PolygonZ: + writeShxFile(shxfilepath, aLayer); + writeShpFile(shpfilepath, aLayer); + writeDbfFile(dbffilepath, aLayer); + writeProjFile(projFilePath, aLayer); + return true; + + default: + return false; + } + } + + /** + * Save shape file + * @param shpfilepath Shape file path + * @param aLayer Vector layer + * @param encoding Encoding + * @return Boolean + * @throws java.io.IOException*/ + public static boolean saveShapeFile(String shpfilepath, VectorLayer aLayer, String encoding) throws IOException { + String shxfilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".shx"); + String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); + String projFilePath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".prj"); + + switch (aLayer.getShapeType()) { + case Point: + case PointZ: + case Polyline: + case PolylineZ: + case Polygon: + case PolygonZ: + writeShxFile(shxfilepath, aLayer); + writeShpFile(shpfilepath, aLayer); + writeDbfFile(dbffilepath, aLayer, encoding); + writeProjFile(projFilePath, aLayer); + return true; + + default: + return false; + } + } + + private static void writeShpFile(String shpfilepath, VectorLayer aLayer) throws FileNotFoundException, IOException { + File shpFile = new File(shpfilepath); + EndianDataOutputStream bw = new EndianDataOutputStream(new BufferedOutputStream(new FileOutputStream(shpFile))); + + //Write header + int FileLength = getShpFileLength(aLayer); + writeHeader(bw, aLayer, FileLength); + + //Write records + int RecordNumber; + + for (int i = 0; i < aLayer.getShapeNum(); i++) { + Shape aShape = aLayer.getShapes().get(i); + RecordNumber = i + 1; + writeRecord(bw, RecordNumber, aShape, aLayer.getShapeType()); + } + + //Close + bw.close(); + } + + private static int getShpFileLength(VectorLayer aLayer) { + int fileLength = 50; + + for (int i = 0; i < aLayer.getShapeNum(); i++) { + Shape aShape = aLayer.getShapes().get(i); + int cLen = getContentLength(aShape, aLayer.getShapeType()); + fileLength += 4 + cLen; + } + + return fileLength; + } + + private static int getContentLength(Shape aShape, ShapeTypes aST) { + int contentLength = 0; + switch (aST) { + case Point: + contentLength = 2 + 4 * 2; + break; + case PointZ: + contentLength = 2 + 4 * 4; + break; + case Polyline: + PolylineShape aPLS = (PolylineShape) aShape; + contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPLS.getPartNum() + 4 * 2 * aPLS.getPointNum(); + break; + case PolylineZ: + PolylineZShape aPLZS = (PolylineZShape) aShape; + contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPLZS.getPartNum() + 4 * 2 * aPLZS.getPointNum() + + 4 + 4 + 4 * aPLZS.getPointNum() + 4 + 4 + 4 * aPLZS.getPointNum(); + break; + case Polygon: + PolygonShape aPGS = (PolygonShape) aShape; + contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPGS.getPartNum() + 4 * 2 * aPGS.getPointNum(); + break; + case PolygonZ: + PolygonZShape aPGZS = (PolygonZShape) aShape; + contentLength = 2 + 4 * 4 + 2 + 2 + 2 * aPGZS.getPartNum() + 4 * 2 * aPGZS.getPointNum() + + 4 + 4 + 4 * aPGZS.getPointNum() + 4 + 4 + 4 * aPGZS.getPointNum(); + break; + } + + return contentLength; + } + + private static void writeRecord(EndianDataOutputStream bw, int RecordNumber, Shape aShape, ShapeTypes aST) throws IOException { + int ContentLength, i; + + ContentLength = getContentLength(aShape, aST); + bw.writeIntBE(RecordNumber); + bw.writeIntBE(ContentLength); + bw.writeIntLE(aST.getValue()); + switch (aST) { + case Point: + PointShape aPS = (PointShape) aShape; + bw.writeDoubleLE(aPS.getPoint().X); + bw.writeDoubleLE(aPS.getPoint().Y); + break; + case Polyline: + PolylineShape aPLS = (PolylineShape) aShape; + bw.writeDoubleLE(aPLS.getExtent().minX); + bw.writeDoubleLE(aPLS.getExtent().minY); + bw.writeDoubleLE(aPLS.getExtent().maxX); + bw.writeDoubleLE(aPLS.getExtent().maxY); + bw.writeIntLE(aPLS.getPartNum()); + bw.writeIntLE(aPLS.getPointNum()); + for (i = 0; i < aPLS.getPartNum(); i++) { + bw.writeIntLE(aPLS.parts[i]); + } + for (i = 0; i < aPLS.getPointNum(); i++) { + bw.writeDoubleLE((aPLS.getPoints().get(i)).X); + bw.writeDoubleLE((aPLS.getPoints().get(i)).Y); + } + break; + case PolylineZ: + PolylineZShape aPLZS = (PolylineZShape) aShape; + bw.writeDoubleLE(aPLZS.getExtent().minX); + bw.writeDoubleLE(aPLZS.getExtent().minY); + bw.writeDoubleLE(aPLZS.getExtent().maxX); + bw.writeDoubleLE(aPLZS.getExtent().maxY); + bw.writeIntLE(aPLZS.getPartNum()); + bw.writeIntLE(aPLZS.getPointNum()); + for (i = 0; i < aPLZS.getPartNum(); i++) { + bw.writeIntLE(aPLZS.parts[i]); + } + for (i = 0; i < aPLZS.getPointNum(); i++) { + bw.writeDoubleLE((aPLZS.getPoints().get(i)).X); + bw.writeDoubleLE((aPLZS.getPoints().get(i)).Y); + } + bw.writeDoubleLE(aPLZS.getZRange()[0]); + bw.writeDoubleLE(aPLZS.getZRange()[1]); + for (i = 0; i < aPLZS.getPointNum(); i++) { + bw.writeDoubleLE(aPLZS.getZArray()[i]); + } + bw.writeDoubleLE(aPLZS.getMRange()[0]); + bw.writeDoubleLE(aPLZS.getMRange()[1]); + for (i = 0; i < aPLZS.getPointNum(); i++) { + bw.writeDoubleLE(aPLZS.getMArray()[i]); + } + break; + case Polygon: + PolygonShape aPGS = (PolygonShape) aShape; + bw.writeDoubleLE(aPGS.getExtent().minX); + bw.writeDoubleLE(aPGS.getExtent().minY); + bw.writeDoubleLE(aPGS.getExtent().maxX); + bw.writeDoubleLE(aPGS.getExtent().maxY); + bw.writeIntLE(aPGS.getPartNum()); + bw.writeIntLE(aPGS.getPointNum()); + for (i = 0; i < aPGS.getPartNum(); i++) { + bw.writeIntLE(aPGS.parts[i]); + } + for (i = 0; i < aPGS.getPointNum(); i++) { + bw.writeDoubleLE((aPGS.getPoints().get(i)).X); + bw.writeDoubleLE((aPGS.getPoints().get(i)).Y); + } + break; + case PolygonZ: + PolygonZShape aPGZS = (PolygonZShape) aShape; + bw.writeDoubleLE(aPGZS.getExtent().minX); + bw.writeDoubleLE(aPGZS.getExtent().minY); + bw.writeDoubleLE(aPGZS.getExtent().maxX); + bw.writeDoubleLE(aPGZS.getExtent().maxY); + bw.writeIntLE(aPGZS.getPartNum()); + bw.writeIntLE(aPGZS.getPointNum()); + for (i = 0; i < aPGZS.getPartNum(); i++) { + bw.writeIntLE(aPGZS.parts[i]); + } + for (i = 0; i < aPGZS.getPointNum(); i++) { + bw.writeDoubleLE((aPGZS.getPoints().get(i)).X); + bw.writeDoubleLE((aPGZS.getPoints().get(i)).Y); + } + bw.writeDoubleLE(aPGZS.getZRange()[0]); + bw.writeDoubleLE(aPGZS.getZRange()[1]); + for (i = 0; i < aPGZS.getPointNum(); i++) { + bw.writeDoubleLE(aPGZS.getZArray()[i]); + } + bw.writeDoubleLE(aPGZS.getMRange()[0]); + bw.writeDoubleLE(aPGZS.getMRange()[1]); + for (i = 0; i < aPGZS.getPointNum(); i++) { + bw.writeDoubleLE(aPGZS.getMArray()[i]); + } + break; + } + } + + private static void writeHeader(EndianDataOutputStream bw, VectorLayer aLayer, int FileLength) throws IOException { + int i; + int FileCode = 9994; + //FileCode = swapByteOrder(FileCode); + int Unused = 0; + //Unused = swapByteOrder(Unused); + //FileLength = swapByteOrder(FileLength); + int Version = 1000; + int aShapeType = aLayer.getShapeType().getValue(); + + bw.writeIntBE(FileCode); + for (i = 0; i < 5; i++) { + bw.writeIntBE(Unused); + } + bw.writeIntBE(FileLength); + bw.writeIntLE(Version); + bw.writeIntLE(aShapeType); + bw.writeDoubleLE(aLayer.getExtent().minX); + bw.writeDoubleLE(aLayer.getExtent().minY); + bw.writeDoubleLE(aLayer.getExtent().maxX); + bw.writeDoubleLE(aLayer.getExtent().maxY); + for (i = 0; i < 4; i++) { + bw.writeDoubleLE(0.0); + } + } + + private static void writeShxFile(String shxfilepath, VectorLayer aLayer) throws IOException { + File shxFile = new File(shxfilepath); + EndianDataOutputStream bw = new EndianDataOutputStream(new BufferedOutputStream(new FileOutputStream(shxFile))); + + //Write header + int FileLength = aLayer.getShapeNum() * 4 + 50; + writeHeader(bw, aLayer, FileLength); + + //Write content + int OffSet, ContentLength; + OffSet = 50; + + for (int i = 0; i < aLayer.getShapeNum(); i++) { + Shape aShape = aLayer.getShapes().get(i); + ContentLength = getContentLength(aShape, aLayer.getShapeType()); + + bw.writeIntBE(OffSet); + bw.writeIntBE(ContentLength); + + OffSet = OffSet + 4 + ContentLength; + } + + //Close + bw.close(); + } + + private static void writeDbfFile(String dbffilepath, VectorLayer aLayer) { + aLayer.getAttributeTable().saveAs(dbffilepath, true); + } + + private static void writeDbfFile(String dbffilepath, VectorLayer aLayer, String encoding) { + AttributeTable attTable = aLayer.getAttributeTable(); + attTable.setEncoding(encoding); + attTable.saveAs(dbffilepath, true); + } + + private static void writeProjFile(String projFilePath, VectorLayer aLayer) { + BufferedWriter sw = null; + try { + String esriString = aLayer.getProjInfo().toEsriString(); + sw = new BufferedWriter(new FileWriter(new File(projFilePath))); + sw.write(esriString); + sw.flush(); + sw.close(); + } catch (IOException ex) { + Logger.getLogger(ShapeFileManage.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + sw.close(); + } catch (IOException ex) { + Logger.getLogger(ShapeFileManage.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + /** + * Swaps the byte order of an int32 + * + * @param i Integer + * @return Byte order swapped int + */ + private static int swapByteOrder(int i) { + byte[] buffer = intToBytes(i); + return ((buffer[3] & 0xff) << 24) | ((buffer[2] & 0xff) << 16) + | ((buffer[1] & 0xff) << 8) | (buffer[0] & 0xff); + } + + private static byte[] intToBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) ((i >> 24) & 0xFF); + result[1] = (byte) ((i >> 16) & 0xFF); + result[2] = (byte) ((i >> 8) & 0xFF); + result[3] = (byte) (i & 0xFF); + return result; + } + + private static int bytesToInt(byte[] buffer){ + return ((buffer[3] & 0xff) << 24) | ((buffer[2] & 0xff) << 16) + | ((buffer[1] & 0xff) << 8) | (buffer[0] & 0xff); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java index fc348fb9..5a8ee712 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java @@ -28,12 +28,13 @@ import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayMath; + import org.meteoinfo.data.GridArray; import org.meteoinfo.data.mapdata.geotiff.compression.CompressionDecoder; import org.meteoinfo.data.mapdata.geotiff.compression.DeflateCompression; import org.meteoinfo.data.mapdata.geotiff.compression.LZWCompression; import org.meteoinfo.global.DataConvert; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/webmap/AbstractTileFactory.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/webmap/AbstractTileFactory.java index e0d1303e..2416282c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/webmap/AbstractTileFactory.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/webmap/AbstractTileFactory.java @@ -1,452 +1,452 @@ -package org.meteoinfo.data.mapdata.webmap; - -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.SoftReference; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.SwingUtilities; - -import org.meteoinfo.global.util.GeoUtil; -import org.meteoinfo.global.util.GraphicsUtilities; - -/** - * The - * AbstractTileFactory provides a basic implementation for the - * TileFactory. - */ -public abstract class AbstractTileFactory extends TileFactory { - - private static final Logger LOG = Logger.getLogger(AbstractTileFactory.class.getName()); - - /** - * Creates a new instance of DefaultTileFactory using the spcified - * TileFactoryInfo - * - * @param info a TileFactoryInfo to configure this TileFactory - */ - public AbstractTileFactory(TileFactoryInfo info) { - super(info); - } - //private static final boolean doEagerLoading = true; - private int threadPoolSize = 4; - private ExecutorService service; - //TODO the tile map should be static ALWAYS, regardless of the number - //of GoogleTileFactories because each tile is, really, a singleton. - private final Map tileMap = new HashMap<>(); - private TileCache cache = new TileCache(); - - /** - * Returns - * - * @param pixelCoordinate - * @return - */ - //public TilePoint getTileCoordinate(Point2D pixelCoordinate) { - // return GeoUtil.getTileCoordinate(pixelCoordinate, getInfo()); - //} - /** - * Returns the tile that is located at the given tilePoint for this zoom. - * For example, if getMapSize() returns 10x20 for this zoom, and the - * tilePoint is (3,5), then the appropriate tile will be located and - * returned. - * - * @param x X index - * @param y Y index - * @param zoom Zoom value - * @return Tile - */ - @Override - public Tile getTile(int x, int y, int zoom) { - return getTile(x, y, zoom, true); - } - - private Tile getTile(int tpx, int tpy, int zoom, boolean eagerLoad) { - //wrap the tiles horizontally --> mod the X with the max width - //and use that - int tileX = tpx;//tilePoint.getX(); - int numTilesWide = (int) getMapSize(zoom).getWidth(); - if (tileX < 0) { - tileX = numTilesWide - (Math.abs(tileX) % numTilesWide); - } - - tileX = tileX % numTilesWide; - int tileY = tpy; - //TilePoint tilePoint = new TilePoint(tileX, tpy); - String url = getInfo().getTileUrl(tileX, tileY, zoom);//tilePoint); - //System.out.println("loading: " + url); - - - Tile.Priority pri = Tile.Priority.High; - if (!eagerLoad) { - pri = Tile.Priority.Low; - } - Tile tile = null; - //System.out.println("testing for validity: " + tilePoint + " zoom = " + zoom); - if (!tileMap.containsKey(url)) { - if (!GeoUtil.isValidTile(tileX, tileY, zoom, getInfo())) { - tile = new Tile(tileX, tileY, zoom); - } else { - tile = new Tile(tileX, tileY, zoom, url, pri, this); - //load(tile); - startLoading(tile); - } - tileMap.put(url, tile); - } else { - tile = tileMap.get(url); - // if its in the map but is low and isn't loaded yet - // but we are in high mode - if (tile.getPriority() == Tile.Priority.Low && eagerLoad && !tile.isLoaded()) { - //System.out.println("in high mode and want a low"); - //tile.promote(); - promote(tile); - } - } - - /* - if (eagerLoad && doEagerLoading) { - for (int i = 0; i<1; i++) { - for (int j = 0; j<1; j++) { - // preload the 4 tiles under the current one - if(zoom > 0) { - eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2, zoom-1); - eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2, zoom-1); - eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2+1, zoom-1); - eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2+1, zoom-1); - } - } - } - }*/ - - - return tile; - } - - /* - private void eagerlyLoad(int x, int y, int zoom) { - TilePoint t1 = new TilePoint(x,y); - if(!isLoaded(t1,zoom)) { - getTile(t1,zoom,false); - } - } - */ - // private boolean isLoaded(int x, int y, int zoom) { - // String url = getInfo().getTileUrl(zoom,x,y); - // return tileMap.containsKey(url); - // } - public TileCache getTileCache() { - return cache; - } - - public void setTileCache(TileCache cache) { - this.cache = cache; - } - /** - * ==== threaded tile loading stuff === - */ - /** - * Thread pool for loading the tiles - */ - private static final BlockingQueue tileQueue = new PriorityBlockingQueue<>(5, - new Comparator() { - @Override - public int compare(Tile o1, Tile o2) { - if (o1.getPriority() == Tile.Priority.Low && o2.getPriority() == Tile.Priority.High) { - return 1; - } - if (o1.getPriority() == Tile.Priority.High && o2.getPriority() == Tile.Priority.Low) { - return -1; - } - return 0; - - } - - @Override - public boolean equals(Object obj) { - return obj == this; - } - }); - - /** - * Subclasses may override this method to provide their own executor - * services. This method will be called each time a tile needs to be loaded. - * Implementations should cache the ExecutorService when possible. - * - * @return ExecutorService to load tiles with - */ - protected synchronized ExecutorService getService() { - if (service == null) { - //System.out.println("creating an executor service with a threadpool of size " + threadPoolSize); - service = Executors.newFixedThreadPool(threadPoolSize, new ThreadFactory() { - private int count = 0; - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r, "tile-pool-" + count++); - t.setPriority(Thread.MIN_PRIORITY); - t.setDaemon(true); - return t; - } - }); - } - return service; - } - - /** - * Set the number of threads to use for loading the tiles. This controls the - * number of threads used by the ExecutorService returned from getService(). - * Note, this method should be called before loading the first tile. Calls - * after the first tile are loaded will have no effect by default. - * - * @param size - */ - public void setThreadPoolSize(int size) { - if (size <= 0) { - throw new IllegalArgumentException("size invalid: " + size + ". The size of the threadpool must be greater than 0."); - } - threadPoolSize = size; - } - - @SuppressWarnings("unchecked") - @Override - protected synchronized void startLoading(Tile tile) { - if (tile.isLoading()) { - System.out.println("already loading. bailing"); - return; - } - tile.setLoading(true); - try { - tileQueue.put(tile); - getService().submit(createTileRunner(tile)); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - @Override - public void load(Tile tile) { - /* - * 3 strikes and you're out. Attempt to load the url. If it fails, - * decrement the number of tries left and try again. Log failures. - * If I run out of try s just get out. This way, if there is some - * kind of serious failure, I can get out and let other tiles - * try to load. - */ - //final Tile tile = tileQueue.remove(); - - int trys = 3; - while (!tile.isLoaded() && trys > 0) { - try { - BufferedImage img = null; - URI uri = getURI(tile); - img = cache.get(uri); - if (img == null) { - byte[] bimg = cacheInputStream(uri.toURL()); - img = GraphicsUtilities.loadCompatibleImage(new ByteArrayInputStream(bimg));//ImageIO.read(new URL(tile.url)); - cache.put(uri, bimg, img); - img = cache.get(uri); - } - if (img == null) { - System.out.println("error loading: " + uri); - LOG.log(Level.INFO, "Failed to load: " + uri); - trys--; - } else { - final BufferedImage i = img; - tile.image = new SoftReference<>(i); - tile.setLoaded(true); - } - } catch (OutOfMemoryError memErr) { - cache.needMoreMemory(); - } catch (Throwable e) { - LOG.log(Level.SEVERE, - "Failed to load a tile at url: " + tile.getURL() + ", retrying", e); - //temp - System.err.println("Failed to load a tile at url: " + tile.getURL()); - e.printStackTrace(); - ///temp - Object oldError = tile.getError(); - tile.setError(e); - tile.firePropertyChangeOnEDT("loadingError", oldError, e); - if (trys == 0) { - tile.firePropertyChangeOnEDT("unrecoverableError", null, e); - } else { - trys--; - } - } - } - tile.setLoading(false); - } - - /** - * Gets the full URI of a tile. - * - * @param tile - * @throws java.net.URISyntaxException - * @return URI - */ - protected URI getURI(Tile tile) throws URISyntaxException { - if (tile.getURL() == null) { - return null; - } - return new URI(tile.getURL()); - } - - private byte[] cacheInputStream(URL url) throws IOException { - InputStream ins = url.openStream(); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - byte[] buf = new byte[256]; - while (true) { - int n = ins.read(buf); - if (n == -1) { - break; - } - bout.write(buf, 0, n); - } - return bout.toByteArray(); - } - - /** - * Subclasses can override this if they need custom TileRunners for some - * reason - * - * @param tile Tile - * @return Runnable - */ - protected Runnable createTileRunner(Tile tile) { - return new TileRunner(); - } - - /** - * Increase the priority of this tile so it will be loaded sooner. - * @param tile Tile - */ - public synchronized void promote(Tile tile) { - if (tileQueue.contains(tile)) { - try { - tileQueue.remove(tile); - tile.setPriority(Tile.Priority.High); - tileQueue.put(tile); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - } - - /** - * An inner class which actually loads the tiles. Used by the thread queue. - * Subclasses can override this if necessary. - */ - private class TileRunner implements Runnable { - //private Tile tile; - //private BlockingQueue tileQueue; - - //public TileRunner(BlockingQueue tileQueue) { - //this.tileQueue = tileQueue; - //this.tile = tile; - //} - /** - * Gets the full URI of a tile. - * - * @param tile - * @throws java.net.URISyntaxException - * @return - */ - protected URI getURI(Tile tile) throws URISyntaxException { - if (tile.getURL() == null) { - return null; - } - return new URI(tile.getURL()); - } - - /** - * implementation of the Runnable interface. - */ - @Override - public void run() { - /* - * 3 strikes and you're out. Attempt to load the url. If it fails, - * decrement the number of tries left and try again. Log failures. - * If I run out of try s just get out. This way, if there is some - * kind of serious failure, I can get out and let other tiles - * try to load. - */ - final Tile tile = tileQueue.remove(); - - int trys = 3; - while (!tile.isLoaded() && trys > 0) { - try { - BufferedImage img = null; - URI uri = getURI(tile); - img = cache.get(uri); - if (img == null) { - byte[] bimg = cacheInputStream(uri.toURL()); - img = GraphicsUtilities.loadCompatibleImage(new ByteArrayInputStream(bimg));//ImageIO.read(new URL(tile.url)); - cache.put(uri, bimg, img); - img = cache.get(uri); - } - if (img == null) { - System.out.println("error loading: " + uri); - LOG.log(Level.INFO, "Failed to load: " + uri); - trys--; - } else { - final BufferedImage i = img; - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - tile.image = new SoftReference<>(i); - tile.setLoaded(true); - } - }); - } - } catch (OutOfMemoryError memErr) { - cache.needMoreMemory(); - } catch (Throwable e) { - LOG.log(Level.SEVERE, - "Failed to load a tile at url: " + tile.getURL() + ", retrying", e); - //temp - System.err.println("Failed to load a tile at url: " + tile.getURL()); - e.printStackTrace(); - ///temp - Object oldError = tile.getError(); - tile.setError(e); - tile.firePropertyChangeOnEDT("loadingError", oldError, e); - if (trys == 0) { - tile.firePropertyChangeOnEDT("unrecoverableError", null, e); - } else { - trys--; - } - } - } - tile.setLoading(false); - } - - private byte[] cacheInputStream(URL url) throws IOException { - InputStream ins = url.openStream(); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - byte[] buf = new byte[256]; - while (true) { - int n = ins.read(buf); - if (n == -1) { - break; - } - bout.write(buf, 0, n); - } - return bout.toByteArray(); - } - } -} +package org.meteoinfo.data.mapdata.webmap; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.SwingUtilities; + +import org.meteoinfo.common.util.GraphicsUtilities; +import org.meteoinfo.global.util.GeoUtil; + +/** + * The + * AbstractTileFactory provides a basic implementation for the + * TileFactory. + */ +public abstract class AbstractTileFactory extends TileFactory { + + private static final Logger LOG = Logger.getLogger(AbstractTileFactory.class.getName()); + + /** + * Creates a new instance of DefaultTileFactory using the spcified + * TileFactoryInfo + * + * @param info a TileFactoryInfo to configure this TileFactory + */ + public AbstractTileFactory(TileFactoryInfo info) { + super(info); + } + //private static final boolean doEagerLoading = true; + private int threadPoolSize = 4; + private ExecutorService service; + //TODO the tile map should be static ALWAYS, regardless of the number + //of GoogleTileFactories because each tile is, really, a singleton. + private final Map tileMap = new HashMap<>(); + private TileCache cache = new TileCache(); + + /** + * Returns + * + * @param pixelCoordinate + * @return + */ + //public TilePoint getTileCoordinate(Point2D pixelCoordinate) { + // return GeoUtil.getTileCoordinate(pixelCoordinate, getInfo()); + //} + /** + * Returns the tile that is located at the given tilePoint for this zoom. + * For example, if getMapSize() returns 10x20 for this zoom, and the + * tilePoint is (3,5), then the appropriate tile will be located and + * returned. + * + * @param x X index + * @param y Y index + * @param zoom Zoom value + * @return Tile + */ + @Override + public Tile getTile(int x, int y, int zoom) { + return getTile(x, y, zoom, true); + } + + private Tile getTile(int tpx, int tpy, int zoom, boolean eagerLoad) { + //wrap the tiles horizontally --> mod the X with the max width + //and use that + int tileX = tpx;//tilePoint.getX(); + int numTilesWide = (int) getMapSize(zoom).getWidth(); + if (tileX < 0) { + tileX = numTilesWide - (Math.abs(tileX) % numTilesWide); + } + + tileX = tileX % numTilesWide; + int tileY = tpy; + //TilePoint tilePoint = new TilePoint(tileX, tpy); + String url = getInfo().getTileUrl(tileX, tileY, zoom);//tilePoint); + //System.out.println("loading: " + url); + + + Tile.Priority pri = Tile.Priority.High; + if (!eagerLoad) { + pri = Tile.Priority.Low; + } + Tile tile = null; + //System.out.println("testing for validity: " + tilePoint + " zoom = " + zoom); + if (!tileMap.containsKey(url)) { + if (!GeoUtil.isValidTile(tileX, tileY, zoom, getInfo())) { + tile = new Tile(tileX, tileY, zoom); + } else { + tile = new Tile(tileX, tileY, zoom, url, pri, this); + //load(tile); + startLoading(tile); + } + tileMap.put(url, tile); + } else { + tile = tileMap.get(url); + // if its in the map but is low and isn't loaded yet + // but we are in high mode + if (tile.getPriority() == Tile.Priority.Low && eagerLoad && !tile.isLoaded()) { + //System.out.println("in high mode and want a low"); + //tile.promote(); + promote(tile); + } + } + + /* + if (eagerLoad && doEagerLoading) { + for (int i = 0; i<1; i++) { + for (int j = 0; j<1; j++) { + // preload the 4 tiles under the current one + if(zoom > 0) { + eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2, zoom-1); + eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2, zoom-1); + eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2+1, zoom-1); + eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2+1, zoom-1); + } + } + } + }*/ + + + return tile; + } + + /* + private void eagerlyLoad(int x, int y, int zoom) { + TilePoint t1 = new TilePoint(x,y); + if(!isLoaded(t1,zoom)) { + getTile(t1,zoom,false); + } + } + */ + // private boolean isLoaded(int x, int y, int zoom) { + // String url = getInfo().getTileUrl(zoom,x,y); + // return tileMap.containsKey(url); + // } + public TileCache getTileCache() { + return cache; + } + + public void setTileCache(TileCache cache) { + this.cache = cache; + } + /** + * ==== threaded tile loading stuff === + */ + /** + * Thread pool for loading the tiles + */ + private static final BlockingQueue tileQueue = new PriorityBlockingQueue<>(5, + new Comparator() { + @Override + public int compare(Tile o1, Tile o2) { + if (o1.getPriority() == Tile.Priority.Low && o2.getPriority() == Tile.Priority.High) { + return 1; + } + if (o1.getPriority() == Tile.Priority.High && o2.getPriority() == Tile.Priority.Low) { + return -1; + } + return 0; + + } + + @Override + public boolean equals(Object obj) { + return obj == this; + } + }); + + /** + * Subclasses may override this method to provide their own executor + * services. This method will be called each time a tile needs to be loaded. + * Implementations should cache the ExecutorService when possible. + * + * @return ExecutorService to load tiles with + */ + protected synchronized ExecutorService getService() { + if (service == null) { + //System.out.println("creating an executor service with a threadpool of size " + threadPoolSize); + service = Executors.newFixedThreadPool(threadPoolSize, new ThreadFactory() { + private int count = 0; + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r, "tile-pool-" + count++); + t.setPriority(Thread.MIN_PRIORITY); + t.setDaemon(true); + return t; + } + }); + } + return service; + } + + /** + * Set the number of threads to use for loading the tiles. This controls the + * number of threads used by the ExecutorService returned from getService(). + * Note, this method should be called before loading the first tile. Calls + * after the first tile are loaded will have no effect by default. + * + * @param size + */ + public void setThreadPoolSize(int size) { + if (size <= 0) { + throw new IllegalArgumentException("size invalid: " + size + ". The size of the threadpool must be greater than 0."); + } + threadPoolSize = size; + } + + @SuppressWarnings("unchecked") + @Override + protected synchronized void startLoading(Tile tile) { + if (tile.isLoading()) { + System.out.println("already loading. bailing"); + return; + } + tile.setLoading(true); + try { + tileQueue.put(tile); + getService().submit(createTileRunner(tile)); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void load(Tile tile) { + /* + * 3 strikes and you're out. Attempt to load the url. If it fails, + * decrement the number of tries left and try again. Log failures. + * If I run out of try s just get out. This way, if there is some + * kind of serious failure, I can get out and let other tiles + * try to load. + */ + //final Tile tile = tileQueue.remove(); + + int trys = 3; + while (!tile.isLoaded() && trys > 0) { + try { + BufferedImage img = null; + URI uri = getURI(tile); + img = cache.get(uri); + if (img == null) { + byte[] bimg = cacheInputStream(uri.toURL()); + img = GraphicsUtilities.loadCompatibleImage(new ByteArrayInputStream(bimg));//ImageIO.read(new URL(tile.url)); + cache.put(uri, bimg, img); + img = cache.get(uri); + } + if (img == null) { + System.out.println("error loading: " + uri); + LOG.log(Level.INFO, "Failed to load: " + uri); + trys--; + } else { + final BufferedImage i = img; + tile.image = new SoftReference<>(i); + tile.setLoaded(true); + } + } catch (OutOfMemoryError memErr) { + cache.needMoreMemory(); + } catch (Throwable e) { + LOG.log(Level.SEVERE, + "Failed to load a tile at url: " + tile.getURL() + ", retrying", e); + //temp + System.err.println("Failed to load a tile at url: " + tile.getURL()); + e.printStackTrace(); + ///temp + Object oldError = tile.getError(); + tile.setError(e); + tile.firePropertyChangeOnEDT("loadingError", oldError, e); + if (trys == 0) { + tile.firePropertyChangeOnEDT("unrecoverableError", null, e); + } else { + trys--; + } + } + } + tile.setLoading(false); + } + + /** + * Gets the full URI of a tile. + * + * @param tile + * @throws java.net.URISyntaxException + * @return URI + */ + protected URI getURI(Tile tile) throws URISyntaxException { + if (tile.getURL() == null) { + return null; + } + return new URI(tile.getURL()); + } + + private byte[] cacheInputStream(URL url) throws IOException { + InputStream ins = url.openStream(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] buf = new byte[256]; + while (true) { + int n = ins.read(buf); + if (n == -1) { + break; + } + bout.write(buf, 0, n); + } + return bout.toByteArray(); + } + + /** + * Subclasses can override this if they need custom TileRunners for some + * reason + * + * @param tile Tile + * @return Runnable + */ + protected Runnable createTileRunner(Tile tile) { + return new TileRunner(); + } + + /** + * Increase the priority of this tile so it will be loaded sooner. + * @param tile Tile + */ + public synchronized void promote(Tile tile) { + if (tileQueue.contains(tile)) { + try { + tileQueue.remove(tile); + tile.setPriority(Tile.Priority.High); + tileQueue.put(tile); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + /** + * An inner class which actually loads the tiles. Used by the thread queue. + * Subclasses can override this if necessary. + */ + private class TileRunner implements Runnable { + //private Tile tile; + //private BlockingQueue tileQueue; + + //public TileRunner(BlockingQueue tileQueue) { + //this.tileQueue = tileQueue; + //this.tile = tile; + //} + /** + * Gets the full URI of a tile. + * + * @param tile + * @throws java.net.URISyntaxException + * @return + */ + protected URI getURI(Tile tile) throws URISyntaxException { + if (tile.getURL() == null) { + return null; + } + return new URI(tile.getURL()); + } + + /** + * implementation of the Runnable interface. + */ + @Override + public void run() { + /* + * 3 strikes and you're out. Attempt to load the url. If it fails, + * decrement the number of tries left and try again. Log failures. + * If I run out of try s just get out. This way, if there is some + * kind of serious failure, I can get out and let other tiles + * try to load. + */ + final Tile tile = tileQueue.remove(); + + int trys = 3; + while (!tile.isLoaded() && trys > 0) { + try { + BufferedImage img = null; + URI uri = getURI(tile); + img = cache.get(uri); + if (img == null) { + byte[] bimg = cacheInputStream(uri.toURL()); + img = GraphicsUtilities.loadCompatibleImage(new ByteArrayInputStream(bimg));//ImageIO.read(new URL(tile.url)); + cache.put(uri, bimg, img); + img = cache.get(uri); + } + if (img == null) { + System.out.println("error loading: " + uri); + LOG.log(Level.INFO, "Failed to load: " + uri); + trys--; + } else { + final BufferedImage i = img; + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + tile.image = new SoftReference<>(i); + tile.setLoaded(true); + } + }); + } + } catch (OutOfMemoryError memErr) { + cache.needMoreMemory(); + } catch (Throwable e) { + LOG.log(Level.SEVERE, + "Failed to load a tile at url: " + tile.getURL() + ", retrying", e); + //temp + System.err.println("Failed to load a tile at url: " + tile.getURL()); + e.printStackTrace(); + ///temp + Object oldError = tile.getError(); + tile.setError(e); + tile.firePropertyChangeOnEDT("loadingError", oldError, e); + if (trys == 0) { + tile.firePropertyChangeOnEDT("unrecoverableError", null, e); + } else { + trys--; + } + } + } + tile.setLoading(false); + } + + private byte[] cacheInputStream(URL url) throws IOException { + InputStream ins = url.openStream(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] buf = new byte[256]; + while (true) { + int n = ins.read(buf); + if (n == -1) { + break; + } + bout.write(buf, 0, n); + } + return bout.toByteArray(); + } + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mathparser/MathParser.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mathparser/MathParser.java index b3489cc1..418d8040 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mathparser/MathParser.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mathparser/MathParser.java @@ -1,331 +1,330 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.data.mathparser; - -import java.beans.Expression; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Stack; -import org.meteoinfo.data.meteodata.MeteoDataInfo; -import org.meteoinfo.global.MIMath; - -/** - * - * @author yaqiang - */ -public class MathParser { - // - - private boolean _isGridData; - private StringBuilder _buffer = new StringBuilder(); - private Stack _symbolStack = new Stack(); - private Queue _expressionQueue = new LinkedList(); - private Map _expressionCache = new HashMap(); - private Stack _calculationStack = new Stack(); - private Stack _parameters = new Stack(); - private List _variables = new ArrayList(); - private StringReader _expressionReader; - private MeteoDataInfo _meteoDataInfo = null; - // - // - - /** - * Constructor - */ - public MathParser() { - } - - /** - * Constructor - * - * @param aDataInfo MeteoDataInfo - */ - public MathParser(MeteoDataInfo aDataInfo) { - _meteoDataInfo = aDataInfo; - _isGridData = aDataInfo.isGridData(); - _variables = aDataInfo.getDataInfo().getVariableNames(); - } - // - // - // - // - - /** - * Evaluates the specified expression - * - * @param expression The expression to evaluate - * @return The evaluated result - */ - public Object evaluate(String expression) throws ParseException, IOException { - if (expression == null || expression.isEmpty()) { - throw new java.lang.IllegalArgumentException("expression"); - } - - _expressionReader = new StringReader(expression); - _symbolStack.clear(); - _expressionQueue.clear(); - - parseExpressionToQueue(); - - Object result = calculateFromQueue(); - - //_variables[AnswerVariable] = result; - return result; - } - - private void parseExpressionToQueue() throws ParseException, IOException { - int ic; - char c; - while ((ic = _expressionReader.read()) != -1) { - c = (char) ic; - if (Character.isWhitespace(c)) { - continue; - } - if (tryNumber(c)) { - continue; - } - if (tryString(c)) { - continue; - } - if (tryStartGroup(c)) { - continue; - } - if (tryOperator(c)) { - continue; - } - if (tryEndGroup(c)) { - continue; - } - //if (TryConvert(c)) - // continue; - throw new ParseException("Invalid character encountered" + c); - } - - processSymbolStack(); - } - - private boolean tryNumber(char c) throws IOException, ParseException { - boolean isNumber = NumberExpression.isNumber(c); - boolean isNegative = false; - if (NumberExpression.isNegativeSign(c)) { - if (_expressionQueue.size() == 0) { - isNegative = true; - } else if (_expressionQueue.size() > 0 && _symbolStack.size() > 0) { - if (((String) _symbolStack.peek()).equals("(")) { - isNegative = true; - } - } - } - - if (!isNumber && !isNegative) { - return false; - } - - _buffer.setLength(0); - _buffer.append(c); - - _expressionReader.mark(1); - char p = (char) _expressionReader.read(); - while (NumberExpression.isNumber(p)) { - _buffer.append(p); - _expressionReader.mark(1); - p = (char) _expressionReader.read(); - } - _expressionReader.reset(); - - double value; - try { - value = Double.parseDouble(_buffer.toString()); - } catch (Exception e) { - throw new ParseException("Invalid number format: " + _buffer); - } - - NumberExpression expression = new NumberExpression(value); - _expressionQueue.offer(expression); - - return true; - } - - private boolean tryString(char c) throws IOException, ParseException { - if (!Character.isLetter(c)) { - return false; - } - - _buffer.setLength(0); - _buffer.append(c); - - _expressionReader.mark(1); - char p = (char) _expressionReader.read(); - while (Character.isLetterOrDigit(p) || p == '_' || p == '@' || p == '.') { - _buffer.append(p); - _expressionReader.mark(1); - p = (char) _expressionReader.read(); - } - _expressionReader.reset(); - - if (_variables.contains(_buffer.toString())) { - Object value = getVariableValue(_buffer.toString()); - NumberExpression expression = new NumberExpression(value); - _expressionQueue.offer(expression); - - return true; - } - - if (FunctionExpression.isFunction(_buffer.toString())) { - _symbolStack.push(_buffer.toString()); - return true; - } - - throw new ParseException("Invalid variable: " + _buffer); - } - - private boolean tryStartGroup(char c) { - if (c != '(') { - return false; - } - - _symbolStack.push(String.valueOf(c)); - return true; - } - - private boolean tryOperator(char c) throws ParseException { - if (!OperatorExpression.isSymbol(c)) { - return false; - } - - boolean repeat; - String s = String.valueOf(c); - - do { - String p = _symbolStack.size() == 0 ? "" : _symbolStack.peek(); - repeat = false; - if (_symbolStack.size() == 0) { - _symbolStack.push(s); - } else if (p.equals("(")) { - _symbolStack.push(s); - } else if (precedence(s) > precedence(p)) { - _symbolStack.push(s); - } else { - IExpression e = getExpressionFromSymbol(_symbolStack.pop()); - _expressionQueue.offer(e); - repeat = true; - } - } while (repeat); - - return true; - } - - private boolean tryEndGroup(char c) throws ParseException { - if (c != ')') { - return false; - } - - boolean ok = false; - - while (_symbolStack.size() > 0) { - String p = _symbolStack.pop(); - if (p.equals("(")) { - ok = true; - break; - } - - IExpression e = getExpressionFromSymbol(p); - _expressionQueue.offer(e); - } - - if (!ok) { - throw new ParseException("Unbalance parenthese"); - } - - return true; - } - - private void processSymbolStack() throws ParseException { - while (_symbolStack.size() > 0) { - String p = _symbolStack.pop(); - if (p.length() == 1 && p.equals("(")) { - throw new ParseException("Unbalance parenthese"); - } - - IExpression e = getExpressionFromSymbol(p); - _expressionQueue.offer(e); - } - } - - private static int precedence(String c) { - String s = c.substring(0, 1); - if (c.length() == 1 && s.equals("*") || s.equals("/") || s.equals("%")) { - return 2; - } - - return 1; - } - - private IExpression getExpressionFromSymbol(String p) throws ParseException { - IExpression e; - - if (_expressionCache.containsKey(p)) { - e = _expressionCache.get(p); - } else if (OperatorExpression.isSymbol(p)) { - e = new OperatorExpression(p); - _expressionCache.put(p, e); - } else if (FunctionExpression.isFunction(p)) { - e = new FunctionExpression(p, false); - _expressionCache.put(p, e); - } //else if (ConvertExpression.IsConvertExpression(p)) - //{ - // e = new ConvertExpression(p); - // _expressionCache.Add(p, e); - //} - else { - throw new ParseException("Invalid symbol on stack" + p); - } - - return e; - } - - private Object calculateFromQueue() throws ParseException { - Object result; - _calculationStack.clear(); - - for (IExpression expression : _expressionQueue) { - if (_calculationStack.size() < expression.getArgumentCount()) { - throw new ParseException("Not enough numbers" + expression); - } - - _parameters.clear(); - for (int i = 0; i < expression.getArgumentCount(); i++) { - _parameters.push(_calculationStack.pop()); - } - - Object[] parameters = _parameters.toArray(); - MIMath.arrayReverse(parameters); - _calculationStack.push(expression.evaluate(parameters)); - } - - result = _calculationStack.pop(); - return result; - } - - private Object getVariableValue(String varName) { - if (_meteoDataInfo == null) { - return 100; - } else { - if (_isGridData) { - return _meteoDataInfo.getGridData(varName); - } else { - return _meteoDataInfo.getStationData(varName); - } - } - } - // -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.data.mathparser; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Stack; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.data.meteodata.MeteoDataInfo; + +/** + * + * @author yaqiang + */ +public class MathParser { + // + + private boolean _isGridData; + private StringBuilder _buffer = new StringBuilder(); + private Stack _symbolStack = new Stack(); + private Queue _expressionQueue = new LinkedList(); + private Map _expressionCache = new HashMap(); + private Stack _calculationStack = new Stack(); + private Stack _parameters = new Stack(); + private List _variables = new ArrayList(); + private StringReader _expressionReader; + private MeteoDataInfo _meteoDataInfo = null; + // + // + + /** + * Constructor + */ + public MathParser() { + } + + /** + * Constructor + * + * @param aDataInfo MeteoDataInfo + */ + public MathParser(MeteoDataInfo aDataInfo) { + _meteoDataInfo = aDataInfo; + _isGridData = aDataInfo.isGridData(); + _variables = aDataInfo.getDataInfo().getVariableNames(); + } + // + // + // + // + + /** + * Evaluates the specified expression + * + * @param expression The expression to evaluate + * @return The evaluated result + */ + public Object evaluate(String expression) throws ParseException, IOException { + if (expression == null || expression.isEmpty()) { + throw new java.lang.IllegalArgumentException("expression"); + } + + _expressionReader = new StringReader(expression); + _symbolStack.clear(); + _expressionQueue.clear(); + + parseExpressionToQueue(); + + Object result = calculateFromQueue(); + + //_variables[AnswerVariable] = result; + return result; + } + + private void parseExpressionToQueue() throws ParseException, IOException { + int ic; + char c; + while ((ic = _expressionReader.read()) != -1) { + c = (char) ic; + if (Character.isWhitespace(c)) { + continue; + } + if (tryNumber(c)) { + continue; + } + if (tryString(c)) { + continue; + } + if (tryStartGroup(c)) { + continue; + } + if (tryOperator(c)) { + continue; + } + if (tryEndGroup(c)) { + continue; + } + //if (TryConvert(c)) + // continue; + throw new ParseException("Invalid character encountered" + c); + } + + processSymbolStack(); + } + + private boolean tryNumber(char c) throws IOException, ParseException { + boolean isNumber = NumberExpression.isNumber(c); + boolean isNegative = false; + if (NumberExpression.isNegativeSign(c)) { + if (_expressionQueue.size() == 0) { + isNegative = true; + } else if (_expressionQueue.size() > 0 && _symbolStack.size() > 0) { + if (((String) _symbolStack.peek()).equals("(")) { + isNegative = true; + } + } + } + + if (!isNumber && !isNegative) { + return false; + } + + _buffer.setLength(0); + _buffer.append(c); + + _expressionReader.mark(1); + char p = (char) _expressionReader.read(); + while (NumberExpression.isNumber(p)) { + _buffer.append(p); + _expressionReader.mark(1); + p = (char) _expressionReader.read(); + } + _expressionReader.reset(); + + double value; + try { + value = Double.parseDouble(_buffer.toString()); + } catch (Exception e) { + throw new ParseException("Invalid number format: " + _buffer); + } + + NumberExpression expression = new NumberExpression(value); + _expressionQueue.offer(expression); + + return true; + } + + private boolean tryString(char c) throws IOException, ParseException { + if (!Character.isLetter(c)) { + return false; + } + + _buffer.setLength(0); + _buffer.append(c); + + _expressionReader.mark(1); + char p = (char) _expressionReader.read(); + while (Character.isLetterOrDigit(p) || p == '_' || p == '@' || p == '.') { + _buffer.append(p); + _expressionReader.mark(1); + p = (char) _expressionReader.read(); + } + _expressionReader.reset(); + + if (_variables.contains(_buffer.toString())) { + Object value = getVariableValue(_buffer.toString()); + NumberExpression expression = new NumberExpression(value); + _expressionQueue.offer(expression); + + return true; + } + + if (FunctionExpression.isFunction(_buffer.toString())) { + _symbolStack.push(_buffer.toString()); + return true; + } + + throw new ParseException("Invalid variable: " + _buffer); + } + + private boolean tryStartGroup(char c) { + if (c != '(') { + return false; + } + + _symbolStack.push(String.valueOf(c)); + return true; + } + + private boolean tryOperator(char c) throws ParseException { + if (!OperatorExpression.isSymbol(c)) { + return false; + } + + boolean repeat; + String s = String.valueOf(c); + + do { + String p = _symbolStack.size() == 0 ? "" : _symbolStack.peek(); + repeat = false; + if (_symbolStack.size() == 0) { + _symbolStack.push(s); + } else if (p.equals("(")) { + _symbolStack.push(s); + } else if (precedence(s) > precedence(p)) { + _symbolStack.push(s); + } else { + IExpression e = getExpressionFromSymbol(_symbolStack.pop()); + _expressionQueue.offer(e); + repeat = true; + } + } while (repeat); + + return true; + } + + private boolean tryEndGroup(char c) throws ParseException { + if (c != ')') { + return false; + } + + boolean ok = false; + + while (_symbolStack.size() > 0) { + String p = _symbolStack.pop(); + if (p.equals("(")) { + ok = true; + break; + } + + IExpression e = getExpressionFromSymbol(p); + _expressionQueue.offer(e); + } + + if (!ok) { + throw new ParseException("Unbalance parenthese"); + } + + return true; + } + + private void processSymbolStack() throws ParseException { + while (_symbolStack.size() > 0) { + String p = _symbolStack.pop(); + if (p.length() == 1 && p.equals("(")) { + throw new ParseException("Unbalance parenthese"); + } + + IExpression e = getExpressionFromSymbol(p); + _expressionQueue.offer(e); + } + } + + private static int precedence(String c) { + String s = c.substring(0, 1); + if (c.length() == 1 && s.equals("*") || s.equals("/") || s.equals("%")) { + return 2; + } + + return 1; + } + + private IExpression getExpressionFromSymbol(String p) throws ParseException { + IExpression e; + + if (_expressionCache.containsKey(p)) { + e = _expressionCache.get(p); + } else if (OperatorExpression.isSymbol(p)) { + e = new OperatorExpression(p); + _expressionCache.put(p, e); + } else if (FunctionExpression.isFunction(p)) { + e = new FunctionExpression(p, false); + _expressionCache.put(p, e); + } //else if (ConvertExpression.IsConvertExpression(p)) + //{ + // e = new ConvertExpression(p); + // _expressionCache.Add(p, e); + //} + else { + throw new ParseException("Invalid symbol on stack" + p); + } + + return e; + } + + private Object calculateFromQueue() throws ParseException { + Object result; + _calculationStack.clear(); + + for (IExpression expression : _expressionQueue) { + if (_calculationStack.size() < expression.getArgumentCount()) { + throw new ParseException("Not enough numbers" + expression); + } + + _parameters.clear(); + for (int i = 0; i < expression.getArgumentCount(); i++) { + _parameters.push(_calculationStack.pop()); + } + + Object[] parameters = _parameters.toArray(); + MIMath.arrayReverse(parameters); + _calculationStack.push(expression.evaluate(parameters)); + } + + result = _calculationStack.pop(); + return result; + } + + private Object getVariableValue(String varName) { + if (_meteoDataInfo == null) { + return 100; + } else { + if (_isGridData) { + return _meteoDataInfo.getGridData(varName); + } else { + return _meteoDataInfo.getStationData(varName); + } + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DataInfo.java index a047c535..cfb18098 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DataInfo.java @@ -19,7 +19,7 @@ import java.time.Period; import java.util.ArrayList; import java.util.List; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.projection.KnownCoordinateSystems; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DrawMeteoData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DrawMeteoData.java index ddc4d2cf..dbe119ad 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DrawMeteoData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/DrawMeteoData.java @@ -14,6 +14,9 @@ package org.meteoinfo.data.meteodata; import org.apache.commons.lang3.ArrayUtils; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.data.DataMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; @@ -21,10 +24,10 @@ import org.meteoinfo.data.dataframe.DataFrame; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.drawing.ContourDraw; import org.meteoinfo.drawing.Draw; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.legend.MarkerType; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.layer.LayerDrawType; import org.meteoinfo.layer.VectorLayer; @@ -45,10 +48,9 @@ import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayUtil; + import org.meteoinfo.data.GridArray; import org.meteoinfo.data.XYListDataset; -import org.meteoinfo.global.Extent; import org.meteoinfo.layer.ImageLayer; import org.meteoinfo.layer.RasterLayer; import org.meteoinfo.layer.WorldFilePara; @@ -107,7 +109,7 @@ public class DrawMeteoData { } aPolyline.setPoints(pList); aPolyline.setValue(i); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); int shapeNum = layer.getShapeNum(); try { @@ -157,7 +159,7 @@ public class DrawMeteoData { } aPolyline.setPoints(pList); aPolyline.setValue(i); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); int shapeNum = layer.getShapeNum(); try { @@ -233,7 +235,7 @@ public class DrawMeteoData { PolylineShape aPolyline = new PolylineShape(); aPolyline.setPoints(ps); aPolyline.setValue(i); - aPolyline.setExtent(MIMath.getPointsExtent(ps)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(ps)); int shapeNum = layer.getShapeNum(); try { @@ -368,7 +370,7 @@ public class DrawMeteoData { PolylineShape aPolyline = new PolylineShape(); aPolyline.setPoints(ps); aPolyline.setValue(k); - aPolyline.setExtent(MIMath.getPointsExtent(ps)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(ps)); int shapeNum = layer.getShapeNum(); try { @@ -509,7 +511,7 @@ public class DrawMeteoData { PolylineZShape aPolyline = new PolylineZShape(); aPolyline.setPoints(ps); aPolyline.setValue(0); - aPolyline.setExtent(MIMath.getPointsExtent(ps)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(ps)); int shapeNum = layer.getShapeNum(); try { @@ -621,7 +623,7 @@ public class DrawMeteoData { PolylineZShape aPolyline = new PolylineZShape(); aPolyline.setPoints(ps); aPolyline.setValue(0); - aPolyline.setExtent(MIMath.getPointsExtent(ps)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(ps)); int shapeNum = layer.getShapeNum(); try { @@ -740,7 +742,7 @@ public class DrawMeteoData { } aPolyline.setPoints(pList); aPolyline.setValue(aValue); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); int shapeNum = aLayer.getShapeNum(); try { @@ -826,7 +828,7 @@ public class DrawMeteoData { } aPolyline.setPoints(pList); aPolyline.setValue(aValue); - aPolyline.setExtent(MIMath.getPointsExtent(pList)); + aPolyline.setExtent(GeometryUtil.getPointsExtent(pList)); int shapeNum = aLayer.getShapeNum(); try { if (aLayer.editInsertShape(aPolyline, shapeNum)) { @@ -968,7 +970,7 @@ public class DrawMeteoData { } PolygonShape aPolygonShape = new PolygonShape(); aPolygonShape.setPoints(pList); - aPolygonShape.setExtent(MIMath.getPointsExtent(pList)); + aPolygonShape.setExtent(GeometryUtil.getPointsExtent(pList)); aPolygonShape.lowValue = aValue; if (aPolygon.HasHoles()) { for (PolyLine holeLine : aPolygon.HoleLines) { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/GridDataSetting.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/GridDataSetting.java index 8b3078c0..c8939246 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/GridDataSetting.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/GridDataSetting.java @@ -1,36 +1,36 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.data.meteodata; - -import org.meteoinfo.global.Extent; - -/** - * - * @author yaqiang - */ -public class GridDataSetting { - /// - /// Data extent - /// - - public Extent dataExtent = new Extent(); - /// - /// X number - /// - public int xNum; - /// - /// Y number - /// - public int yNum; -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.data.meteodata; + +import org.meteoinfo.common.Extent; + +/** + * + * @author yaqiang + */ +public class GridDataSetting { + /// + /// Data extent + /// + + public Extent dataExtent = new Extent(); + /// + /// X number + /// + public int xNum; + /// + /// Y number + /// + public int yNum; +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/MeteoDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/MeteoDataInfo.java index 9a603089..90fae8a6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/MeteoDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/MeteoDataInfo.java @@ -14,6 +14,8 @@ package org.meteoinfo.data.meteodata; import java.io.File; + +import org.meteoinfo.common.MIMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.arl.ARLDataInfo; @@ -30,14 +32,15 @@ import java.io.IOException; import java.time.LocalDateTime; import java.time.Duration; import java.util.ArrayList; + +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.projection.info.ProjectionInfo; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayMath; + import org.meteoinfo.data.meteodata.mm5.MM5DataInfo; import org.meteoinfo.data.meteodata.mm5.MM5IMDataInfo; -import org.meteoinfo.global.MIMath; import org.meteoinfo.data.mathparser.MathParser; import org.meteoinfo.data.mathparser.ParseException; import org.meteoinfo.data.meteodata.awx.AWXDataInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationModelData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationModelData.java index eba884f3..b1054aaa 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationModelData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationModelData.java @@ -1,100 +1,101 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.data.meteodata; - -import org.meteoinfo.global.Extent; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author yaqiang - */ -public class StationModelData { - // - - private List _data = new ArrayList<>(); - private Extent _dataExtent = new Extent(); - private double _missingValue = -9999.0; - // - // - // - // - - /** - * Get data - * - * @return Data - */ - public List getData() { - return _data; - } - - /** - * Set data - * - * @param value Data - */ - public void setData(List value) { - _data = value; - } - - /** - * Get data extent - * - * @return Data extent - */ - public Extent getDataExtent() { - return _dataExtent; - } - - /** - * Set data extent - * - * @param value Data extent - */ - public void setDataExtent(Extent value) { - _dataExtent = value; - } - - /** - * Get missing data - * - * @return Missing data - */ - public double getMissingValue() { - return _missingValue; - } - - /** - * Set missing data - * - * @param value Missing data - */ - public void setMissingValue(double value) { - _missingValue = value; - } - - /** - * Get data number - * - * @return Data number - */ - public int getDataNum() { - return _data.size(); - } - // - // - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.data.meteodata; + +import org.meteoinfo.common.Extent; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author yaqiang + */ +public class StationModelData { + // + + private List _data = new ArrayList<>(); + private Extent _dataExtent = new Extent(); + private double _missingValue = -9999.0; + // + // + // + // + + /** + * Get data + * + * @return Data + */ + public List getData() { + return _data; + } + + /** + * Set data + * + * @param value Data + */ + public void setData(List value) { + _data = value; + } + + /** + * Get data extent + * + * @return Data extent + */ + public Extent getDataExtent() { + return _dataExtent; + } + + /** + * Set data extent + * + * @param value Data extent + */ + public void setDataExtent(Extent value) { + _dataExtent = value; + } + + /** + * Get missing data + * + * @return Missing data + */ + public double getMissingValue() { + return _missingValue; + } + + /** + * Set missing data + * + * @param value Missing data + */ + public void setMissingValue(double value) { + _missingValue = value; + } + + /** + * Get data number + * + * @return Data number + */ + public int getDataNum() { + return _data.size(); + } + // + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/Variable.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/Variable.java index 5f26701b..eb401e5a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/Variable.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/Variable.java @@ -13,13 +13,14 @@ */ package org.meteoinfo.data.meteodata; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.ndarray.Dimension; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import org.meteoinfo.global.util.JDateUtil; + import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.Range; import org.meteoinfo.ndarray.Section; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java index 9b4f938a..61daded8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java @@ -13,17 +13,19 @@ */ package org.meteoinfo.data.meteodata.arl; -import org.meteoinfo.bak.ArrayMath; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.util.GlobalUtil; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; @@ -40,7 +42,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.meteodata.MeteoDataType; -import org.meteoinfo.global.MIMath; import org.locationtech.proj4j.proj.Projection; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java index 7d18e0cf..9f4ed6d4 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java @@ -13,13 +13,14 @@ */ package org.meteoinfo.data.meteodata.ascii; +import org.meteoinfo.common.MIMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/LonLatStationDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/LonLatStationDataInfo.java index df0cb460..ffd5ec4a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/LonLatStationDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/LonLatStationDataInfo.java @@ -13,14 +13,16 @@ */ package org.meteoinfo.data.meteodata.ascii; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; import org.meteoinfo.data.meteodata.IStationDataInfo; import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -34,8 +36,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import org.meteoinfo.data.meteodata.MeteoDataType; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.io.FileCharsetDetector; +import org.meteoinfo.common.io.FileCharsetDetector; import org.meteoinfo.ndarray.Array; import org.meteoinfo.data.meteodata.Attribute; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/awx/AWXDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/awx/AWXDataInfo.java index 82e4ce80..aaf3ca6f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/awx/AWXDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/awx/AWXDataInfo.java @@ -15,6 +15,8 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.Extent; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; @@ -28,7 +30,6 @@ import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.Extent; import org.meteoinfo.layer.WorldFilePara; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/bandraster/GeoTiffDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/bandraster/GeoTiffDataInfo.java index 21139931..1ee41533 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/bandraster/GeoTiffDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/bandraster/GeoTiffDataInfo.java @@ -18,11 +18,12 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayMath; + import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.mapdata.geotiff.GeoTiff; import org.meteoinfo.data.meteodata.DataInfo; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; @@ -149,7 +150,7 @@ public class GeoTiffDataInfo extends DataInfo implements IGridDataInfo { public Array read(String varName, int[] origin, int[] size, int[] stride) { try { Array array = read(varName); - array = ArrayMath.section(array, origin, size, stride); + array = ArrayMath.section(array, origin, size, stride); return array; } catch (InvalidRangeException ex) { Logger.getLogger(GeoTiffDataInfo.class.getName()).log(Level.SEVERE, null, ex); diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java index d56d8396..a5b2f57d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java @@ -13,6 +13,8 @@ */ package org.meteoinfo.data.meteodata.grads; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; import org.meteoinfo.ndarray.Dimension; @@ -20,7 +22,7 @@ import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.io.EndianDataOutputStream; +import org.meteoinfo.common.io.EndianDataOutputStream; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; @@ -51,7 +53,6 @@ import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.arl.ARLDataInfo; -import org.meteoinfo.global.Extent; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.IndexIterator; @@ -59,7 +60,6 @@ import org.meteoinfo.ndarray.InvalidRangeException; import org.meteoinfo.ndarray.Range; import org.meteoinfo.ndarray.Section; import org.meteoinfo.data.meteodata.Attribute; -import org.meteoinfo.global.util.JDateUtil; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grib/grib2/GRIB2DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grib/grib2/GRIB2DataInfo.java index 7c685068..fee51b99 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grib/grib2/GRIB2DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grib/grib2/GRIB2DataInfo.java @@ -11,6 +11,8 @@ import java.util.Date; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.Bytes2Number; import org.meteoinfo.data.DataMath; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; @@ -18,7 +20,6 @@ import org.meteoinfo.data.meteodata.DataInfo; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Bytes2Number; import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.ndarray.Array; import org.meteoinfo.data.meteodata.Attribute; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java index 03b5b69a..0bd7d4c8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java @@ -13,10 +13,10 @@ */ package org.meteoinfo.data.meteodata.hysplit; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.meteodata.ascii.ASCIIGridDataInfo; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITPartDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITPartDataInfo.java index 78d28ff7..6304317c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITPartDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITPartDataInfo.java @@ -13,13 +13,14 @@ */ package org.meteoinfo.data.meteodata.hysplit; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.dataframe.Column; import org.meteoinfo.data.dataframe.ColumnIndex; import org.meteoinfo.data.dataframe.DataFrame; import org.meteoinfo.data.dataframe.Index; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; @@ -27,7 +28,6 @@ import org.meteoinfo.data.meteodata.IStationDataInfo; import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; import java.io.IOException; import java.io.RandomAccessFile; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITTrajDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITTrajDataInfo.java index 1cdad49d..c73b8388 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITTrajDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITTrajDataInfo.java @@ -13,15 +13,15 @@ */ package org.meteoinfo.data.meteodata.hysplit; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.TrajDataInfo; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import java.awt.Color; import java.io.BufferedReader; @@ -466,7 +466,7 @@ public class HYSPLITTrajDataInfo extends DataInfo implements TrajDataInfo { TrajNum += 1; aPolyline.setValue(TrajNum); aPolyline.setPoints(PointList.get(i)); - aPolyline.setExtent(MIMath.getPointsExtent(aPolyline.getPoints())); + aPolyline.setExtent(GeometryUtil.getPointsExtent(aPolyline.getPoints())); int shapeNum = aLayer.getShapeNum(); if (aLayer.editInsertShape(aPolyline, shapeNum)) { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/metar/METARDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/metar/METARDataInfo.java index 9b10def9..f5945877 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/metar/METARDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/metar/METARDataInfo.java @@ -13,9 +13,11 @@ */ package org.meteoinfo.data.meteodata.metar; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; @@ -23,8 +25,7 @@ import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModel; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MDFSDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MDFSDataInfo.java index 05ec3edd..e2bb43a7 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MDFSDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MDFSDataInfo.java @@ -1,5 +1,7 @@ package org.meteoinfo.data.meteodata.micaps; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; @@ -8,11 +10,7 @@ import org.meteoinfo.data.dataframe.ColumnIndex; import org.meteoinfo.data.dataframe.DataFrame; import org.meteoinfo.data.dataframe.Index; import org.meteoinfo.data.meteodata.*; -import org.meteoinfo.data.meteodata.awx.AWXDataInfo; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.util.JDateUtil; -import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.*; import java.io.IOException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS11DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS11DataInfo.java index 724725d3..3e588ef3 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS11DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS11DataInfo.java @@ -25,16 +25,17 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.MIMath; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.IndexIterator; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS120DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS120DataInfo.java index 80297a21..3440e0f0 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS120DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS120DataInfo.java @@ -13,9 +13,11 @@ */ package org.meteoinfo.data.meteodata.micaps; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; @@ -35,13 +37,12 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayMath; + import org.meteoinfo.data.dataframe.Column; import org.meteoinfo.data.dataframe.ColumnIndex; import org.meteoinfo.data.dataframe.DataFrame; import org.meteoinfo.data.dataframe.Index; import org.meteoinfo.data.meteodata.MeteoDataType; -import org.meteoinfo.global.Extent; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.data.meteodata.Attribute; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java index 781fbec8..8b4078fc 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java @@ -23,10 +23,11 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS13DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS13DataInfo.java index b7570e02..6443f3ce 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS13DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS13DataInfo.java @@ -22,17 +22,18 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.MIMath; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.projection.Reproject; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS1DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS1DataInfo.java index edecc46b..dfd1c1f9 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS1DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS1DataInfo.java @@ -13,9 +13,12 @@ */ package org.meteoinfo.data.meteodata.micaps; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; @@ -23,8 +26,7 @@ import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModel; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -37,7 +39,7 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.math.ArrayMath; + import org.meteoinfo.data.dataframe.Column; import org.meteoinfo.data.dataframe.ColumnIndex; import org.meteoinfo.data.dataframe.DataFrame; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS2DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS2DataInfo.java index 09c748df..4f58960e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS2DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS2DataInfo.java @@ -18,9 +18,11 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; @@ -29,7 +31,6 @@ import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModel; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.data.meteodata.Attribute; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS3DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS3DataInfo.java index 8b9e619f..de59ba59 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS3DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS3DataInfo.java @@ -13,16 +13,17 @@ */ package org.meteoinfo.data.meteodata.micaps; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS4DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS4DataInfo.java index f08846ab..eaf2fb5f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS4DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS4DataInfo.java @@ -13,14 +13,15 @@ */ package org.meteoinfo.data.meteodata.micaps; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS7DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS7DataInfo.java index 40ff87be..546c19db 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS7DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS7DataInfo.java @@ -25,17 +25,18 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.TrajDataInfo; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.data.meteodata.hysplit.TrajectoryInfo; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.layer.LayerDrawType; import org.meteoinfo.layer.VectorLayer; @@ -333,7 +334,7 @@ public class MICAPS7DataInfo extends DataInfo implements TrajDataInfo { TrajNum += 1; aPolyline.setValue(TrajNum); aPolyline.setPoints(PointList.get(i)); - aPolyline.setExtent(MIMath.getPointsExtent(aPolyline.getPoints())); + aPolyline.setExtent(GeometryUtil.getPointsExtent(aPolyline.getPoints())); int shapeNum = aLayer.getShapeNum(); if (aLayer.editInsertShape(aPolyline, shapeNum)) { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5DataInfo.java index e937b760..ccedd421 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5DataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5DataInfo.java @@ -18,10 +18,11 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5IMDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5IMDataInfo.java index b09ed482..b04667c5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5IMDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/mm5/MM5IMDataInfo.java @@ -16,17 +16,18 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.GridData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.data.meteodata.Attribute; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/netcdf/NetCDFDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/netcdf/NetCDFDataInfo.java index 80cff23a..96236b58 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/netcdf/NetCDFDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/netcdf/NetCDFDataInfo.java @@ -13,10 +13,14 @@ */ package org.meteoinfo.data.meteodata.netcdf; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.math.ArrayMath; +import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IGridDataInfo; @@ -24,8 +28,7 @@ import org.meteoinfo.data.meteodata.IStationDataInfo; import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.io.IOException; import java.text.ParseException; import java.time.LocalDateTime; @@ -36,8 +39,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; -import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.math.ArrayUtil; + import org.meteoinfo.data.GridArray; import org.meteoinfo.data.meteodata.MeteoDataType; import org.meteoinfo.projection.KnownCoordinateSystems; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/synop/SYNOPDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/synop/SYNOPDataInfo.java index 18fdd5ea..461794b6 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/synop/SYNOPDataInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/synop/SYNOPDataInfo.java @@ -13,9 +13,11 @@ */ package org.meteoinfo.data.meteodata.synop; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.data.StationData; import org.meteoinfo.data.meteodata.DataInfo; -import org.meteoinfo.global.util.JDateUtil; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.ndarray.DimensionType; import org.meteoinfo.data.meteodata.IStationDataInfo; @@ -23,8 +25,7 @@ import org.meteoinfo.data.meteodata.StationInfoData; import org.meteoinfo.data.meteodata.StationModel; import org.meteoinfo.data.meteodata.StationModelData; import org.meteoinfo.data.meteodata.Variable; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; + import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/ContourDraw.java b/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/ContourDraw.java index 67b5dad2..dae1da75 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/ContourDraw.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/ContourDraw.java @@ -13,7 +13,8 @@ */ package org.meteoinfo.drawing; -import org.meteoinfo.global.MIMath; +import org.meteoinfo.common.MIMath; + import java.util.List; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/Draw.java b/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/Draw.java index e707ff67..3afaf1b5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/Draw.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/drawing/Draw.java @@ -13,14 +13,14 @@ */ package org.meteoinfo.drawing; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.legend.MarkerType; import org.meteoinfo.legend.PointStyle; import org.meteoinfo.geoprocess.Spline; import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.legend.BreakTypes; import org.meteoinfo.legend.ChartBreak; import org.meteoinfo.legend.LabelBreak; @@ -60,7 +60,6 @@ import java.util.logging.Logger; import javax.imageio.ImageIO; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.bak.ArrayMath; import org.meteoinfo.legend.ArrowBreak; import org.meteoinfo.legend.ArrowLineBreak; import org.meteoinfo.legend.ColorBreakCollection; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/BorderPoint.java b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/BorderPoint.java index 53a6ba9a..2d2b3482 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/BorderPoint.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/BorderPoint.java @@ -1,45 +1,45 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.geoprocess; - -import org.meteoinfo.global.PointD; - -/** - * - * @author Yaqiang Wang - */ -public class BorderPoint { - /// - /// Identifer - /// - public int Id; - /// - /// Border index - /// - public int BorderIdx; - /// - /// Border inner index - /// - public int BInnerIdx; - /// - /// Point - /// - public PointD Point; - /// - /// Value - /// - public double Value; - - public RectPointTypes rectPointType = RectPointTypes.None; -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.geoprocess; + + import org.meteoinfo.common.PointD; + + /** + * + * @author Yaqiang Wang + */ +public class BorderPoint { + /// + /// Identifer + /// + public int Id; + /// + /// Border index + /// + public int BorderIdx; + /// + /// Border inner index + /// + public int BInnerIdx; + /// + /// Point + /// + public PointD Point; + /// + /// Value + /// + public double Value; + + public RectPointTypes rectPointType = RectPointTypes.None; +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/ClipLine.java b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/ClipLine.java index d1e3eb73..8a4e29d5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/ClipLine.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/ClipLine.java @@ -1,155 +1,155 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.geoprocess; - -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; - -/** - * - * @author yaqiang - */ -public class ClipLine { - // - - private double _value; - private boolean _isLon; - private boolean _isLeftOrTop; - // - // - - /** - * Constructor - */ - public ClipLine() { - _isLon = true; - _isLeftOrTop = true; - } - // - // - - /** - * Get value - * - * @return Value - */ - public double getValue() { - return _value; - } - - /** - * Set value - * - * @param value Value - */ - public void setValue(double value) { - _value = value; - } - - /** - * Get if is longitude - * - * @return Boolean - */ - public boolean isLongitude() { - return _isLon; - } - - /** - * Set if is longitude - * - * @param istrue Boolean - */ - public void setLongitude(boolean istrue) { - _isLon = istrue; - } - - /** - * Get if is left (longitude) or top (latitude) - * - * @return Boolean - */ - public boolean isLeftOrTop() { - return _isLeftOrTop; - } - - /** - * Set if is left (longitude) or top (latitude) - * - * @param istrue - */ - public void setLeftOrTop(boolean istrue) { - _isLeftOrTop = istrue; - } - // - // - - /** - * Determine if a point is inside - * - * @param aPoint The Point - * @return If is inside - */ - public boolean isInside(PointD aPoint) { - boolean isIn = false; - if (_isLon) { - if (_isLeftOrTop) { - isIn = (aPoint.X <= _value); - } else { - isIn = (aPoint.X >= _value); - } - } else { - if (_isLeftOrTop) { - isIn = (aPoint.Y >= _value); - } else { - isIn = (aPoint.Y <= _value); - } - } - - return isIn; - } - - /** - * Determine if an extent is cross - * - * @param aExtent The extent - * @return Is extent cross - */ - public boolean isExtentCross(Extent aExtent) { - if (_isLeftOrTop) { - PointD aPoint = new PointD(aExtent.minX, aExtent.maxY); - return isInside(aPoint); - } else { - PointD aPoint = new PointD(aExtent.maxX, aExtent.minY); - return isInside(aPoint); - } - } - - /** - * Determine if an extent is inside - * - * @param aExtent The extent - * @return Is extent inside - */ - public boolean isExtentInside(Extent aExtent) { - if (_isLeftOrTop) { - PointD aPoint = new PointD(aExtent.maxX, aExtent.minY); - return isInside(aPoint); - } else { - PointD aPoint = new PointD(aExtent.minX, aExtent.maxY); - return isInside(aPoint); - } - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.geoprocess; + + import org.meteoinfo.common.Extent; + import org.meteoinfo.common.PointD; + + /** + * + * @author yaqiang + */ +public class ClipLine { + // + + private double _value; + private boolean _isLon; + private boolean _isLeftOrTop; + // + // + + /** + * Constructor + */ + public ClipLine() { + _isLon = true; + _isLeftOrTop = true; + } + // + // + + /** + * Get value + * + * @return Value + */ + public double getValue() { + return _value; + } + + /** + * Set value + * + * @param value Value + */ + public void setValue(double value) { + _value = value; + } + + /** + * Get if is longitude + * + * @return Boolean + */ + public boolean isLongitude() { + return _isLon; + } + + /** + * Set if is longitude + * + * @param istrue Boolean + */ + public void setLongitude(boolean istrue) { + _isLon = istrue; + } + + /** + * Get if is left (longitude) or top (latitude) + * + * @return Boolean + */ + public boolean isLeftOrTop() { + return _isLeftOrTop; + } + + /** + * Set if is left (longitude) or top (latitude) + * + * @param istrue + */ + public void setLeftOrTop(boolean istrue) { + _isLeftOrTop = istrue; + } + // + // + + /** + * Determine if a point is inside + * + * @param aPoint The Point + * @return If is inside + */ + public boolean isInside(PointD aPoint) { + boolean isIn = false; + if (_isLon) { + if (_isLeftOrTop) { + isIn = (aPoint.X <= _value); + } else { + isIn = (aPoint.X >= _value); + } + } else { + if (_isLeftOrTop) { + isIn = (aPoint.Y >= _value); + } else { + isIn = (aPoint.Y <= _value); + } + } + + return isIn; + } + + /** + * Determine if an extent is cross + * + * @param aExtent The extent + * @return Is extent cross + */ + public boolean isExtentCross(Extent aExtent) { + if (_isLeftOrTop) { + PointD aPoint = new PointD(aExtent.minX, aExtent.maxY); + return isInside(aPoint); + } else { + PointD aPoint = new PointD(aExtent.maxX, aExtent.minY); + return isInside(aPoint); + } + } + + /** + * Determine if an extent is inside + * + * @param aExtent The extent + * @return Is extent inside + */ + public boolean isExtentInside(Extent aExtent) { + if (_isLeftOrTop) { + PointD aPoint = new PointD(aExtent.maxX, aExtent.minY); + return isInside(aPoint); + } else { + PointD aPoint = new PointD(aExtent.minX, aExtent.maxY); + return isInside(aPoint); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeoComputation.java b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeoComputation.java index c1242ab5..9d3eb537 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeoComputation.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeoComputation.java @@ -13,11 +13,12 @@ */ package org.meteoinfo.geoprocess; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Direction; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; +import org.meteoinfo.math.meteo.MeteoMath; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.shape.*; @@ -28,7 +29,7 @@ import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.bak.ArrayMath; + import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataRow; @@ -232,7 +233,7 @@ public class GeoComputation { */ public static boolean pointInPolygons(List polygons, PointD aPoint) { boolean isIn = false; - Extent ext = MIMath.getExtent(polygons); + Extent ext = GeometryUtil.getExtent(polygons); if (MIMath.pointInExtent(aPoint, ext)) { for (PolygonShape aPGS : polygons) { if (pointInPolygon(aPGS, aPoint)) { @@ -360,7 +361,7 @@ public class GeoComputation { aExtent.maxX = sp.X + buffer; aExtent.minY = sp.Y - buffer; aExtent.maxY = sp.Y + buffer; - Extent bExtent = MIMath.getPointsExtent(points); + Extent bExtent = GeometryUtil.getPointsExtent(points); double dis; if (MIMath.isExtentCross(aExtent, bExtent)) { for (int j = 0; j < points.size(); j++) { @@ -1347,7 +1348,7 @@ public class GeoComputation { if (inPolygon.hasHole()) { for (int h = 0; h < inPolygon.getHoleLines().size(); h++) { List holePList = (List) inPolygon.getHoleLines().get(h); - Extent plExtent = MIMath.getPointsExtent(holePList); + Extent plExtent = GeometryUtil.getPointsExtent(holePList); if (!isExtentCross(plExtent, clipObj)) { continue; } @@ -1563,7 +1564,7 @@ public class GeoComputation { if (inPolygon.hasHole()) { for (int h = 0; h < inPolygon.getHoleLines().size(); h++) { List holePList = (List) inPolygon.getHoleLines().get(h); - Extent plExtent = MIMath.getPointsExtent(holePList); + Extent plExtent = GeometryUtil.getPointsExtent(holePList); if (!isExtentCross(plExtent, extent)) { continue; } @@ -2020,7 +2021,7 @@ public class GeoComputation { int i, j; for (i = 0; i < holeList.size(); i++) { List holePs = holeList.get(i); - Extent aExtent = MIMath.getPointsExtent(holePs); + Extent aExtent = GeometryUtil.getPointsExtent(holePs); for (j = 0; j < polygonList.size(); j++) { Polygon aPolygon = polygonList.get(j); if (aPolygon.getExtent().include(aExtent)) { @@ -2043,7 +2044,7 @@ public class GeoComputation { private static boolean isExtentCross(Extent aExtent, Object clipObj) { if (clipObj instanceof List) { - Extent bExtent = MIMath.getPointsExtent((List) clipObj); + Extent bExtent = GeometryUtil.getPointsExtent((List) clipObj); return MIMath.isExtentCross(aExtent, bExtent); } if (clipObj.getClass() == ClipLine.class) { @@ -2158,8 +2159,8 @@ public class GeoComputation { PListA.add(lineA.P2); PListB.add(lineB.P1); PListB.add(lineB.P2); - boundA = MIMath.getPointsExtent(PListA); - boundB = MIMath.getPointsExtent(PListB); + boundA = GeometryUtil.getPointsExtent(PListA); + boundB = GeometryUtil.getPointsExtent(PListB); if (!MIMath.isExtentCross(boundA, boundB)) { return false; @@ -2481,7 +2482,7 @@ public class GeoComputation { } else { aGL.setLabDirection(Direction.Weast); } - aGL.setAnge((float)ArrayMath.uv2ds(p2.X - p1.X, p2.Y - p1.Y)[0]); + aGL.setAnge((float)MeteoMath.uv2ds(p2.X - p1.X, p2.Y - p1.Y)[0]); gridLabels.add(aGL); p1 = aPList.get(aPList.size() - 1); @@ -2498,7 +2499,7 @@ public class GeoComputation { } else { aGL.setLabDirection(Direction.East); } - aGL.setAnge((float)ArrayMath.uv2ds(p2.X - p1.X, p2.Y - p1.Y)[0]); + aGL.setAnge((float) MeteoMath.uv2ds(p2.X - p1.X, p2.Y - p1.Y)[0]); gridLabels.add(aGL); return gridLabels; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeometryUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeometryUtil.java index 37408f9f..b26ccbcd 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeometryUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/GeometryUtil.java @@ -10,7 +10,9 @@ import java.util.List; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.common.PointD; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.*; @@ -22,6 +24,157 @@ import org.meteoinfo.shape.*; */ public class GeometryUtil { + /** + * Get extent from point list + * + * @param PList point list + * @return extent + */ + public static Extent getPointsExtent(List PList) { + if (PList.get(0) instanceof PointZ){ + Extent3D cET = new Extent3D(); + for (int i = 0; i < PList.size(); i++) { + PointZ aP = (PointZ)PList.get(i); + if (i == 0) { + cET.minX = aP.X; + cET.maxX = aP.X; + cET.minY = aP.Y; + cET.maxY = aP.Y; + cET.minZ = aP.Z; + cET.maxZ = aP.Z; + } else { + if (cET.minX > aP.X) { + cET.minX = aP.X; + } else if (cET.maxX < aP.X) { + cET.maxX = aP.X; + } + + if (cET.minY > aP.Y) { + cET.minY = aP.Y; + } else if (cET.maxY < aP.Y) { + cET.maxY = aP.Y; + } + + if (cET.minZ > aP.Z) { + cET.minZ = aP.Z; + } else if (cET.maxZ < aP.Z) { + cET.maxZ = aP.Z; + } + } + } + + return cET; + } else { + Extent cET = new Extent(); + for (int i = 0; i < PList.size(); i++) { + PointD aP = PList.get(i); + if (i == 0) { + cET.minX = aP.X; + cET.maxX = aP.X; + cET.minY = aP.Y; + cET.maxY = aP.Y; + } else { + if (cET.minX > aP.X) { + cET.minX = aP.X; + } else if (cET.maxX < aP.X) { + cET.maxX = aP.X; + } + + if (cET.minY > aP.Y) { + cET.minY = aP.Y; + } else if (cET.maxY < aP.Y) { + cET.maxY = aP.Y; + } + } + } + + return cET; + } + } + + /** + * Get extent of the shapes + * + * @param shapes + * @return Extent + */ + public static Extent getExtent(List shapes) { + Extent extent = (Extent) shapes.get(0).getExtent().clone(); + double minx = extent.minX; + double maxx = extent.maxX; + double miny = extent.minY; + double maxy = extent.maxY; + Extent ext; + for (int i = 1; i < shapes.size(); i++) { + ext = shapes.get(i).getExtent(); + if (minx > ext.minX) { + minx = ext.minX; + } + if (maxx < ext.maxX) { + maxx = ext.maxX; + } + if (miny > ext.minY) { + miny = ext.minY; + } + if (maxy < ext.maxY) { + maxy = ext.maxY; + } + } + + extent.minX = minx; + extent.maxX = maxx; + extent.minY = miny; + extent.maxY = maxy; + + return extent; + } + + /** + * Get extent of the points + * + * @param points + * @return Extent + */ + public static Extent3D getExtent(PointZ[] points) { + PointZ p = points[0]; + double minx = p.X; + double maxx = p.X; + double miny = p.Y; + double maxy = p.Y; + double minz = p.Z; + double maxz = p.Z; + for (int i = 1; i < points.length; i++) { + if (minx > p.X) { + minx = p.M; + } + if (maxx < p.X) { + maxx = p.M; + } + if (miny > p.Y) { + miny = p.Y; + } + if (maxy < p.Y) { + maxy = p.Y; + } + if (minz > p.Z) { + minz = p.Z; + } + if (maxz < p.Z) { + maxz = p.Z; + } + } + + Extent3D extent = new Extent3D(); + extent.minX = minx; + extent.maxX = maxx; + extent.minY = miny; + extent.maxY = maxy; + extent.minZ = minz; + extent.maxZ = maxz; + + return extent; + } + /** * Get ellipse coordinate * @param x0 Center x diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/Spline.java b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/Spline.java index 249473a2..f618bb26 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/Spline.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/geoprocess/Spline.java @@ -1,113 +1,114 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.geoprocess; - -import org.meteoinfo.global.PointD; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author Yaqiang Wang - */ -public class Spline { - - private static class Vec2 { - - public double X, Y; - - public Vec2(double x, double y) { - this.X = x; - this.Y = y; - } - - public Vec2(PointD p) { - this.X = p.X; - this.Y = p.Y; - } - - public PointD toPointD() { - return new PointD(X, Y); - } - - public Vec2 add(Vec2 v) { - return new Vec2(this.X + v.X, this.Y + v.Y); - } - - public Vec2 subtract(Vec2 v) { - return new Vec2(this.X - v.X, this.Y - v.Y); - } - - public Vec2 multiply(float f) { - return new Vec2(this.X * f, this.Y * f); - } - - public Vec2 divide(float f) { - return new Vec2(this.X / f, this.Y / f); - } - } - - private static PointD[] interpolateBezier(PointD p0, PointD p1, PointD p2, PointD p3, int samples) { - PointD[] result = new PointD[samples]; - Vec2 v0 = new Vec2(p0); - Vec2 v1 = new Vec2(p1); - Vec2 v2 = new Vec2(p2); - Vec2 v3 = new Vec2(p3); - for (int i = 0; i < samples; i++) { - float t = (i + 1) / (samples + 1.0f); - result[i] = (v0.multiply((1 - t) * (1 - t) * (1 - t)). - add(v1.multiply(3 * (1 - t) * (1 - t) * t)). - add(v2.multiply(3 * (1 - t) * t * t)). - add(v3.multiply(t * t * t))).toPointD(); - } - return result; - } - - private static PointD[] interpolateCardinalSpline(PointD p0, PointD p1, PointD p2, PointD p3, int samples) { - float tension = 0.5f; - Vec2 v0 = new Vec2(p0); - Vec2 v1 = new Vec2(p1); - Vec2 v2 = new Vec2(p2); - Vec2 v3 = new Vec2(p3); - - PointD u = v2.subtract(v0).multiply(tension / 3).add(v1).toPointD(); - PointD v = v1.subtract(v3).multiply(tension / 3).add(v2).toPointD(); - - return interpolateBezier(p1, u, v, p2, samples); - } - - /** - * '基数样条'内插法。 points为通过点,samplesInSegment为两个样本点之间的内插数量。 - * - * @param points The points - * @param samplesInSegment Sample in segment - * @return Splined points - */ - public static PointD[] cardinalSpline(PointD[] points, int samplesInSegment) { - List result = new ArrayList<>(); - for (int i = 0; i < points.length - 1; i++) { - result.add(points[i]); - PointD[] pds = interpolateCardinalSpline( - points[Math.max(i - 1, 0)], - points[i], - points[i + 1], - points[Math.min(i + 2, points.length - 1)], - samplesInSegment); - result.addAll(Arrays.asList(pds)); - } - result.add(points[points.length - 1]); - return (PointD[]) result.toArray(new PointD[result.size()]); - } -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.geoprocess; + +import org.meteoinfo.common.PointD; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author Yaqiang Wang + */ +public class Spline { + + private static class Vec2 { + + public double X, Y; + + public Vec2(double x, double y) { + this.X = x; + this.Y = y; + } + + public Vec2(PointD p) { + this.X = p.X; + this.Y = p.Y; + } + + public PointD toPointD() { + return new PointD(X, Y); + } + + public Vec2 add(Vec2 v) { + return new Vec2(this.X + v.X, this.Y + v.Y); + } + + public Vec2 subtract(Vec2 v) { + return new Vec2(this.X - v.X, this.Y - v.Y); + } + + public Vec2 multiply(float f) { + return new Vec2(this.X * f, this.Y * f); + } + + public Vec2 divide(float f) { + return new Vec2(this.X / f, this.Y / f); + } + } + + private static PointD[] interpolateBezier(PointD p0, PointD p1, PointD p2, PointD p3, int samples) { + PointD[] result = new PointD[samples]; + Vec2 v0 = new Vec2(p0); + Vec2 v1 = new Vec2(p1); + Vec2 v2 = new Vec2(p2); + Vec2 v3 = new Vec2(p3); + for (int i = 0; i < samples; i++) { + float t = (i + 1) / (samples + 1.0f); + result[i] = (v0.multiply((1 - t) * (1 - t) * (1 - t)). + add(v1.multiply(3 * (1 - t) * (1 - t) * t)). + add(v2.multiply(3 * (1 - t) * t * t)). + add(v3.multiply(t * t * t))).toPointD(); + } + return result; + } + + private static PointD[] interpolateCardinalSpline(PointD p0, PointD p1, PointD p2, PointD p3, int samples) { + float tension = 0.5f; + Vec2 v0 = new Vec2(p0); + Vec2 v1 = new Vec2(p1); + Vec2 v2 = new Vec2(p2); + Vec2 v3 = new Vec2(p3); + + PointD u = v2.subtract(v0).multiply(tension / 3).add(v1).toPointD(); + PointD v = v1.subtract(v3).multiply(tension / 3).add(v2).toPointD(); + + return interpolateBezier(p1, u, v, p2, samples); + } + + /** + * '基数样条'内插法。 points为通过点,samplesInSegment为两个样本点之间的内插数量。 + * + * @param points The points + * @param samplesInSegment Sample in segment + * @return Splined points + */ + public static PointD[] cardinalSpline(PointD[] points, int samplesInSegment) { + List result = new ArrayList<>(); + for (int i = 0; i < points.length - 1; i++) { + result.add(points[i]); + PointD[] pds = interpolateCardinalSpline( + points[Math.max(i - 1, 0)], + points[i], + points[i + 1], + points[Math.min(i + 2, points.length - 1)], + samplesInSegment); + result.addAll(Arrays.asList(pds)); + } + result.add(points[points.length - 1]); + return (PointD[]) result.toArray(new PointD[result.size()]); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/DataConvert.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/DataConvert.java index ebd811cb..91a73503 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/DataConvert.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/DataConvert.java @@ -29,8 +29,8 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import org.meteoinfo.global.util.JDateUtil; -import org.meteoinfo.global.util.TypeUtils; +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.common.util.TypeUtils; import org.meteoinfo.ndarray.DataType; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorMap.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorMap.java index ae4dd02b..5b431617 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorMap.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorMap.java @@ -17,7 +17,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; -import org.meteoinfo.global.MIMath; + +import org.meteoinfo.common.MIMath; import org.meteoinfo.legend.LegendManage; /** @@ -459,7 +460,7 @@ public class ColorMap { line = line.trim(); strs = line.split("\\s+"); if (strs.length >= 3){ - if (MIMath.isNumeric(strs[0]) && MIMath.isNumeric(strs[1]) && + if (MIMath.isNumeric(strs[0]) && MIMath.isNumeric(strs[1]) && MIMath.isNumeric(strs[2])){ if (n == 0){ if (strs[0].contains(".")) diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorUtil.java index e536509e..81978ae4 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/colors/ColorUtil.java @@ -1,568 +1,569 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global.colors; - -import java.awt.Color; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.util.GlobalUtil; - -/** - * ColorUtiles class - * - * @author Yaqiang - */ -public class ColorUtil { - // - - private final static Map colorNames; - - static { - // color names. - colorNames = new HashMap(); - colorNames.put("aliceblue", new Color(0xF0F8FF)); - colorNames.put("antiquewhite", new Color(0xFAEBD7)); - colorNames.put("black", new Color(0x000000)); - colorNames.put("green", new Color(0x008000)); - colorNames.put("silver", new Color(0xC0C0C0)); - colorNames.put("lime", new Color(0x00FF00)); - colorNames.put("gray", new Color(0x808080)); - colorNames.put("darkgray", new Color(0xA9A9A9)); - colorNames.put("olive", new Color(0x808000)); - colorNames.put("white", new Color(0xFFFFFF)); - colorNames.put("yellow", new Color(0xFFFF00)); - colorNames.put("maroon", new Color(0x800000)); - colorNames.put("navy", new Color(0x000080)); - colorNames.put("red", new Color(0xFF0000)); - colorNames.put("blue", new Color(0x0000FF)); - colorNames.put("purple", new Color(0x800080)); - colorNames.put("teal", new Color(0x008080)); - colorNames.put("fuchsia", new Color(0xFF00FF)); - colorNames.put("aqua", new Color(0x00FFFF)); - colorNames.put("transparent", new Color(0, 0, 0, 0)); - } - - // - // - // - // - - /** - * Get common color - * - * @param idx Index - * @return Common color - */ - public static Color getCommonColor(int idx) { -// if (idx == 0) { -// idx = 1; -// } - if (idx > 11) { - idx = idx % 11; - } - - switch (idx) { - case 0: - return Color.red; - case 1: - return Color.blue; - case 2: - return Color.green; - case 3: - return Color.black; - case 4: - return Color.yellow; - case 5: - return Color.pink; - case 6: - return Color.gray; - case 7: - return Color.cyan; - case 8: - return Color.magenta; - case 9: - return Color.orange; - case 10: - return Color.darkGray; - case 11: - return Color.lightGray; - } - - return Color.red; - } - // - // - - /** - * Convert a color to hex string - * - * @param color a color - * @return Hex string - */ - public static String toHexEncoding(Color color) { - String A, R, G, B; - StringBuilder sb = new StringBuilder(); - - A = Integer.toHexString(color.getAlpha()); - R = Integer.toHexString(color.getRed()); - G = Integer.toHexString(color.getGreen()); - B = Integer.toHexString(color.getBlue()); - - A = A.length() == 1 ? "0" + A : A; - R = R.length() == 1 ? "0" + R : R; - G = G.length() == 1 ? "0" + G : G; - B = B.length() == 1 ? "0" + B : B; - - sb.append("0x"); - sb.append(A); - sb.append(R); - sb.append(G); - sb.append(B); - - return sb.toString(); - } - - /** - * Parse hex string to color - * - * @param c hex string - * @return Color - */ - public static Color parseToColor(final String c) { - //Color convertedColor = (Color) colorNames.get(c.trim().toLowerCase()); - Color convertedColor = Color.white; - try { - WebColor webColor = WebColor.valueOf(c.trim()); - convertedColor = WebColor.valueOf(c.trim()).getColor(); - } catch (IllegalArgumentException e) { - try { - if (c.length() == 10) { - String aStr = c.substring(2, 4); - String cStr = c.substring(0, 2) + c.substring(4); - int alpha = Integer.parseInt(aStr, 16); - //int rgb = Integer.parseInt(cStr); - convertedColor = Color.decode(cStr); - //convertedColor = new Color(rgb); - convertedColor = new Color(convertedColor.getRed(), convertedColor.getGreen(), convertedColor.getBlue(), alpha); - } else { - //convertedColor = new Color(Integer.parseInt(c, 16)); - convertedColor = Color.decode(c); - } - } catch (NumberFormatException ne) { - // codes to deal with this exception - //convertedColor = Color.white; - } - } - - return convertedColor; - } - - /** - * Modifies an existing brightness level of a color - * - * @param c The color - * @param brightness The brightness - * @return Adjusted color - */ - public static Color modifyBrightness(Color c, float brightness) { - float hsbVals[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - return Color.getHSBColor(hsbVals[0], hsbVals[1], brightness * hsbVals[2]); - } - - /** - * Convert color to KML color string - AABBGGRR - * - * @param color The color - * @return KML color string - */ - public static String toKMLColor(Color color) { - String A, R, G, B; - StringBuilder sb = new StringBuilder(); - - A = Integer.toHexString(color.getAlpha()).toUpperCase(); - R = Integer.toHexString(color.getRed()).toUpperCase(); - G = Integer.toHexString(color.getGreen()).toUpperCase(); - B = Integer.toHexString(color.getBlue()).toUpperCase(); - - A = A.length() == 1 ? "0" + A : A; - R = R.length() == 1 ? "0" + R : R; - G = G.length() == 1 ? "0" + G : G; - B = B.length() == 1 ? "0" + B : B; - - //sb.append("0x"); - sb.append(A); - sb.append(B); - sb.append(G); - sb.append(R); - - return sb.toString(); - } - - /** - * Get color tables - * - * @return Color tables - * @throws IOException - */ - public static ColorMap[] getColorTables() throws IOException { - String fn = GlobalUtil.getAppPath(ColorUtil.class); - boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean(). - getInputArguments().toString().contains("jdwp"); - if (isDebug) { - fn = "D:/MyProgram/Distribution/Java/MeteoInfo/MeteoInfo/"; - } - fn = fn.substring(0, fn.lastIndexOf("/")); - String path = fn + File.separator + "colormaps"; - File pathDir = new File(path); - if (!pathDir.isDirectory()) { - return null; - } - - File[] files = pathDir.listFiles(); - List cts = new ArrayList<>(); - for (File file : files) { - //InputStream is = ColorUtil.class.getResourceAsStream(pdir + "/" + fileName); - //System.out.println(file.getAbsolutePath()); - ColorMap ct = new ColorMap(); - ct.readFromFile(file); - if (ct.getColorCount() > 0) { - String name = file.getName(); - name = name.substring(0, name.lastIndexOf(".")); - ct.setName(name); - cts.add(ct); - } - } - - ColorMap[] ncts = new ColorMap[cts.size()]; - for (int i = 0; i < cts.size(); i++) { - ncts[i] = cts.get(i); - } - - return ncts; - } - - /** - * Load color map from rgb file - * @param fn Color map rgb file path - * @return Color table - * @throws java.io.IOException - */ - public static ColorMap loadColorMap(String fn) throws IOException{ - File ctFile = new File(fn); - if (!ctFile.isFile()) - return null; - - ColorMap ct = new ColorMap(); - ct.readFromFile(fn); - - return ct; - } - - /** - * Load color map from rgb file - * @param fn Color map rgb file path - * @param alpha Alpha - * @return Color table - * @throws java.io.IOException - */ - public static ColorMap loadColorMap(String fn, int alpha) throws IOException{ - File ctFile = new File(fn); - if (!ctFile.isFile()) - return null; - - ColorMap ct = new ColorMap(); - ct.readFromFile(fn, alpha); - - return ct; - } - - /** - * Find color table - * @param cts Color tables - * @param name Color table name - * @return Finded color table - */ - public static ColorMap findColorTable(ColorMap[] cts, String name){ - for (ColorMap ct : cts){ - if (ct.getName().equalsIgnoreCase(name)) - return ct; - } - - return null; - } - - /** - * Get color tables - * - * @return Color tables - * @throws IOException - */ - public static ColorMap[] getColorTables_old() throws IOException { - String pdir = "/images/colortables"; - List fns = new ArrayList<>(); - fns.add("grads_rainbow.rgb"); - fns.add("GHRSST_anomaly.rgb"); - fns.add("amwg256.rgb"); - fns.add("cmp_b2r.rgb"); - fns.add("cmp_flux.rgb"); - fns.add("cmp_haxby.rgb"); - fns.add("matlab_hot.rgb"); - fns.add("matlab_hsv.rgb"); - fns.add("matlab_jet.rgb"); - fns.add("matlab_lines.rgb"); - fns.add("ncl_default.rgb"); - fns.add("ncview_default.ncmap"); - fns.add("rainbow+white+gray.gp"); - fns.add("rainbow.gp"); - fns.add("seaice_1.rgb"); - fns.add("seaice_2.rgb"); - - List cts = new ArrayList<>(); - for (String fileName : fns) { - InputStream is = ColorUtil.class.getResourceAsStream(pdir + "/" + fileName); - ColorMap ct = new ColorMap(); - ct.readFromFile(is); - cts.add(ct); - } - - ColorMap[] ncts = new ColorMap[cts.size()]; - for (int i = 0; i < cts.size(); i++) { - ncts[i] = cts.get(i); - } - - return ncts; - } - - /** - * Create colors from start and end color - * - * @param sColor Start color - * @param eColor End color - * @param cNum Color number - * @return Color array - */ - public static Color[] createColors(Color sColor, Color eColor, int cNum) { - Color[] colors = new Color[cNum]; - int sR, sG, sB, eR, eG, eB; - int rStep, gStep, bStep; - int i; - - sR = sColor.getRed(); - sG = sColor.getGreen(); - sB = sColor.getBlue(); - eR = eColor.getRed(); - eG = eColor.getGreen(); - eB = eColor.getBlue(); - rStep = (int) ((eR - sR) / cNum); - gStep = (int) ((eG - sG) / cNum); - bStep = (int) ((eB - sB) / cNum); - for (i = 0; i < colors.length; i++) { - colors[i] = new Color(sR + i * rStep, sG + i * gStep, sB + i * bStep); - } - - return colors; - } - - /** - * Create colors - * @param cm Color map - * @param min Min value - * @param max Max value - * @return Colors - */ - public static Color[] createColors(ColorMap cm, double min, double max){ - double[] values = MIMath.getIntervalValues(min, max); - return cm.getColors(values.length + 1); - } - - /** - * Create colors - * @param cm Color map - * @param min Min value - * @param max Max value - * @param n Color number - * @return Colors - */ - public static Color[] createColors(ColorMap cm, double min, double max, int n){ - double[] values = MIMath.getIntervalValues(min, max, n); - return cm.getColors(values.length + 1); - } - - /** - * Create color from start and end color - * - * @param sColor Start color - * @param eColor End color - * @param p Proportion - * @return Color - */ - public static Color createColor(Color sColor, Color eColor, float p) { - int sR, sG, sB, eR, eG, eB, r, g, b; - - sR = sColor.getRed(); - sG = sColor.getGreen(); - sB = sColor.getBlue(); - eR = eColor.getRed(); - eG = eColor.getGreen(); - eB = eColor.getBlue(); - r = (int) (sR + (eR - sR) * p); - g = (int) (sG + (eG - sG) * p); - b = (int) (sB + (eB - sB) * p); - - return new Color(r, g, b); - } - - /** - * Create rainbow colors - * - * @param cNum Color number - * @return Rainbow color array - */ - public static Color[] createRainBowColors(int cNum) { - if (cNum > 13) { - //return getRainBowColors_HSL(cNum); - return getRainBowColors_HSV(cNum); - } - - List colorList = new ArrayList<>(); - - colorList.add(new Color(160, 0, 200)); - colorList.add(new Color(110, 0, 220)); - colorList.add(new Color(30, 60, 255)); - colorList.add(new Color(0, 160, 255)); - colorList.add(new Color(0, 200, 200)); - colorList.add(new Color(0, 210, 140)); - colorList.add(new Color(0, 220, 0)); - colorList.add(new Color(160, 230, 50)); - colorList.add(new Color(230, 220, 50)); - colorList.add(new Color(230, 175, 45)); - colorList.add(new Color(240, 130, 40)); - colorList.add(new Color(250, 60, 60)); - colorList.add(new Color(240, 0, 130)); - - switch (cNum) { - case 12: - colorList.remove(new Color(0, 210, 140)); - break; - case 11: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - break; - case 10: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - break; - case 9: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - colorList.remove(new Color(160, 230, 50)); - break; - case 8: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - colorList.remove(new Color(160, 230, 50)); - colorList.remove(new Color(110, 0, 220)); - break; - case 7: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - colorList.remove(new Color(160, 230, 50)); - colorList.remove(new Color(110, 0, 220)); - colorList.remove(new Color(0, 200, 200)); - break; - case 6: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - colorList.remove(new Color(160, 230, 50)); - colorList.remove(new Color(110, 0, 220)); - colorList.remove(new Color(0, 200, 200)); - colorList.remove(new Color(240, 130, 40)); - break; - case 5: - colorList.remove(new Color(0, 210, 140)); - colorList.remove(new Color(30, 60, 255)); - colorList.remove(new Color(230, 175, 45)); - colorList.remove(new Color(160, 230, 50)); - colorList.remove(new Color(110, 0, 220)); - colorList.remove(new Color(0, 200, 200)); - colorList.remove(new Color(240, 130, 40)); - colorList.remove(new Color(160, 0, 200)); - break; - } - - Color[] colors = new Color[cNum]; - for (int i = 0; i < cNum; i++) { - colors[i] = colorList.get(i); - } - - return colors; - } - - /** - * Get rainbow color by HSV/HSB - * - * @param cNum Color number - * @return Rainbow colors - */ - public static Color[] getRainBowColors_HSV(int cNum) { - double p = 360.0 / cNum; - Color[] colors = new Color[cNum]; - for (int i = 0; i < cNum; i++) { - colors[cNum - i - 1] = Color.getHSBColor((float) (i * p), 1.0f, 1.0f); - } - - return colors; - } - - /** - * Create a random color - * @return A random color - */ - public static Color createRandomColor(){ - Random randomColor = new Random(); - return new Color(randomColor.nextInt(256), randomColor.nextInt(256), randomColor.nextInt(256)); - } - - /** - * Create random colors - * - * @param cNum Color number - * @return The random colors - */ - public static Color[] createRandomColors(int cNum) { - Color[] colors = new Color[cNum]; - int i; - Random randomColor = new Random(); - - for (i = 0; i < cNum; i++) { - colors[i] = new Color(randomColor.nextInt(256), - randomColor.nextInt(256), randomColor.nextInt(256)); - } - - return colors; - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.global.colors; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.GlobalUtil; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + + /** + * ColorUtiles class + * + * @author Yaqiang + */ +public class ColorUtil { + // + + private final static Map colorNames; + + static { + // color names. + colorNames = new HashMap(); + colorNames.put("aliceblue", new Color(0xF0F8FF)); + colorNames.put("antiquewhite", new Color(0xFAEBD7)); + colorNames.put("black", new Color(0x000000)); + colorNames.put("green", new Color(0x008000)); + colorNames.put("silver", new Color(0xC0C0C0)); + colorNames.put("lime", new Color(0x00FF00)); + colorNames.put("gray", new Color(0x808080)); + colorNames.put("darkgray", new Color(0xA9A9A9)); + colorNames.put("olive", new Color(0x808000)); + colorNames.put("white", new Color(0xFFFFFF)); + colorNames.put("yellow", new Color(0xFFFF00)); + colorNames.put("maroon", new Color(0x800000)); + colorNames.put("navy", new Color(0x000080)); + colorNames.put("red", new Color(0xFF0000)); + colorNames.put("blue", new Color(0x0000FF)); + colorNames.put("purple", new Color(0x800080)); + colorNames.put("teal", new Color(0x008080)); + colorNames.put("fuchsia", new Color(0xFF00FF)); + colorNames.put("aqua", new Color(0x00FFFF)); + colorNames.put("transparent", new Color(0, 0, 0, 0)); + } + + // + // + // + // + + /** + * Get common color + * + * @param idx Index + * @return Common color + */ + public static Color getCommonColor(int idx) { +// if (idx == 0) { +// idx = 1; +// } + if (idx > 11) { + idx = idx % 11; + } + + switch (idx) { + case 0: + return Color.red; + case 1: + return Color.blue; + case 2: + return Color.green; + case 3: + return Color.black; + case 4: + return Color.yellow; + case 5: + return Color.pink; + case 6: + return Color.gray; + case 7: + return Color.cyan; + case 8: + return Color.magenta; + case 9: + return Color.orange; + case 10: + return Color.darkGray; + case 11: + return Color.lightGray; + } + + return Color.red; + } + // + // + + /** + * Convert a color to hex string + * + * @param color a color + * @return Hex string + */ + public static String toHexEncoding(Color color) { + String A, R, G, B; + StringBuilder sb = new StringBuilder(); + + A = Integer.toHexString(color.getAlpha()); + R = Integer.toHexString(color.getRed()); + G = Integer.toHexString(color.getGreen()); + B = Integer.toHexString(color.getBlue()); + + A = A.length() == 1 ? "0" + A : A; + R = R.length() == 1 ? "0" + R : R; + G = G.length() == 1 ? "0" + G : G; + B = B.length() == 1 ? "0" + B : B; + + sb.append("0x"); + sb.append(A); + sb.append(R); + sb.append(G); + sb.append(B); + + return sb.toString(); + } + + /** + * Parse hex string to color + * + * @param c hex string + * @return Color + */ + public static Color parseToColor(final String c) { + //Color convertedColor = (Color) colorNames.get(c.trim().toLowerCase()); + Color convertedColor = Color.white; + try { + WebColor webColor = WebColor.valueOf(c.trim()); + convertedColor = WebColor.valueOf(c.trim()).getColor(); + } catch (IllegalArgumentException e) { + try { + if (c.length() == 10) { + String aStr = c.substring(2, 4); + String cStr = c.substring(0, 2) + c.substring(4); + int alpha = Integer.parseInt(aStr, 16); + //int rgb = Integer.parseInt(cStr); + convertedColor = Color.decode(cStr); + //convertedColor = new Color(rgb); + convertedColor = new Color(convertedColor.getRed(), convertedColor.getGreen(), convertedColor.getBlue(), alpha); + } else { + //convertedColor = new Color(Integer.parseInt(c, 16)); + convertedColor = Color.decode(c); + } + } catch (NumberFormatException ne) { + // codes to deal with this exception + //convertedColor = Color.white; + } + } + + return convertedColor; + } + + /** + * Modifies an existing brightness level of a color + * + * @param c The color + * @param brightness The brightness + * @return Adjusted color + */ + public static Color modifyBrightness(Color c, float brightness) { + float hsbVals[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); + return Color.getHSBColor(hsbVals[0], hsbVals[1], brightness * hsbVals[2]); + } + + /** + * Convert color to KML color string - AABBGGRR + * + * @param color The color + * @return KML color string + */ + public static String toKMLColor(Color color) { + String A, R, G, B; + StringBuilder sb = new StringBuilder(); + + A = Integer.toHexString(color.getAlpha()).toUpperCase(); + R = Integer.toHexString(color.getRed()).toUpperCase(); + G = Integer.toHexString(color.getGreen()).toUpperCase(); + B = Integer.toHexString(color.getBlue()).toUpperCase(); + + A = A.length() == 1 ? "0" + A : A; + R = R.length() == 1 ? "0" + R : R; + G = G.length() == 1 ? "0" + G : G; + B = B.length() == 1 ? "0" + B : B; + + //sb.append("0x"); + sb.append(A); + sb.append(B); + sb.append(G); + sb.append(R); + + return sb.toString(); + } + + /** + * Get color tables + * + * @return Color tables + * @throws IOException + */ + public static ColorMap[] getColorTables() throws IOException { + String fn = GlobalUtil.getAppPath(ColorUtil.class); + boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean(). + getInputArguments().toString().contains("jdwp"); + if (isDebug) { + fn = "D:/MyProgram/Distribution/Java/MeteoInfo/MeteoInfo/"; + } + fn = fn.substring(0, fn.lastIndexOf("/")); + String path = fn + File.separator + "colormaps"; + File pathDir = new File(path); + if (!pathDir.isDirectory()) { + return null; + } + + File[] files = pathDir.listFiles(); + List cts = new ArrayList<>(); + for (File file : files) { + //InputStream is = ColorUtil.class.getResourceAsStream(pdir + "/" + fileName); + //System.out.println(file.getAbsolutePath()); + ColorMap ct = new ColorMap(); + ct.readFromFile(file); + if (ct.getColorCount() > 0) { + String name = file.getName(); + name = name.substring(0, name.lastIndexOf(".")); + ct.setName(name); + cts.add(ct); + } + } + + ColorMap[] ncts = new ColorMap[cts.size()]; + for (int i = 0; i < cts.size(); i++) { + ncts[i] = cts.get(i); + } + + return ncts; + } + + /** + * Load color map from rgb file + * @param fn Color map rgb file path + * @return Color table + * @throws java.io.IOException + */ + public static ColorMap loadColorMap(String fn) throws IOException{ + File ctFile = new File(fn); + if (!ctFile.isFile()) + return null; + + ColorMap ct = new ColorMap(); + ct.readFromFile(fn); + + return ct; + } + + /** + * Load color map from rgb file + * @param fn Color map rgb file path + * @param alpha Alpha + * @return Color table + * @throws java.io.IOException + */ + public static ColorMap loadColorMap(String fn, int alpha) throws IOException{ + File ctFile = new File(fn); + if (!ctFile.isFile()) + return null; + + ColorMap ct = new ColorMap(); + ct.readFromFile(fn, alpha); + + return ct; + } + + /** + * Find color table + * @param cts Color tables + * @param name Color table name + * @return Finded color table + */ + public static ColorMap findColorTable(ColorMap[] cts, String name){ + for (ColorMap ct : cts){ + if (ct.getName().equalsIgnoreCase(name)) + return ct; + } + + return null; + } + + /** + * Get color tables + * + * @return Color tables + * @throws IOException + */ + public static ColorMap[] getColorTables_old() throws IOException { + String pdir = "/images/colortables"; + List fns = new ArrayList<>(); + fns.add("grads_rainbow.rgb"); + fns.add("GHRSST_anomaly.rgb"); + fns.add("amwg256.rgb"); + fns.add("cmp_b2r.rgb"); + fns.add("cmp_flux.rgb"); + fns.add("cmp_haxby.rgb"); + fns.add("matlab_hot.rgb"); + fns.add("matlab_hsv.rgb"); + fns.add("matlab_jet.rgb"); + fns.add("matlab_lines.rgb"); + fns.add("ncl_default.rgb"); + fns.add("ncview_default.ncmap"); + fns.add("rainbow+white+gray.gp"); + fns.add("rainbow.gp"); + fns.add("seaice_1.rgb"); + fns.add("seaice_2.rgb"); + + List cts = new ArrayList<>(); + for (String fileName : fns) { + InputStream is = ColorUtil.class.getResourceAsStream(pdir + "/" + fileName); + ColorMap ct = new ColorMap(); + ct.readFromFile(is); + cts.add(ct); + } + + ColorMap[] ncts = new ColorMap[cts.size()]; + for (int i = 0; i < cts.size(); i++) { + ncts[i] = cts.get(i); + } + + return ncts; + } + + /** + * Create colors from start and end color + * + * @param sColor Start color + * @param eColor End color + * @param cNum Color number + * @return Color array + */ + public static Color[] createColors(Color sColor, Color eColor, int cNum) { + Color[] colors = new Color[cNum]; + int sR, sG, sB, eR, eG, eB; + int rStep, gStep, bStep; + int i; + + sR = sColor.getRed(); + sG = sColor.getGreen(); + sB = sColor.getBlue(); + eR = eColor.getRed(); + eG = eColor.getGreen(); + eB = eColor.getBlue(); + rStep = (int) ((eR - sR) / cNum); + gStep = (int) ((eG - sG) / cNum); + bStep = (int) ((eB - sB) / cNum); + for (i = 0; i < colors.length; i++) { + colors[i] = new Color(sR + i * rStep, sG + i * gStep, sB + i * bStep); + } + + return colors; + } + + /** + * Create colors + * @param cm Color map + * @param min Min value + * @param max Max value + * @return Colors + */ + public static Color[] createColors(ColorMap cm, double min, double max){ + double[] values = MIMath.getIntervalValues(min, max); + return cm.getColors(values.length + 1); + } + + /** + * Create colors + * @param cm Color map + * @param min Min value + * @param max Max value + * @param n Color number + * @return Colors + */ + public static Color[] createColors(ColorMap cm, double min, double max, int n){ + double[] values = MIMath.getIntervalValues(min, max, n); + return cm.getColors(values.length + 1); + } + + /** + * Create color from start and end color + * + * @param sColor Start color + * @param eColor End color + * @param p Proportion + * @return Color + */ + public static Color createColor(Color sColor, Color eColor, float p) { + int sR, sG, sB, eR, eG, eB, r, g, b; + + sR = sColor.getRed(); + sG = sColor.getGreen(); + sB = sColor.getBlue(); + eR = eColor.getRed(); + eG = eColor.getGreen(); + eB = eColor.getBlue(); + r = (int) (sR + (eR - sR) * p); + g = (int) (sG + (eG - sG) * p); + b = (int) (sB + (eB - sB) * p); + + return new Color(r, g, b); + } + + /** + * Create rainbow colors + * + * @param cNum Color number + * @return Rainbow color array + */ + public static Color[] createRainBowColors(int cNum) { + if (cNum > 13) { + //return getRainBowColors_HSL(cNum); + return getRainBowColors_HSV(cNum); + } + + List colorList = new ArrayList<>(); + + colorList.add(new Color(160, 0, 200)); + colorList.add(new Color(110, 0, 220)); + colorList.add(new Color(30, 60, 255)); + colorList.add(new Color(0, 160, 255)); + colorList.add(new Color(0, 200, 200)); + colorList.add(new Color(0, 210, 140)); + colorList.add(new Color(0, 220, 0)); + colorList.add(new Color(160, 230, 50)); + colorList.add(new Color(230, 220, 50)); + colorList.add(new Color(230, 175, 45)); + colorList.add(new Color(240, 130, 40)); + colorList.add(new Color(250, 60, 60)); + colorList.add(new Color(240, 0, 130)); + + switch (cNum) { + case 12: + colorList.remove(new Color(0, 210, 140)); + break; + case 11: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + break; + case 10: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + break; + case 9: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + colorList.remove(new Color(160, 230, 50)); + break; + case 8: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + colorList.remove(new Color(160, 230, 50)); + colorList.remove(new Color(110, 0, 220)); + break; + case 7: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + colorList.remove(new Color(160, 230, 50)); + colorList.remove(new Color(110, 0, 220)); + colorList.remove(new Color(0, 200, 200)); + break; + case 6: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + colorList.remove(new Color(160, 230, 50)); + colorList.remove(new Color(110, 0, 220)); + colorList.remove(new Color(0, 200, 200)); + colorList.remove(new Color(240, 130, 40)); + break; + case 5: + colorList.remove(new Color(0, 210, 140)); + colorList.remove(new Color(30, 60, 255)); + colorList.remove(new Color(230, 175, 45)); + colorList.remove(new Color(160, 230, 50)); + colorList.remove(new Color(110, 0, 220)); + colorList.remove(new Color(0, 200, 200)); + colorList.remove(new Color(240, 130, 40)); + colorList.remove(new Color(160, 0, 200)); + break; + } + + Color[] colors = new Color[cNum]; + for (int i = 0; i < cNum; i++) { + colors[i] = colorList.get(i); + } + + return colors; + } + + /** + * Get rainbow color by HSV/HSB + * + * @param cNum Color number + * @return Rainbow colors + */ + public static Color[] getRainBowColors_HSV(int cNum) { + double p = 360.0 / cNum; + Color[] colors = new Color[cNum]; + for (int i = 0; i < cNum; i++) { + colors[cNum - i - 1] = Color.getHSBColor((float) (i * p), 1.0f, 1.0f); + } + + return colors; + } + + /** + * Create a random color + * @return A random color + */ + public static Color createRandomColor(){ + Random randomColor = new Random(); + return new Color(randomColor.nextInt(256), randomColor.nextInt(256), randomColor.nextInt(256)); + } + + /** + * Create random colors + * + * @param cNum Color number + * @return The random colors + */ + public static Color[] createRandomColors(int cNum) { + Color[] colors = new Color[cNum]; + int i; + Random randomColor = new Random(); + + for (i = 0; i < cNum; i++) { + colors[i] = new Color(randomColor.nextInt(256), + randomColor.nextInt(256), randomColor.nextInt(256)); + } + + return colors; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java deleted file mode 100644 index f072860c..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java +++ /dev/null @@ -1,456 +0,0 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global.util; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -import org.joda.time.*; -import org.joda.time.format.DateTimeFormatter; -import org.meteoinfo.ndarray.util.BigDecimalUtil; - -/** - * - * @author yaqiang - */ -public class DateUtil { - // - // - // - // - // - // - // - - /** - * Add days to a date - * - * @param sDate Start date - * @param days Days - * @return Added date - */ - public static Date addDays(Date sDate, float days) { - Calendar cal = Calendar.getInstance(); - cal.setTime(sDate); - int intDays = (int) days; - cal.add(Calendar.DAY_OF_YEAR, intDays); - int hours = (int) ((days - intDays) * 24); - cal.add(Calendar.HOUR, hours); - - return cal.getTime(); - } - - /** - * Get days of a month - * - * @param year The year - * @param month The month - * @return The days in the month - */ - public static int getDaysInMonth(int year, int month) { - Calendar cal = Calendar.getInstance(); - cal.set(year, month, 1); - - return cal.getActualMaximum(Calendar.DAY_OF_MONTH); - } - - /** - * Get time values - Time delta values of base date - * - * @param times Time list - * @param baseDate Base date - * @param tDelta Time delta type - days/hours/... - * @return The time delta values - */ - public static List getTimeDeltaValues(List times, Date baseDate, String tDelta) { - List values = new ArrayList<>(); - Calendar cal = Calendar.getInstance(); - cal.setTime(baseDate); - long sl = cal.getTimeInMillis(); - long el, delta; - int value; - for (int i = 0; i < times.size(); i++) { - cal.setTime(times.get(i)); - el = cal.getTimeInMillis(); - delta = el - sl; - if (tDelta.equalsIgnoreCase("hours")) { - value = (int) (delta / (60 * 60 * 1000)); - values.add(value); - } else if (tDelta.equalsIgnoreCase("days")) { - value = (int) (delta / (24 * 60 * 60 * 1000)); - values.add(value); - } - } - - return values; - } - - /** - * Get time value - Time delta value of base date - * - * @param t The time - * @param baseDate Base date - * @param tDelta Time delta type - days/hours/... - * @return The time delta value - */ - public static int getTimeDeltaValue(Date t, Date baseDate, String tDelta) { - Calendar cal = Calendar.getInstance(); - cal.setTime(baseDate); - long sl = cal.getTimeInMillis(); - long el, delta; - int value = 0; - cal.setTime(t); - el = cal.getTimeInMillis(); - delta = el - sl; - if (tDelta.equalsIgnoreCase("hours")) { - value = (int) (delta / (60 * 60 * 1000)); - } else if (tDelta.equalsIgnoreCase("days")) { - value = (int) (delta / (24 * 60 * 60 * 1000)); - } - - return value; - } - - /** - * Get days difference between two dates - * - * @param t The time - * @param baseDate Base date - * @return The time delta value - */ - public static int getDays(Date t, Date baseDate) { - Calendar cal = Calendar.getInstance(); - cal.setTime(baseDate); - long sl = cal.getTimeInMillis(); - long el, delta; - cal.setTime(t); - el = cal.getTimeInMillis(); - delta = el - sl; - int value = (int) (delta / (24 * 60 * 60 * 1000)); - - return value; - } - - /** - * Get hours difference between two dates - * - * @param t The time - * @param baseDate Base date - * @return The time delta value - */ - public static int getHours(Date t, Date baseDate) { - Calendar cal = Calendar.getInstance(); - cal.setTime(baseDate); - long sl = cal.getTimeInMillis(); - long el, delta; - cal.setTime(t); - el = cal.getTimeInMillis(); - delta = el - sl; - int value = (int) (delta / (60 * 60 * 1000)); - - return value; - } - - /** - * Convert OA date to date - * - * @param oaDate OA date - * @return Date - */ - public static Date fromOADate(double oaDate) { - Date date = new Date(); - //long t = (long)((oaDate - 25569) * 24 * 3600 * 1000); - //long t = (long) (oaDate * 1000000); - long t = (long) BigDecimalUtil.mul(oaDate, 1000000); - date.setTime(t); - return date; - } - - /** - * Convert date to OA date - * - * @param date Date - * @return OA date - */ - public static double toOADate(Date date) { - double oaDate = date.getTime(); - //oaDate = oaDate / (24 * 3600 * 1000) + 25569; - //oaDate = oaDate / 1000000; - oaDate = BigDecimalUtil.div(oaDate, 1000000); - - return oaDate; - } - - /** - * Date equals - * - * @param a Date a - * @param b Date b - * @return If equals - */ - public static boolean equals(Date a, Date b) { - if (a.getTime() == b.getTime()) { - return true; - } else { - return false; - } - } - - /** - * Get day of year - * - * @param year Year - * @param month Month - * @param day Day - * @return Day of year - */ - public static int dayOfYear(int year, int month, int day) { - Calendar cal = Calendar.getInstance(); - cal.set(year, month, day); - int doy = cal.get(Calendar.DAY_OF_YEAR); - return doy; - } - - /** - * Convert day of year to date - * - * @param year Year - * @param doy Day of year - * @return The date - */ - public static Date doy2date(int year, int doy) { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.DAY_OF_YEAR, doy); - return cal.getTime(); - } - - /** - * Get period type from string - * - * @param p Period type string - * @return PeriodType - */ - public static PeriodType getPeriodType(String p) { - PeriodType pt = PeriodType.days(); - switch (p) { - case "H": - pt = PeriodType.hours(); - break; - case "M": - pt = PeriodType.minutes(); - break; - case "S": - pt = PeriodType.seconds(); - break; - case "m": - pt = PeriodType.months(); - break; - case "Y": - pt = PeriodType.years(); - break; - } - - return pt; - } - - /** - * Get period from string - * - * @param pStr Period string - * @return Period - */ - public static ReadablePeriod getPeriod(String pStr) { - String p; - int n = 1; - int idx = 0; - for (int i = 0; i < pStr.length(); i++) { - if (Character.isLetter(pStr.charAt(i))){ - break; - } - idx += 1; - } - if (idx == 0) { - p = pStr; - } else { - p = pStr.substring(idx); - n = Integer.parseInt(pStr.substring(0, idx)); - } - - ReadablePeriod pe; - switch (p) { - case "H": - pe = Hours.hours(n); - break; - case "T": - case "Min": - pe = Minutes.minutes(n); - break; - case "S": - pe = Seconds.seconds(n); - break; - case "D": - pe = Days.days(n); - break; - case "W": - pe = Weeks.weeks(n); - break; - case "M": - pe = Months.months(n); - break; - case "Y": - pe = Years.years(n); - break; - default: - pe = new Period(); - break; - } - - return pe; - } - - /** - * Get date format string - * - * @param p Period - * @return Date format string - */ - public static String getDateFormat(ReadablePeriod p) { - String df = "yyyy-MM-dd"; - if (p instanceof Hours) { - df = "yyyy-MM-dd HH"; - } else if (p instanceof Minutes) { - df = "yyyy-MM-dd HH:mm"; - } else if (p instanceof Seconds) { - df = "yyyy-MM-dd HH:mm:ss"; - } - - return df; - } - - /** - * Get date time from string - * - * @param dts Date time string - * @return DateTime - */ - public static DateTime getDateTime(String dts) { - int year, month, day; - String dateStr = dts; - String timeStr = null; - if (dts.contains(":")) { - String[] v = dts.split("\\s+"); - dateStr = v[0].trim(); - timeStr = v[1].trim(); - } - if (dateStr.contains("/")) { - String[] ymd = dateStr.split("/"); - month = Integer.parseInt(ymd[0]); - day = Integer.parseInt(ymd[1]); - year = Integer.parseInt(ymd[2]); - } else if (dateStr.contains("-")) { - String[] ymd = dateStr.split("-"); - month = Integer.parseInt(ymd[1]); - day = Integer.parseInt(ymd[2]); - year = Integer.parseInt(ymd[0]); - } else { - year = Integer.parseInt(dateStr.substring(0, 4)); - month = Integer.parseInt(dateStr.substring(4, 6)); - day = Integer.parseInt(dateStr.substring(6)); - } - int hour = 0, minute = 0, second = 0; - if (timeStr != null) { - String[] hms = timeStr.split(":"); - hour = Integer.parseInt(hms[0]); - minute = Integer.parseInt(hms[1]); - second = hms.length == 3 ? Integer.parseInt(hms[2]) : 0; - } - - return new DateTime(year, month, day, hour, minute, second); - } - - /** - * Get date time from string - * - * @param dts Date time string - * @return DateTime - */ - public static DateTime getDateTime_(String dts) { - DateTimeFormatter dtf; - if (dts.contains(":")) { - dtf = TypeUtilsBak.getDateTimeFormatter(dts); - } else { - dtf = TypeUtilsBak.getDateFormatter(dts); - } - DateTime dt = dtf.parseDateTime(dts); - return dt; - } - - /** - * Get date time list - * - * @param start Start date time - * @param end End date time - * @param p Peroid - * @return Date time list - */ - public static List getDateTimes(DateTime start, DateTime end, ReadablePeriod p) { - List dts = new ArrayList<>(); - while (!start.isAfter(end)) { - dts.add(start); - start = start.plus(p); - } - - return dts; - } - - /** - * Get date time list - * - * @param start Start date time - * @param tNum Date time number - * @param p Peroid - * @return Date time list - */ - public static List getDateTimes(DateTime start, int tNum, ReadablePeriod p) { - List dts = new ArrayList<>(); - for (int i = 0; i < tNum; i++) { - dts.add(start); - start = start.plus(p); - } - - return dts; - } - - /** - * Get date time list - * - * @param end End date time - * @param tNum Date time number - * @param p Peroid - * @return Date time list - */ - public static List getDateTimes(int tNum, DateTime end, ReadablePeriod p) { - List dts = new ArrayList<>(); - for (int i = 0; i < tNum; i++) { - dts.add(end); - end = end.minus(p); - } - - return dts; - } - // -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/FontUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/FontUtil.java index 13bc4c8c..bf2e9fea 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/FontUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/FontUtil.java @@ -1,128 +1,130 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global.util; - -import java.awt.Font; -import java.awt.FontFormatException; -import java.awt.GraphicsEnvironment; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.legend.MapFrame; - -/** - * - * @author yaqiang - */ -public class FontUtil { - - /** - * Get all available fonts (system fonts, weather font and custom fonts) - * - * @return Font list - */ - public static List getAllFonts() { - List fontList = new ArrayList<>(); - - //Weather font - Font weatherFont = getWeatherFont(); - if (weatherFont != null) { - fontList.add(weatherFont); - } - - //System fonts - GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Font[] fonts = gEnv.getAllFonts(); - for (Font font : fonts) { - fontList.add(font); - } - - //Custom fonts - String fn = GlobalUtil.getAppPath(MapFrame.class); - fn = fn.substring(0, fn.lastIndexOf("/")); - String path = fn + File.separator + "font"; - File pathDir = new File(path); - if (pathDir.isDirectory()) { - - } - - return fontList; - } - - /** - * Register a font - * @param font The font - */ - public static void registerFont(Font font){ - GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); - } - - /** - * Register a font - * @param fileName Font file name - */ - public static void registerFont(String fileName){ - Font font = getFont(fileName); - if (font != null){ - registerFont(font); - } - } - - /** - * Register weather font - */ - public static void registerWeatherFont(){ - Font weatherFont = getWeatherFont(); - if (weatherFont != null) { - GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(weatherFont); - } - } - - /** - * Get font from font file - .ttf - * @param fileName Font file name - * @return The font - */ - public static Font getFont(String fileName){ - Font font = null; - try { - font = Font.createFont(Font.TRUETYPE_FONT, new File(fileName)); - } catch (FontFormatException | IOException ex) { - Logger.getLogger(FontUtil.class.getName()).log(Level.SEVERE, null, ex); - } - return font; - } - - /** - * Get weather symbol font - * - * @return Weather symbol font - */ - public static Font getWeatherFont() { - Font font = null; - InputStream is = Draw.class.getResourceAsStream("/fonts/WeatherSymbol.ttf"); - try { - font = Font.createFont(Font.TRUETYPE_FONT, is); - } catch (FontFormatException | IOException ex) { - Logger.getLogger(Draw.class.getName()).log(Level.SEVERE, null, ex); - } - - return font; - } -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.global.util; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.legend.MapFrame; + +/** + * + * @author yaqiang + */ +public class FontUtil { + + /** + * Get all available fonts (system fonts, weather font and custom fonts) + * + * @return Font list + */ + public static List getAllFonts() { + List fontList = new ArrayList<>(); + + //Weather font + Font weatherFont = getWeatherFont(); + if (weatherFont != null) { + fontList.add(weatherFont); + } + + //System fonts + GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Font[] fonts = gEnv.getAllFonts(); + for (Font font : fonts) { + fontList.add(font); + } + + //Custom fonts + String fn = GlobalUtil.getAppPath(MapFrame.class); + fn = fn.substring(0, fn.lastIndexOf("/")); + String path = fn + File.separator + "font"; + File pathDir = new File(path); + if (pathDir.isDirectory()) { + + } + + return fontList; + } + + /** + * Register a font + * @param font The font + */ + public static void registerFont(Font font){ + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + } + + /** + * Register a font + * @param fileName Font file name + */ + public static void registerFont(String fileName){ + Font font = getFont(fileName); + if (font != null){ + registerFont(font); + } + } + + /** + * Register weather font + */ + public static void registerWeatherFont(){ + Font weatherFont = getWeatherFont(); + if (weatherFont != null) { + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(weatherFont); + } + } + + /** + * Get font from font file - .ttf + * @param fileName Font file name + * @return The font + */ + public static Font getFont(String fileName){ + Font font = null; + try { + font = Font.createFont(Font.TRUETYPE_FONT, new File(fileName)); + } catch (FontFormatException | IOException ex) { + Logger.getLogger(FontUtil.class.getName()).log(Level.SEVERE, null, ex); + } + return font; + } + + /** + * Get weather symbol font + * + * @return Weather symbol font + */ + public static Font getWeatherFont() { + Font font = null; + InputStream is = Draw.class.getResourceAsStream("/fonts/WeatherSymbol.ttf"); + try { + font = Font.createFont(Font.TRUETYPE_FONT, is); + } catch (FontFormatException | IOException ex) { + Logger.getLogger(Draw.class.getName()).log(Level.SEVERE, null, ex); + } + + return font; + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GlobalUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GlobalUtil.java deleted file mode 100644 index a775450c..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GlobalUtil.java +++ /dev/null @@ -1,682 +0,0 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global.util; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Toolkit; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.FilteredImageSource; -import java.awt.image.ImageFilter; -import java.awt.image.ImageProducer; -import java.awt.image.RGBImageFilter; -import java.awt.image.WritableRaster; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * Template - * - * @author Yaqiang Wang - */ -public class GlobalUtil { - // - // - // - // - // - // - // - - /** - * Get software version - * @return Software version - */ - public static String getVersion(){ - String version = GlobalUtil.class.getPackage().getImplementationVersion(); - return version; - } - - /** - * Get file extension - * - * @param filePath The file path - * @return File extension - */ - public static String getFileExtension(String filePath) { - String extension = ""; - String fn = new File(filePath).getName(); - if (fn.contains(".")) { - String ext = filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase().trim(); - try { - extension = ext; - } catch (IllegalArgumentException e) { - } - } - - return extension; - } - - /** - * Get the list of specific file types in a directory - * - * @param directory The directory - * @param ext the file extension - * @return File name list - */ - public static List getFiles(String directory, String ext) { - List fileNames = new ArrayList<>(); - try { - File f = new File(directory); - boolean flag = f.isDirectory(); - if (flag) { - File fs[] = f.listFiles(); - for (int i = 0; i < fs.length; i++) { - if (!fs[i].isDirectory()) { - String filename = fs[i].getAbsolutePath(); - if (filename.endsWith(ext.trim())) { - fileNames.add(filename); - } - } else { - fileNames.addAll(getFiles(fs[i].getAbsolutePath(), ext)); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return fileNames; - } - - /** - * Get sub directories - * - * @param directory The directory - * @return Sub directories - */ - public static List getSubDirectories(String directory) { - List subDirs = new ArrayList<>(); - File f = new File(directory); - File fs[] = f.listFiles(); - for (File f1 : fs) { - if (f1.isDirectory()) { - subDirs.add(f1.getPath()); - } - } - - return subDirs; - } - - /** - * Get class names in a jar file - * - * @param jarFileName The jar file name - * @return The class names in the jar file - * @throws FileNotFoundException - * @throws IOException - */ - public static List getClassNames(String jarFileName) throws FileNotFoundException, IOException { - List classNames = new ArrayList<>(); - ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFileName)); - for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) { - if (entry.getName().endsWith(".class") && !entry.isDirectory()) { - // This ZipEntry represents a class. Now, what class does it represent? - StringBuilder className = new StringBuilder(); - for (String part : entry.getName().split("/")) { - if (className.length() != 0) { - className.append("."); - } - className.append(part); - if (part.endsWith(".class")) { - className.setLength(className.length() - ".class".length()); - } - } - classNames.add(className.toString()); - } - } - - return classNames; - } - - /** - * Get the class name which implements IPlugin interface - * - * @param jarFileName The jar file name - * @return The class name which implements IPlugin interface - */ - public static String getPluginClassName(String jarFileName) { - String pluginClassName = null; - try { - List classNames = getClassNames(jarFileName); - URL url = new URL("file:" + jarFileName); - URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}); - for (String name : classNames) { - Class clazz = urlClassLoader.loadClass(name); - if (isInterface(clazz, "org.meteoinfo.plugin.IPlugin")) { - pluginClassName = name; - break; - } - } - } catch (FileNotFoundException ex) { - Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); - } catch (ClassNotFoundException ex) { - Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); - } - - return pluginClassName; - } - - /** - * Given a package name, attempts to reflect to find all classes within the - * package on the local file system. - * - * @param packageName - * @return Class list - */ - public static List getClassesInPackage(String packageName) { - List classes = new ArrayList<>(); - String packageNameSlashed = "/" + packageName.replace(".", "/"); - // Get a File object for the package - URL directoryURL = Thread.currentThread().getContextClassLoader().getResource(packageNameSlashed); - if (directoryURL == null) { - System.out.println("Could not retrieve URL resource: " + packageNameSlashed); - return classes; - } - - String directoryString = directoryURL.getFile(); - if (directoryString == null) { - System.out.println("Could not find directory for URL resource: " + packageNameSlashed); - return classes; - } - - File directory = new File(directoryString); - if (directory.exists()) { - // Get the list of the files contained in the package - String[] files = directory.list(); - for (String fileName : files) { - // We are only interested in .class files - if (fileName.endsWith(".class")) { - // Remove the .class extension - fileName = fileName.substring(0, fileName.length() - 6); - try { - classes.add(Class.forName(packageName + "." + fileName)); - } catch (ClassNotFoundException e) { - System.out.println(packageName + "." + fileName + " does not appear to be a valid class."); - } - } - } - } else { - System.out.println(packageName + " does not appear to exist as a valid package on the file system."); - } - return classes; - } - - /** - * Given a package name, attempts to reflect to find all file names within the - * package on the local file system. - * - * @param packageName - * @return File names - */ - public static List getFilesInPackage(String packageName) { - List fns = new ArrayList<>(); - //String packageNameSlashed = "/" + packageName.replace(".", "/"); - String packageNameSlashed = packageName.replace(".", "/"); - // Get a File object for the package - URL directoryURL = Thread.currentThread().getContextClassLoader().getResource(packageNameSlashed); - if (directoryURL == null) { - System.out.println("Could not retrieve URL resource: " + packageNameSlashed); - return fns; - } - - String directoryString = directoryURL.getFile(); - if (directoryString == null) { - System.out.println("Could not find directory for URL resource: " + packageNameSlashed); - return fns; - } - - File directory = new File(directoryString); - if (directory.exists()) { - // Get the list of the files contained in the package - String[] files = directory.list(); - for (String fileName : files) { - fns.add(fileName); - } - } else { - System.out.println(packageName + " does not appear to exist as a valid package on the file system."); - } - return fns; - } - - /** - * Determine if a class implements a interface - * - * @param c The class - * @param szInterface The interface name - * @return Boolean - */ - public static boolean isInterface(Class c, String szInterface) { - Class[] face = c.getInterfaces(); - for (int i = 0, j = face.length; i < j; i++) { - if (face[i].getName().equals(szInterface)) { - return true; - } else { - Class[] face1 = face[i].getInterfaces(); - for (int x = 0; x < face1.length; x++) { - if (face1[x].getName().equals(szInterface)) { - return true; - } else if (isInterface(face1[x], szInterface)) { - return true; - } - } - } - } - if (null != c.getSuperclass()) { - return isInterface(c.getSuperclass(), szInterface); - } - return false; - } - - /** - * Get root path - * - * @param aFile The file - * @return Root path - */ - public static String getPathRoot(File aFile) { - File path = aFile.getParentFile(); - String pathRoot = path.toString(); - while (path != null) { - path = path.getParentFile(); - if (path != null) { - pathRoot = path.toString(); - } - } - - return pathRoot; - } - - /** - * Get relative path of the file using project file path - * - * @param fileName File path - * @param projFile Project file path - * @return Relative path - * @throws java.io.IOException - */ - public static String getRelativePath(String fileName, String projFile) throws IOException { - String RelativePath = ""; - File aFile = new File(fileName); - File pFile = new File(projFile); - fileName = aFile.getCanonicalPath(); - - String layerPathRoot = getPathRoot(aFile); - String projPathRoot = getPathRoot(pFile); - if (!layerPathRoot.equalsIgnoreCase(projPathRoot)) { - RelativePath = fileName; - } else { - List aList = new ArrayList<>(); - aList.add(fileName); - do { - aList.add(""); - File tempFile = new File(aList.get(aList.size() - 2)); - if (tempFile.exists() && tempFile.getParent() != null) { - aList.set(aList.size() - 1, tempFile.getParent()); - } else { - break; - } - } while (!"".equals(aList.get(aList.size() - 1))); - - List bList = new ArrayList<>(); - bList.add(pFile.getCanonicalPath()); - do { - bList.add(""); - File tempFile = new File(bList.get(bList.size() - 2)); - if (tempFile.getParent() != null) { - bList.set(bList.size() - 1, tempFile.getParent()); - } else { - break; - } - } while (!"".equals(bList.get(bList.size() - 1))); - - boolean ifExist = false; - int offSet; - for (int i = 0; i < aList.size(); i++) { - for (int j = 0; j < bList.size(); j++) { - if (aList.get(i).equals(bList.get(j))) { - for (int k = 1; k < j; k++) { - RelativePath = RelativePath + ".." + File.separator; - } - if (aList.get(i).endsWith(File.separator)) { - offSet = 0; - } else { - offSet = 1; - } - RelativePath = RelativePath + fileName.substring(aList.get(i).length() + offSet); - ifExist = true; - break; - } - } - if (ifExist) { - break; - } - } - } - - if ("".equals(RelativePath)) { - RelativePath = fileName; - } - return RelativePath; - } - - /** - * Convert Image to BufferedImage - * - * @param image The Image - * @return The BufferedImage - */ - public static BufferedImage imageToBufferedImage(Image image) { - - BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = bufferedImage.createGraphics(); - g2.drawImage(image, 0, 0, null); - g2.dispose(); - - return bufferedImage; - - } - - /** - * Make a color of a image transparent - * - * @param im The image - * @param color The color - * @return Result image - */ - public static Image makeColorTransparent(BufferedImage im, final Color color) { - ImageFilter filter = new RGBImageFilter() { - // the color we are looking for... Alpha bits are set to opaque - public int markerRGB = color.getRGB() | 0xFF000000; - - @Override - public final int filterRGB(int x, int y, int rgb) { - if ((rgb | 0xFF000000) == markerRGB) { - // Mark the alpha bits as zero - transparent - return 0x00FFFFFF & rgb; - } else { - // nothing to do - return rgb; - } - } - }; - - ImageProducer ip = new FilteredImageSource(im.getSource(), filter); - return Toolkit.getDefaultToolkit().createImage(ip); - } - - /** - * Get application path by a class - * - * @param cls Class - * @return Application path - */ - public static String getAppPath(Class cls) { - if (cls == null) { - throw new java.lang.IllegalArgumentException("The parameter can not be null!"); - } - - ClassLoader loader = cls.getClassLoader(); - //Get class name - String clsName = cls.getName() + ".class"; - //Get package - Package pack = cls.getPackage(); - String path = ""; - if (pack != null) { - String packName = pack.getName(); - //Judge if is Java base class to avoid this condition - if (packName.startsWith("java.") || packName.startsWith("javax.")) { - throw new java.lang.IllegalArgumentException("Dont use Java system class!"); - } - //Remove package name from the class name - clsName = clsName.substring(packName.length() + 1); - //Convert package name to path if the package has simple name - if (!packName.contains(".")) { - path = packName + "/"; - } else { //Convert package name to path - int start = 0; - int end = packName.indexOf("."); - while (end != -1) { - path = path + packName.substring(start, end) + "/"; - start = end + 1; - end = packName.indexOf(".", start); - } - path = path + packName.substring(start) + "/"; - } - } - - //Get resource - java.net.URL url = loader.getResource(path + clsName); - //Get path - String realPath = url.getPath(); - //Remove "file:" - int pos = realPath.indexOf("file:"); - if (pos > -1) { - realPath = realPath.substring(pos + 5); - } - //Remove class info - pos = realPath.indexOf(path + clsName); - realPath = realPath.substring(0, pos - 1); - //Remove JAR package name - if (realPath.endsWith("!")) { - realPath = realPath.substring(0, realPath.lastIndexOf("/")); - } - - //Get Chinese path by decode - try { - realPath = java.net.URLDecoder.decode(realPath, "utf-8"); - } catch (Exception e) { - throw new RuntimeException(e); - } - - return realPath; - } - - /** - * String pad left - * - * @param str The string - * @param length Pad length - * @param ch Pad char - * @return Padded string - */ - public static String padLeft(String str, int length, char ch) { - for (int i = str.length(); i < length; i++) { - str = ch + str; - } - - return str; - } - - /** - * String pad right - * - * @param str The string - * @param length Pad length - * @param ch Pad char - * @return Padded string - */ - public static String padRight(String str, int length, char ch) { - for (int i = str.length(); i < length; i++) { - str = str + ch; - } - - return str; - } - - /** - * Deep clone object - * - * @param oldObj Old object - * @return Cloned object - * @throws Exception - */ - public static Object deepCopy(Object oldObj) throws Exception { - ObjectOutputStream oos = null; - ObjectInputStream ois = null; - try { - ByteArrayOutputStream bos - = new ByteArrayOutputStream(); // A - oos = new ObjectOutputStream(bos); // B - // serialize and pass the object - oos.writeObject(oldObj); // C - oos.flush(); // D - ByteArrayInputStream bin - = new ByteArrayInputStream(bos.toByteArray()); // E - ois = new ObjectInputStream(bin); // F - // return the new object - return ois.readObject(); // G - } catch (Exception e) { - System.out.println("Exception in ObjectCloner = " + e); - throw (e); - } finally { - oos.close(); - ois.close(); - } - } - - /** - * Deep clone a BufferedIamge - * - * @param bi Original image - * @return Cloned image - */ - public static BufferedImage deepCopy(BufferedImage bi) { - ColorModel cm = bi.getColorModel(); - boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); - WritableRaster raster = bi.copyData(null); - return new BufferedImage(cm, raster, isAlphaPremultiplied, null); - } - - /** - * Get default font name - * - * @return Default font name - */ - public static String getDefaultFontName() { - String[] fontnames = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); - List fns = Arrays.asList(fontnames); - String fn = "宋体"; - if (!fns.contains(fn)) { - fn = "Arial"; - } - - if (!fns.contains(fn)) { - fn = fontnames[0]; - } - - return fn; - } - - /** - * Get separator - * - * @param line The string line - * @return Delimiter string - */ - public static String getDelimiter(String line) { - String separator = null; - if (line.contains(",")) { - separator = ","; - } else if (line.contains(";")) { - separator = ";"; - } - - return separator; - } - - /** - * Get delimiter - * @param file File - * @return Delimiter - * @throws FileNotFoundException - * @throws IOException - */ - public static String getDelimiter(File file) throws FileNotFoundException, IOException{ - BufferedReader sr = new BufferedReader(new FileReader(file)); - String line = sr.readLine(); - sr.close(); - return getDelimiter(line); - } - - /** - * Split a string line by separator - * - * @param line The string line - * @param separator The separator - * @return Split string array - */ - public static String[] split(String line, String separator) { - if (separator == null || separator.equals(" ")) { - return line.split("\\s+"); - } else { - String[] strs = line.split(separator); - List r = new ArrayList<>(); - for (String s : strs){ - r.add(s.trim()); - } - strs = r.toArray(new String[1]); - return strs; - } - } - - /** - * Capitalize the first character of a string - * @param str The string - * @return Capitalized string - */ - public static String capitalize(String str){ - if(str == null || str.length() == 0) - return ""; - - if(str.length() == 1) - return str.toUpperCase(); - - char[] charArray = str.toCharArray(); - charArray[0] = Character.toUpperCase(charArray[0]); - return new String(charArray); - } - // -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtilsBak.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtilsBak.java deleted file mode 100644 index f323049c..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtilsBak.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.global.util; - -import com.google.common.collect.ImmutableList; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.DateTimeFormatterBuilder; -import org.joda.time.format.ISODateTimeFormat; - -import java.time.format.DateTimeParseException; -import java.util.Arrays; -import java.util.List; - -/** - * - * Ported from Tablesaw - */ -public class TypeUtilsBak { - // These Strings will convert to true booleans - public static final List TRUE_STRINGS = - Arrays.asList("T", "t", "Y", "y", "TRUE", "true", "True", "1"); - // A more restricted set of 'true' strings that is used for column type detection - public static final List TRUE_STRINGS_FOR_DETECTION = - Arrays.asList("T", "t", "Y", "y", "TRUE", "true", "True"); - // These Strings will convert to false booleans - public static final List FALSE_STRINGS = - Arrays.asList("F", "f", "N", "n", "FALSE", "false", "False", "0"); - // A more restricted set of 'false' strings that is used for column type detection - public static final List FALSE_STRINGS_FOR_DETECTION = - Arrays.asList("F", "f", "N", "n", "FALSE", "false", "False"); - - // Formats that we accept in parsing dates from strings - // TODO: Add more types, especially dates with month names spelled-out fully. - private static final DateTimeFormatter dtf1 = DateTimeFormat.forPattern("yyyyMMdd"); - private static final DateTimeFormatter dtf2 = DateTimeFormat.forPattern("MM/dd/yyyy"); - private static final DateTimeFormatter dtf3 = DateTimeFormat.forPattern("MM-dd-yyyy"); - private static final DateTimeFormatter dtf4 = DateTimeFormat.forPattern("MM.dd.yyyy"); - private static final DateTimeFormatter dtf5 = DateTimeFormat.forPattern("yyyy-MM-dd"); - private static final DateTimeFormatter dtf6 = DateTimeFormat.forPattern("yyyy/MM/dd"); - private static final DateTimeFormatter dtf7 = DateTimeFormat.forPattern("dd/MMM/yyyy"); - private static final DateTimeFormatter dtf8 = DateTimeFormat.forPattern("dd-MMM-yyyy"); - private static final DateTimeFormatter dtf9 = DateTimeFormat.forPattern("M/d/yyyy"); - private static final DateTimeFormatter dtf10 = DateTimeFormat.forPattern("M/d/yy"); - private static final DateTimeFormatter dtf11 = DateTimeFormat.forPattern("MMM/dd/yyyy"); - private static final DateTimeFormatter dtf12 = DateTimeFormat.forPattern("MMM-dd-yyyy"); - private static final DateTimeFormatter dtf13 = DateTimeFormat.forPattern("MMM/dd/yy"); - private static final DateTimeFormatter dtf14 = DateTimeFormat.forPattern("MMM-dd-yy"); - private static final DateTimeFormatter dtf15 = DateTimeFormat.forPattern("MMM/dd/yyyy"); - private static final DateTimeFormatter dtf16 = DateTimeFormat.forPattern("MMM/d/yyyy"); - private static final DateTimeFormatter dtf17 = DateTimeFormat.forPattern("MMM-dd-yy"); - private static final DateTimeFormatter dtf18 = DateTimeFormat.forPattern("MMM dd, yyyy"); - private static final DateTimeFormatter dtf19 = DateTimeFormat.forPattern("MMM d, yyyy"); - // A formatter that handles all the date formats defined above - public static final DateTimeFormatter DATE_FORMATTER = - new DateTimeFormatterBuilder() - .append(dtf1) - .append(dtf2) - .append(dtf3) - .append(dtf4) - .append(dtf5) - .append(dtf6) - .append(dtf7) - .append(dtf8) - .append(dtf9) - .append(dtf10) - .append(dtf11) - .append(dtf12) - .append(dtf13) - .append(dtf14) - .append(dtf15) - .append(dtf16) - .append(dtf17) - .append(dtf18) - .append(dtf19) - .toFormatter(); - private static final DateTimeFormatter dtTimef0 = - DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); // 2014-07-09 13:03:44 - private static final DateTimeFormatter dtTimef2 = - DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.S"); // 2014-07-09 13:03:44.7 (as above, but without leading 0 in millis - private static final DateTimeFormatter dtTimef4 = - DateTimeFormat.forPattern("dd-MMM-yyyy HH:mm"); // 09-Jul-2014 13:03 - private static final DateTimeFormatter dtTimef5 = ISODateTimeFormat.dateTime(); - private static final DateTimeFormatter dtTimef6; // ISO, with millis appended - private static final DateTimeFormatter dtTimef7 = // 7/9/14 9:04 - DateTimeFormat.forPattern("M/d/yy H:mm"); - private static final DateTimeFormatter dtTimef8 = - DateTimeFormat.forPattern("M/d/yyyy h:mm:ss a"); // 7/9/2014 9:04:55 PM - - static { - dtTimef6 = new DateTimeFormatterBuilder() - .append(ISODateTimeFormat.dateTime()) - .appendLiteral('.') - .appendPattern("SSS") - .toFormatter(); - } - - // A formatter that handles date time formats defined above - public static final DateTimeFormatter DATE_TIME_FORMATTER = - new DateTimeFormatterBuilder() - .append(dtTimef7) - .append(dtTimef8) - .append(dtTimef2) - .append(dtTimef4) - .append(dtTimef0) - .append(dtTimef5) - .append(dtTimef6) - .toFormatter(); - private static final DateTimeFormatter timef1 = DateTimeFormat.forPattern("HH:mm:ss.SSS"); - private static final DateTimeFormatter timef2 = DateTimeFormat.forPattern("hh:mm:ss a"); - private static final DateTimeFormatter timef3 = DateTimeFormat.forPattern("h:mm:ss a"); - private static final DateTimeFormatter timef4 = ISODateTimeFormat.dateTime(); - private static final DateTimeFormatter timef5 = DateTimeFormat.forPattern("hh:mm a"); - private static final DateTimeFormatter timef6 = DateTimeFormat.forPattern("h:mm a"); - // A formatter that handles time formats defined above used for type detection. - // It is more conservative than the converter - public static final DateTimeFormatter TIME_DETECTION_FORMATTER = - new DateTimeFormatterBuilder() - .append(timef5) - .append(timef2) - .append(timef3) - .append(timef1) - .append(timef4) - .append(timef6) - // .append(timef7) - .toFormatter(); - private static final DateTimeFormatter timef7 = DateTimeFormat.forPattern("HHmm"); - // A formatter that handles time formats defined above - public static final DateTimeFormatter TIME_FORMATTER = - new DateTimeFormatterBuilder() - .append(timef5) - .append(timef2) - .append(timef3) - .append(timef1) - .append(timef4) - .append(timef6) - .append(timef7) - .toFormatter(); - /** - * Strings representing missing values in, for example, a CSV file that is being imported - */ - private static final String missingInd1 = "NaN"; - private static final String missingInd2 = "*"; - private static final String missingInd3 = "NA"; - private static final String missingInd4 = "null"; - public static final ImmutableList MISSING_INDICATORS = ImmutableList.of( - missingInd1, - missingInd2, - missingInd3, - missingInd4 - ); - /** - * List of formatters for use in code that selects the correct one for a given Date string - */ - private static ImmutableList dateFormatters = ImmutableList.of( - dtf1, - dtf2, - dtf3, - dtf4, - dtf5, - dtf6, - dtf7, - dtf8, - dtf9, - dtf10, - dtf11, - dtf12, - dtf13, - dtf14, - dtf15, - dtf16, - dtf17, - dtf18, - dtf19 - ); - /** - * List of formatters for use in code that selects the correct one for a given DateTime string - */ - private static ImmutableList dateTimeFormatters = ImmutableList.of( - dtTimef0, - dtTimef2, - dtTimef4, - dtTimef5, - dtTimef6, - dtTimef7, - dtTimef8 - ); - /** - * List of formatters for use in code that selects the correct one for a given Time string - */ - private static ImmutableList timeFormatters = ImmutableList.of( - timef1, - timef2, - timef3, - timef4, - timef5, - timef6 - ); - - /** - * Private constructor to prevent instantiation - */ - private TypeUtilsBak() { - } - - /** - * Returns the first DateTimeFormatter to parse the string, which represents a DATE - *

- * It's intended to be called at the start of a large formatting job so that it picks the write format and is not - * called again. This is an optimization, because the older version, which will try multiple formatters was too - * slow for large data sets. - */ - public static DateTimeFormatter getDateFormatter(String dateValue) { - - for (DateTimeFormatter formatter : dateFormatters) { - try { - formatter.parseDateTime(dateValue); - return formatter; - } catch (DateTimeParseException e) { - // ignore; - } - } - return DATE_FORMATTER; - } - - /** - * Returns the first DateTimeFormatter to parse the string, which represents a DATE_TIME - *

- * It's intended to be called at the start of a large formatting job so that it picks the write format and is not - * called again. This is an optimization, because the older version, which will try multiple formatters was too - * slow for large data sets. - */ - public static DateTimeFormatter getDateTimeFormatter(String dateTimeValue) { - for (DateTimeFormatter formatter : dateTimeFormatters) { - if (canParse(formatter, dateTimeValue)) { - return formatter; - } - } - if (canParse(DATE_FORMATTER, dateTimeValue)) { - return DATE_FORMATTER; - } - if (canParse(DATE_TIME_FORMATTER, dateTimeValue)) { - return DATE_TIME_FORMATTER; - } - throw new IllegalArgumentException("Could not find datetime parser for " + dateTimeValue); - } - - private static boolean canParse(DateTimeFormatter formatter, String dateTimeValue) { - try { - formatter.parseDateTime(dateTimeValue); - return true; - } catch (DateTimeParseException e) { - return false; - } - } - - /** - * Returns the first DateTimeFormatter to parse the string, which represents a TIME - *

- * It's intended to be called at the start of a large formatting job so that it picks the write format and is not - * called again. This is an optimization, because the older version, which will try multiple formatters was too - * slow for large data sets. - */ - public static DateTimeFormatter getTimeFormatter(String timeValue) { - for (DateTimeFormatter formatter : timeFormatters) { - try { - formatter.parseDateTime(timeValue); - return formatter; - } catch (DateTimeParseException e) { - // ignore; - } - } - return DATE_FORMATTER; - } - -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataInputStream.java b/MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataInputStream.java deleted file mode 100644 index 0284a4c2..00000000 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataInputStream.java +++ /dev/null @@ -1,136 +0,0 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.io; - -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.IOException; - -/** - * - * @author yaqiang - come from OpenJump - */ -public class EndianDataInputStream { - private final java.io.DataInputStream inputStream; - private final byte[] workSpace = new byte[8]; //chars are 16 bits, so we always quash the 1st 8 bits - - /** Creates new EndianDataInputStream - * @param in */ - public EndianDataInputStream(java.io.InputStream in) { - inputStream = new DataInputStream(new BufferedInputStream(in)); - } - - /** close the strea*/ - public void close() throws IOException { - inputStream.close(); - } - - /** read a byte in BigEndian - the same as LE because its only 1 byt*/ - public byte readByteBE() throws IOException { - return inputStream.readByte(); - } - - /** read a byte in LittleEndian - the same as BE because its only 1 byt*/ - public byte readByteLE() throws IOException { - return inputStream.readByte(); - } - - /** read a byte in LittleEndian - the same as BE because its only 1 byte*/ - public void readByteLEnum(byte[] b) throws IOException { - inputStream.readFully(b); - } - - - /** read a byte in BigEndian - the same as LE because its only 1 byte. returns int as per java.io.DataStream*/ - public int readUnsignedByteBE() throws IOException { - return inputStream.readUnsignedByte(); - } - - /** read a byte in LittleEndian - the same as BE because its only 1 byte. returns int as per java.io.DataStream*/ - public int readUnsignedByteLE() throws IOException { - return inputStream.readUnsignedByte(); - } - - /** read a 16bit short in BE*/ - public short readShortBE() throws IOException { - return inputStream.readShort(); - } - - /** read a 16bit short in LE*/ - public short readShortLE() throws IOException { - inputStream.readFully(workSpace, 0, 2); - - return (short) (((workSpace[1] & 0xff) << 8) | (workSpace[0] & 0xff)); - } - - /** read a 32bit int in BE*/ - public int readIntBE() throws IOException { - return inputStream.readInt(); - } - - /** read a 32bit int in LE*/ - public int readIntLE() throws IOException { - inputStream.readFully(workSpace, 0, 4); - - return ((workSpace[3] & 0xff) << 24) | ((workSpace[2] & 0xff) << 16) | - ((workSpace[1] & 0xff) << 8) | (workSpace[0] & 0xff); - } - - /** read a 64bit long in BE*/ - public long readLongBE() throws IOException { - return inputStream.readLong(); - } - - /** read a 64bit long in LE*/ - public long readLongLE() throws IOException { - inputStream.readFully(workSpace, 0, 8); - - return ((long) (workSpace[7] & 0xff) << 56) | - ((long) (workSpace[6] & 0xff) << 48) | - ((long) (workSpace[5] & 0xff) << 40) | - ((long) (workSpace[4] & 0xff) << 32) | - ((long) (workSpace[3] & 0xff) << 24) | - ((long) (workSpace[2] & 0xff) << 16) | - ((long) (workSpace[1] & 0xff) << 8) | ((long) (workSpace[0] & 0xff)); - } - - /** read a 64bit double in BE*/ - public double readDoubleBE() throws IOException { - return inputStream.readDouble(); - } - - /** read a 64bit double in LE*/ - public double readDoubleLE() throws IOException { - long l; - - inputStream.readFully(workSpace, 0, 8); - l = ((long) (workSpace[7] & 0xff) << 56) | - ((long) (workSpace[6] & 0xff) << 48) | - ((long) (workSpace[5] & 0xff) << 40) | - ((long) (workSpace[4] & 0xff) << 32) | - ((long) (workSpace[3] & 0xff) << 24) | - ((long) (workSpace[2] & 0xff) << 16) | - ((long) (workSpace[1] & 0xff) << 8) | - ((long) (workSpace[0] & 0xff)); - - return Double.longBitsToDouble(l); - } - - /** skip ahead in the stream - * @param num number of bytes to read ahead - */ - public int skipBytes(int num) throws IOException { - return inputStream.skipBytes(num); - } -} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLabelSet.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLabelSet.java index 5f169b2b..a0af2f98 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLabelSet.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLabelSet.java @@ -5,7 +5,6 @@ package org.meteoinfo.layer; import org.meteoinfo.data.mapdata.Field; -import org.meteoinfo.global.MIMath; import org.meteoinfo.legend.AlignType; import org.meteoinfo.map.MapView; import org.meteoinfo.shape.ShapeTypes; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLayerProperty.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLayerProperty.java index 82dcc22c..16e2f2e5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLayerProperty.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/FrmLayerProperty.java @@ -5,8 +5,8 @@ package org.meteoinfo.layer; import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.MIMath; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.MIMath; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.legend.ColorBreak; import org.meteoinfo.legend.FrmLegendBreaks; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/ImageLayer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/ImageLayer.java index ad47c6a6..35c8c7fa 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/ImageLayer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/ImageLayer.java @@ -1,890 +1,890 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layer; - -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.shape.ShapeTypes; -import java.awt.Color; -import java.awt.Image; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.awt.image.Raster; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author Yaqiang Wang - */ -public class ImageLayer extends MapLayer { - // - - private BufferedImage _image; - private WorldFilePara _worldFilePara = new WorldFilePara(); - private String _worldFileName; - private boolean _isSetTransColor; - private Color _transparencyColor; - protected Object interp; - // - // - - /** - * Constructor - */ - public ImageLayer() { - super(); - this.setLayerType(LayerTypes.ImageLayer); - this.setShapeType(ShapeTypes.Image); - _isSetTransColor = false; - _transparencyColor = Color.black; - this.interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - } - // - // - - /** - * Get image - * - * @return The image - */ - public BufferedImage getImage() { - return _image; - } - - /** - * Set image - * - * @param image The image - */ - public void setImage(BufferedImage image) { - _image = image; - _transparencyColor = new Color(image.getRGB(1, 1)); - } - - /** - * Get world file name of the layer - * - * @return World file name - */ - public String getWorldFileName() { - return _worldFileName; - } - - /** - * Set world file name - * - * @param name World file name - */ - public void setWorldFileName(String name) { - _worldFileName = name; - } - - /** - * Get world file parameters - * - * @return World file parameters - */ - public WorldFilePara getWorldFilePara() { - return _worldFilePara; - } - - /** - * Set world file parameters - * - * @param value World file parameters - */ - public void setWorldFilePara(WorldFilePara value) { - _worldFilePara = value; - } - - /** - * Get if set transparency color - * - * @return Boolean - */ - public boolean isUseTransColor() { - return _isSetTransColor; - } - - /** - * Set if using transparency color - * - * @param istrue Boolean - */ - public void setUseTransColor(boolean istrue) { - _isSetTransColor = istrue; - if (istrue) { - Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); - _image = GlobalUtil.imageToBufferedImage(image); - } - } - - /** - * Get transparency color - * - * @return Transparency color - */ - public Color getTransparencyColor() { - return _transparencyColor; - } - - /** - * Set transparency color - * - * @param color The color - */ - public void setTransparencyColor(Color color) { - _transparencyColor = color; - if (_isSetTransColor) { - Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); - _image = GlobalUtil.imageToBufferedImage(image); - } - } - - /** - * Get X upper-left - * - * @return Upper-left x value - */ - public double getXUL() { - return _worldFilePara.xUL; - } - - /** - * Set upper-left x - * - * @param value The value - * @throws java.io.IOException - */ - public void setXUL(double value) throws IOException { - _worldFilePara.xUL = value; - Extent aExtent = (Extent) this.getExtent().clone(); - aExtent.minX = _worldFilePara.xUL; - aExtent.maxX = _worldFilePara.xUL + this.getExtent().getWidth(); - this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y upper-left - * - * @return Upper-left y - */ - public double getYUL() { - return _worldFilePara.yUL; - } - - /** - * Set upper-left y - * - * @param value The value - * @throws java.io.IOException - */ - public void setYUL(double value) throws IOException { - _worldFilePara.yUL = value; - Extent aExtent = (Extent) this.getExtent().clone(); - aExtent.maxY = _worldFilePara.yUL; - aExtent.minY = _worldFilePara.yUL - this.getExtent().getHeight(); - this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get x scale - * - * @return The x scale - */ - public double getXScale() { - return _worldFilePara.xScale; - } - - /** - * Set x scale - * - * @param value The value - * @throws java.io.IOException - */ - public void setXScale(double value) throws IOException { - _worldFilePara.xScale = value; - Extent aExtent = (Extent) this.getExtent(); - double width = _image.getWidth() * _worldFilePara.xScale; - aExtent.maxX = _worldFilePara.xUL + width; - this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y scale - * - * @return The y scale - */ - public double getYScale() { - return _worldFilePara.yScale; - } - - /** - * Set y scale - * - * @param value The y scale value - * @throws IOException - */ - public void setYScale(double value) throws IOException { - _worldFilePara.yScale = value; - Extent aExtent = (Extent) this.getExtent(); - double height = _image.getHeight() * _worldFilePara.yScale; - aExtent.minY = _worldFilePara.yUL + height; - this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get x rotate(shear) - * - * @return X rotate - */ - public double getXRotate() { - return _worldFilePara.xRotate; - } - - /** - * Set x rotate(shear) - * - * @param value Value - * @throws IOException - */ - public void setXRotate(double value) throws IOException { - _worldFilePara.xRotate = value; - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y rotate(shear) - * - * @return X rotate - */ - public double getYRotate() { - return _worldFilePara.yRotate; - } - - /** - * Set y rotate(shear) - * - * @param value Value - * @throws IOException - */ - public void setYRotate(double value) throws IOException { - _worldFilePara.yRotate = value; - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get interpolation - * - * @return Interpolation - */ - public Object getInterpolation() { - return this.interp; - } - - /** - * Get interpolation string - * - * @return Interpolation string - */ - public String getInterpolationStr() { - if (interp == RenderingHints.VALUE_INTERPOLATION_BILINEAR) { - return "bilinear"; - } else if (interp == RenderingHints.VALUE_INTERPOLATION_BICUBIC) { - return "bicubic"; - } else { - return "nearest"; - } - } - - /** - * Set interpolation object - * - * @param value Interpolation object - */ - public void setInterpolation(Object value) { - this.interp = value; - } - - /** - * Set interpolation string - * - * @param value Interpolation string - */ - public void setInterpolation(String value) { - switch (value) { - case "nearest": - this.interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - break; - case "bilinear": - this.interp = RenderingHints.VALUE_INTERPOLATION_BILINEAR; - break; - case "bicubic": - this.interp = RenderingHints.VALUE_INTERPOLATION_BICUBIC; - break; - } - } - // - // - - /** - * Read image world file - * - * @param aIFile Image world file path - * @throws java.io.FileNotFoundException - */ - public void readImageWorldFile(String aIFile) throws FileNotFoundException, IOException { - BufferedReader sr = new BufferedReader(new FileReader(new File(aIFile))); - - _worldFilePara.xScale = Double.parseDouble(sr.readLine()); - _worldFilePara.yRotate = Double.parseDouble(sr.readLine()); - _worldFilePara.xRotate = Double.parseDouble(sr.readLine()); - _worldFilePara.yScale = Double.parseDouble(sr.readLine()); - _worldFilePara.xUL = Double.parseDouble(sr.readLine()); - _worldFilePara.yUL = Double.parseDouble(sr.readLine()); - sr.close(); - } - - /** - * Write image world file - * - * @param aFile File path - * @param aWFP WorldFilePara - * @throws java.io.IOException - */ - public void writeImageWorldFile(String aFile, WorldFilePara aWFP) throws IOException { - BufferedWriter sw = new BufferedWriter(new FileWriter(new File(aFile))); - sw.write(String.valueOf(aWFP.xScale)); - sw.newLine(); - sw.write(String.valueOf(aWFP.yRotate)); - sw.newLine(); - sw.write(String.valueOf(aWFP.xRotate)); - sw.newLine(); - sw.write(String.valueOf(aWFP.yScale)); - sw.newLine(); - sw.write(String.valueOf(aWFP.xUL)); - sw.newLine(); - sw.write(String.valueOf(aWFP.yUL)); - sw.close(); - } - - /** - * Get colors from palette file - * - * @param pFile Palette file path - * @return Colors - */ - public List getColorsFromPaletteFile(String pFile) { - BufferedReader sr; - try { - sr = new BufferedReader(new InputStreamReader(new FileInputStream(pFile))); - sr.readLine(); - String aLine = sr.readLine(); - String[] dataArray; - List colors = new ArrayList<>(); - while (aLine != null) { - if (aLine.isEmpty()) { - aLine = sr.readLine(); - continue; - } - - aLine = aLine.trim(); - dataArray = aLine.split("\\s+"); - colors.add(new Color(Integer.parseInt(dataArray[3]), Integer.parseInt(dataArray[2]), - Integer.parseInt(dataArray[1]))); - - aLine = sr.readLine(); - } - sr.close(); - - return colors; - } catch (FileNotFoundException ex) { - Logger.getLogger(ImageLayer.class.getName()).log(Level.SEVERE, null, ex); - return null; - } catch (IOException ex) { - Logger.getLogger(ImageLayer.class.getName()).log(Level.SEVERE, null, ex); - return null; - } - } - - /** - * Set palette - * - * @param colors Colors - */ - public void setPalette(List colors) { - Raster imageData = _image.getData(); - - for (int i = 0; i < _image.getWidth(); i++) { - for (int j = 0; j < _image.getHeight(); j++) { - _image.setRGB(i, _image.getHeight() - j - 1, colors.get(imageData.getSample(i, j, 0)).getRGB()); - } - } - } - - /** - * Set color palette to a image from a palette file - * - * @param aFile File path - */ - public void setPalette(String aFile) { - List colors = getColorsFromPaletteFile(aFile); - - setPalette(colors); - } - // - - // - public class ImageLayerBean { - - ImageLayerBean() { - } - - // - /** - * Get layer type - * - * @return Layer type - */ - public LayerTypes getLayerType() { - return ImageLayer.this.getLayerType(); - } - - /** - * Set layer type - * - * @param lt Layer type - */ - public void setLayerType(LayerTypes lt) { - ImageLayer.this.setLayerType(lt); - } - - /** - * Get layer draw type - * - * @return Layer draw type - */ - public LayerDrawType getLayerDrawType() { - return ImageLayer.this.getLayerDrawType(); - } - - /** - * Set layer draw type - * - * @param ldt Layer draw type - */ - public void setLayerDrawType(LayerDrawType ldt) { - ImageLayer.this.setLayerDrawType(ldt); - } - - /** - * Get file name - * - * @return File name - */ - public String getFileName() { - return ImageLayer.this.getFileName(); - } - - /** - * Set file name - * - * @param fn File name - */ - public void setFileName(String fn) { - ImageLayer.this.setFileName(fn); - } - - /** - * Get layer handle - * - * @return Layer handle - */ - public int getHandle() { - return ImageLayer.this.getHandle(); - } - - /** - * Get layer name - * - * @return Layer name - */ - public String getLayerName() { - return ImageLayer.this.getLayerName(); - } - - /** - * Set layer name - * - * @param name Layer name - */ - public void setLayerName(String name) { - ImageLayer.this.setLayerName(name); - } - - /** - * Get if is maskout - * - * @return If is maskout - */ - public boolean isMaskout() { - return ImageLayer.this.isMaskout(); - } - - /** - * Set if maskout - * - * @param value If maskout - */ - public void setMaskout(boolean value) { - ImageLayer.this.setMaskout(value); - } - - /** - * Get if is visible - * - * @return If is visible - */ - public boolean isVisible() { - return ImageLayer.this.isVisible(); - } - - /** - * Set if is visible - * - * @param value If is visible - */ - public void setVisible(boolean value) { - ImageLayer.this.setVisible(value); - } - - /** - * Get world file name of the layer - * - * @return World file name - */ - public String getWorldFileName() { - return _worldFileName; - } - - /** - * Get if set transparency color - * - * @return Boolean - */ - public boolean isUseTransColor() { - return _isSetTransColor; - } - - /** - * Set if using transparency color - * - * @param istrue Boolean - */ - public void setUseTransColor(boolean istrue) { - _isSetTransColor = istrue; - if (istrue) { - Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); - _image = GlobalUtil.imageToBufferedImage(image); - } - } - - /** - * Get transparency color - * - * @return Transparency color - */ - public Color getTransparencyColor() { - return _transparencyColor; - } - - /** - * Set transparency color - * - * @param color The color - */ - public void setTransparencyColor(Color color) { - _transparencyColor = color; - if (_isSetTransColor) { - Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); - _image = GlobalUtil.imageToBufferedImage(image); - } - } - - /** - * Get transparency percent - * - * @return Transparency percent - */ - public int getTransparency() { - return ImageLayer.this.getTransparency(); - } - - /** - * Set transparency percent - * - * @param value Transparency percent - */ - public void setTransparency(int value) { - ImageLayer.this.setTransparency(value); - } - - /** - * Get X upper-left - * - * @return Upper-left x value - */ - public double getXUL() { - return _worldFilePara.xUL; - } - - /** - * Set upper-left x - * - * @param value The value - * @throws java.io.IOException - */ - public void setXUL(double value) throws IOException { - _worldFilePara.xUL = value; - Extent aExtent = (Extent) ImageLayer.this.getExtent().clone(); - aExtent.minX = _worldFilePara.xUL; - aExtent.maxX = _worldFilePara.xUL + ImageLayer.this.getExtent().getWidth(); - ImageLayer.this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y upper-left - * - * @return Upper-left y - */ - public double getYUL() { - return _worldFilePara.yUL; - } - - /** - * Set upper-left y - * - * @param value The value - * @throws java.io.IOException - */ - public void setYUL(double value) throws IOException { - _worldFilePara.yUL = value; - Extent aExtent = (Extent) ImageLayer.this.getExtent().clone(); - aExtent.maxY = _worldFilePara.yUL; - aExtent.minY = _worldFilePara.yUL - ImageLayer.this.getExtent().getHeight(); - ImageLayer.this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get x scale - * - * @return The x scale - */ - public double getXScale() { - return _worldFilePara.xScale; - } - - /** - * Set x scale - * - * @param value The value - * @throws java.io.IOException - */ - public void setXScale(double value) throws IOException { - _worldFilePara.xScale = value; - Extent aExtent = (Extent) ImageLayer.this.getExtent(); - double width = _image.getWidth() * _worldFilePara.xScale; - aExtent.maxX = _worldFilePara.xUL + width; - ImageLayer.this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y scale - * - * @return The y scale - */ - public double getYScale() { - return _worldFilePara.yScale; - } - - public void setYScale(double value) throws IOException { - _worldFilePara.yScale = value; - Extent aExtent = (Extent) ImageLayer.this.getExtent(); - double height = _image.getHeight() * _worldFilePara.yScale; - aExtent.minY = _worldFilePara.yUL + height; - ImageLayer.this.setExtent(aExtent); - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get x rotate(shear) - * - * @return X rotate - */ - public double getXRotate() { - return _worldFilePara.xRotate; - } - - /** - * Set x rotate(shear) - * - * @param value Value - * @throws IOException - */ - public void setXRotate(double value) throws IOException { - _worldFilePara.xRotate = value; - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get y rotate(shear) - * - * @return X rotate - */ - public double getYRotate() { - return _worldFilePara.yRotate; - } - - /** - * Set y rotate(shear) - * - * @param value Value - * @throws IOException - */ - public void setYRotate(double value) throws IOException { - _worldFilePara.yRotate = value; - if (new File(_worldFileName).exists()) { - writeImageWorldFile(_worldFileName, _worldFilePara); - } - } - - /** - * Get interpolation - * - * @return Interpolation - */ - public String getInterpolation() { - if (interp == RenderingHints.VALUE_INTERPOLATION_BILINEAR) { - return "bilinear"; - } else if (interp == RenderingHints.VALUE_INTERPOLATION_BICUBIC) { - return "bicubic"; - } else { - return "nearest"; - } - } - - /** - * Set interpolation - * - * @param value Interpolation - */ - public void setInterpolation(String value) { - switch (value) { - case "nearest": - interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - break; - case "bilinear": - interp = RenderingHints.VALUE_INTERPOLATION_BILINEAR; - break; - case "bicubic": - interp = RenderingHints.VALUE_INTERPOLATION_BICUBIC; - break; - } - } - // - } - - public static class ImageLayerBeanBeanInfo extends BaseBeanInfo { - - public ImageLayerBeanBeanInfo() { - super(ImageLayerBean.class); - addProperty("fileName").setCategory("Read only").setReadOnly().setDisplayName("File name"); - addProperty("layerType").setCategory("Read only").setReadOnly().setDisplayName("Layer type"); - addProperty("layerDrawType").setCategory("Read only").setReadOnly().setDisplayName("Layer draw type"); - addProperty("handle").setCategory("Read only").setReadOnly().setDisplayName("Handle"); - addProperty("layerName").setCategory("Editable").setDisplayName("Layer name"); - addProperty("visible").setCategory("Editable").setDisplayName("Visible"); - addProperty("maskout").setCategory("Editable").setDisplayName("Is maskout"); - addProperty("transparency").setCategory("Editable").setDisplayName("Transparency Percent"); - addProperty("useTransColor").setCategory("Editable").setDisplayName("If use transparency color"); - addProperty("transparencyColor").setCategory("Editable").setDisplayName("Transparency color"); - addProperty("xScale").setCategory("Editable").setDisplayName("X scale"); - addProperty("yScale").setCategory("Editable").setDisplayName("Y scale"); - addProperty("xUL").setCategory("Editable").setDisplayName("X upper left"); - addProperty("yUL").setCategory("Editable").setDisplayName("Y upper left"); - addProperty("xRotate").setCategory("Editable").setDisplayName("X rotate"); - addProperty("yRotate").setCategory("Editable").setDisplayName("Y rotate"); - ExtendedPropertyDescriptor e = addProperty("interpolation"); - e.setCategory("Editable").setPropertyEditorClass(InterpolationEditor.class); - e.setDisplayName("Interpolation"); - } - } - - public static class InterpolationEditor extends ComboBoxPropertyEditor { - - public InterpolationEditor() { - super(); - String[] names = new String[3]; - names[0] = "nearest"; - names[1] = "bilinear"; - names[2] = "bicubic"; - setAvailableValues(names); - } - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layer; + +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.shape.ShapeTypes; +import java.awt.Color; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Yaqiang Wang + */ +public class ImageLayer extends MapLayer { + // + + private BufferedImage _image; + private WorldFilePara _worldFilePara = new WorldFilePara(); + private String _worldFileName; + private boolean _isSetTransColor; + private Color _transparencyColor; + protected Object interp; + // + // + + /** + * Constructor + */ + public ImageLayer() { + super(); + this.setLayerType(LayerTypes.ImageLayer); + this.setShapeType(ShapeTypes.Image); + _isSetTransColor = false; + _transparencyColor = Color.black; + this.interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; + } + // + // + + /** + * Get image + * + * @return The image + */ + public BufferedImage getImage() { + return _image; + } + + /** + * Set image + * + * @param image The image + */ + public void setImage(BufferedImage image) { + _image = image; + _transparencyColor = new Color(image.getRGB(1, 1)); + } + + /** + * Get world file name of the layer + * + * @return World file name + */ + public String getWorldFileName() { + return _worldFileName; + } + + /** + * Set world file name + * + * @param name World file name + */ + public void setWorldFileName(String name) { + _worldFileName = name; + } + + /** + * Get world file parameters + * + * @return World file parameters + */ + public WorldFilePara getWorldFilePara() { + return _worldFilePara; + } + + /** + * Set world file parameters + * + * @param value World file parameters + */ + public void setWorldFilePara(WorldFilePara value) { + _worldFilePara = value; + } + + /** + * Get if set transparency color + * + * @return Boolean + */ + public boolean isUseTransColor() { + return _isSetTransColor; + } + + /** + * Set if using transparency color + * + * @param istrue Boolean + */ + public void setUseTransColor(boolean istrue) { + _isSetTransColor = istrue; + if (istrue) { + Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); + _image = GlobalUtil.imageToBufferedImage(image); + } + } + + /** + * Get transparency color + * + * @return Transparency color + */ + public Color getTransparencyColor() { + return _transparencyColor; + } + + /** + * Set transparency color + * + * @param color The color + */ + public void setTransparencyColor(Color color) { + _transparencyColor = color; + if (_isSetTransColor) { + Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); + _image = GlobalUtil.imageToBufferedImage(image); + } + } + + /** + * Get X upper-left + * + * @return Upper-left x value + */ + public double getXUL() { + return _worldFilePara.xUL; + } + + /** + * Set upper-left x + * + * @param value The value + * @throws java.io.IOException + */ + public void setXUL(double value) throws IOException { + _worldFilePara.xUL = value; + Extent aExtent = (Extent) this.getExtent().clone(); + aExtent.minX = _worldFilePara.xUL; + aExtent.maxX = _worldFilePara.xUL + this.getExtent().getWidth(); + this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y upper-left + * + * @return Upper-left y + */ + public double getYUL() { + return _worldFilePara.yUL; + } + + /** + * Set upper-left y + * + * @param value The value + * @throws java.io.IOException + */ + public void setYUL(double value) throws IOException { + _worldFilePara.yUL = value; + Extent aExtent = (Extent) this.getExtent().clone(); + aExtent.maxY = _worldFilePara.yUL; + aExtent.minY = _worldFilePara.yUL - this.getExtent().getHeight(); + this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get x scale + * + * @return The x scale + */ + public double getXScale() { + return _worldFilePara.xScale; + } + + /** + * Set x scale + * + * @param value The value + * @throws java.io.IOException + */ + public void setXScale(double value) throws IOException { + _worldFilePara.xScale = value; + Extent aExtent = (Extent) this.getExtent(); + double width = _image.getWidth() * _worldFilePara.xScale; + aExtent.maxX = _worldFilePara.xUL + width; + this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y scale + * + * @return The y scale + */ + public double getYScale() { + return _worldFilePara.yScale; + } + + /** + * Set y scale + * + * @param value The y scale value + * @throws IOException + */ + public void setYScale(double value) throws IOException { + _worldFilePara.yScale = value; + Extent aExtent = (Extent) this.getExtent(); + double height = _image.getHeight() * _worldFilePara.yScale; + aExtent.minY = _worldFilePara.yUL + height; + this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get x rotate(shear) + * + * @return X rotate + */ + public double getXRotate() { + return _worldFilePara.xRotate; + } + + /** + * Set x rotate(shear) + * + * @param value Value + * @throws IOException + */ + public void setXRotate(double value) throws IOException { + _worldFilePara.xRotate = value; + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y rotate(shear) + * + * @return X rotate + */ + public double getYRotate() { + return _worldFilePara.yRotate; + } + + /** + * Set y rotate(shear) + * + * @param value Value + * @throws IOException + */ + public void setYRotate(double value) throws IOException { + _worldFilePara.yRotate = value; + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get interpolation + * + * @return Interpolation + */ + public Object getInterpolation() { + return this.interp; + } + + /** + * Get interpolation string + * + * @return Interpolation string + */ + public String getInterpolationStr() { + if (interp == RenderingHints.VALUE_INTERPOLATION_BILINEAR) { + return "bilinear"; + } else if (interp == RenderingHints.VALUE_INTERPOLATION_BICUBIC) { + return "bicubic"; + } else { + return "nearest"; + } + } + + /** + * Set interpolation object + * + * @param value Interpolation object + */ + public void setInterpolation(Object value) { + this.interp = value; + } + + /** + * Set interpolation string + * + * @param value Interpolation string + */ + public void setInterpolation(String value) { + switch (value) { + case "nearest": + this.interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; + break; + case "bilinear": + this.interp = RenderingHints.VALUE_INTERPOLATION_BILINEAR; + break; + case "bicubic": + this.interp = RenderingHints.VALUE_INTERPOLATION_BICUBIC; + break; + } + } + // + // + + /** + * Read image world file + * + * @param aIFile Image world file path + * @throws java.io.FileNotFoundException + */ + public void readImageWorldFile(String aIFile) throws FileNotFoundException, IOException { + BufferedReader sr = new BufferedReader(new FileReader(new File(aIFile))); + + _worldFilePara.xScale = Double.parseDouble(sr.readLine()); + _worldFilePara.yRotate = Double.parseDouble(sr.readLine()); + _worldFilePara.xRotate = Double.parseDouble(sr.readLine()); + _worldFilePara.yScale = Double.parseDouble(sr.readLine()); + _worldFilePara.xUL = Double.parseDouble(sr.readLine()); + _worldFilePara.yUL = Double.parseDouble(sr.readLine()); + sr.close(); + } + + /** + * Write image world file + * + * @param aFile File path + * @param aWFP WorldFilePara + * @throws java.io.IOException + */ + public void writeImageWorldFile(String aFile, WorldFilePara aWFP) throws IOException { + BufferedWriter sw = new BufferedWriter(new FileWriter(new File(aFile))); + sw.write(String.valueOf(aWFP.xScale)); + sw.newLine(); + sw.write(String.valueOf(aWFP.yRotate)); + sw.newLine(); + sw.write(String.valueOf(aWFP.xRotate)); + sw.newLine(); + sw.write(String.valueOf(aWFP.yScale)); + sw.newLine(); + sw.write(String.valueOf(aWFP.xUL)); + sw.newLine(); + sw.write(String.valueOf(aWFP.yUL)); + sw.close(); + } + + /** + * Get colors from palette file + * + * @param pFile Palette file path + * @return Colors + */ + public List getColorsFromPaletteFile(String pFile) { + BufferedReader sr; + try { + sr = new BufferedReader(new InputStreamReader(new FileInputStream(pFile))); + sr.readLine(); + String aLine = sr.readLine(); + String[] dataArray; + List colors = new ArrayList<>(); + while (aLine != null) { + if (aLine.isEmpty()) { + aLine = sr.readLine(); + continue; + } + + aLine = aLine.trim(); + dataArray = aLine.split("\\s+"); + colors.add(new Color(Integer.parseInt(dataArray[3]), Integer.parseInt(dataArray[2]), + Integer.parseInt(dataArray[1]))); + + aLine = sr.readLine(); + } + sr.close(); + + return colors; + } catch (FileNotFoundException ex) { + Logger.getLogger(ImageLayer.class.getName()).log(Level.SEVERE, null, ex); + return null; + } catch (IOException ex) { + Logger.getLogger(ImageLayer.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } + + /** + * Set palette + * + * @param colors Colors + */ + public void setPalette(List colors) { + Raster imageData = _image.getData(); + + for (int i = 0; i < _image.getWidth(); i++) { + for (int j = 0; j < _image.getHeight(); j++) { + _image.setRGB(i, _image.getHeight() - j - 1, colors.get(imageData.getSample(i, j, 0)).getRGB()); + } + } + } + + /** + * Set color palette to a image from a palette file + * + * @param aFile File path + */ + public void setPalette(String aFile) { + List colors = getColorsFromPaletteFile(aFile); + + setPalette(colors); + } + // + + // + public class ImageLayerBean { + + ImageLayerBean() { + } + + // + /** + * Get layer type + * + * @return Layer type + */ + public LayerTypes getLayerType() { + return ImageLayer.this.getLayerType(); + } + + /** + * Set layer type + * + * @param lt Layer type + */ + public void setLayerType(LayerTypes lt) { + ImageLayer.this.setLayerType(lt); + } + + /** + * Get layer draw type + * + * @return Layer draw type + */ + public LayerDrawType getLayerDrawType() { + return ImageLayer.this.getLayerDrawType(); + } + + /** + * Set layer draw type + * + * @param ldt Layer draw type + */ + public void setLayerDrawType(LayerDrawType ldt) { + ImageLayer.this.setLayerDrawType(ldt); + } + + /** + * Get file name + * + * @return File name + */ + public String getFileName() { + return ImageLayer.this.getFileName(); + } + + /** + * Set file name + * + * @param fn File name + */ + public void setFileName(String fn) { + ImageLayer.this.setFileName(fn); + } + + /** + * Get layer handle + * + * @return Layer handle + */ + public int getHandle() { + return ImageLayer.this.getHandle(); + } + + /** + * Get layer name + * + * @return Layer name + */ + public String getLayerName() { + return ImageLayer.this.getLayerName(); + } + + /** + * Set layer name + * + * @param name Layer name + */ + public void setLayerName(String name) { + ImageLayer.this.setLayerName(name); + } + + /** + * Get if is maskout + * + * @return If is maskout + */ + public boolean isMaskout() { + return ImageLayer.this.isMaskout(); + } + + /** + * Set if maskout + * + * @param value If maskout + */ + public void setMaskout(boolean value) { + ImageLayer.this.setMaskout(value); + } + + /** + * Get if is visible + * + * @return If is visible + */ + public boolean isVisible() { + return ImageLayer.this.isVisible(); + } + + /** + * Set if is visible + * + * @param value If is visible + */ + public void setVisible(boolean value) { + ImageLayer.this.setVisible(value); + } + + /** + * Get world file name of the layer + * + * @return World file name + */ + public String getWorldFileName() { + return _worldFileName; + } + + /** + * Get if set transparency color + * + * @return Boolean + */ + public boolean isUseTransColor() { + return _isSetTransColor; + } + + /** + * Set if using transparency color + * + * @param istrue Boolean + */ + public void setUseTransColor(boolean istrue) { + _isSetTransColor = istrue; + if (istrue) { + Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); + _image = GlobalUtil.imageToBufferedImage(image); + } + } + + /** + * Get transparency color + * + * @return Transparency color + */ + public Color getTransparencyColor() { + return _transparencyColor; + } + + /** + * Set transparency color + * + * @param color The color + */ + public void setTransparencyColor(Color color) { + _transparencyColor = color; + if (_isSetTransColor) { + Image image = GlobalUtil.makeColorTransparent(_image, _transparencyColor); + _image = GlobalUtil.imageToBufferedImage(image); + } + } + + /** + * Get transparency percent + * + * @return Transparency percent + */ + public int getTransparency() { + return ImageLayer.this.getTransparency(); + } + + /** + * Set transparency percent + * + * @param value Transparency percent + */ + public void setTransparency(int value) { + ImageLayer.this.setTransparency(value); + } + + /** + * Get X upper-left + * + * @return Upper-left x value + */ + public double getXUL() { + return _worldFilePara.xUL; + } + + /** + * Set upper-left x + * + * @param value The value + * @throws java.io.IOException + */ + public void setXUL(double value) throws IOException { + _worldFilePara.xUL = value; + Extent aExtent = (Extent) ImageLayer.this.getExtent().clone(); + aExtent.minX = _worldFilePara.xUL; + aExtent.maxX = _worldFilePara.xUL + ImageLayer.this.getExtent().getWidth(); + ImageLayer.this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y upper-left + * + * @return Upper-left y + */ + public double getYUL() { + return _worldFilePara.yUL; + } + + /** + * Set upper-left y + * + * @param value The value + * @throws java.io.IOException + */ + public void setYUL(double value) throws IOException { + _worldFilePara.yUL = value; + Extent aExtent = (Extent) ImageLayer.this.getExtent().clone(); + aExtent.maxY = _worldFilePara.yUL; + aExtent.minY = _worldFilePara.yUL - ImageLayer.this.getExtent().getHeight(); + ImageLayer.this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get x scale + * + * @return The x scale + */ + public double getXScale() { + return _worldFilePara.xScale; + } + + /** + * Set x scale + * + * @param value The value + * @throws java.io.IOException + */ + public void setXScale(double value) throws IOException { + _worldFilePara.xScale = value; + Extent aExtent = (Extent) ImageLayer.this.getExtent(); + double width = _image.getWidth() * _worldFilePara.xScale; + aExtent.maxX = _worldFilePara.xUL + width; + ImageLayer.this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y scale + * + * @return The y scale + */ + public double getYScale() { + return _worldFilePara.yScale; + } + + public void setYScale(double value) throws IOException { + _worldFilePara.yScale = value; + Extent aExtent = (Extent) ImageLayer.this.getExtent(); + double height = _image.getHeight() * _worldFilePara.yScale; + aExtent.minY = _worldFilePara.yUL + height; + ImageLayer.this.setExtent(aExtent); + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get x rotate(shear) + * + * @return X rotate + */ + public double getXRotate() { + return _worldFilePara.xRotate; + } + + /** + * Set x rotate(shear) + * + * @param value Value + * @throws IOException + */ + public void setXRotate(double value) throws IOException { + _worldFilePara.xRotate = value; + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get y rotate(shear) + * + * @return X rotate + */ + public double getYRotate() { + return _worldFilePara.yRotate; + } + + /** + * Set y rotate(shear) + * + * @param value Value + * @throws IOException + */ + public void setYRotate(double value) throws IOException { + _worldFilePara.yRotate = value; + if (new File(_worldFileName).exists()) { + writeImageWorldFile(_worldFileName, _worldFilePara); + } + } + + /** + * Get interpolation + * + * @return Interpolation + */ + public String getInterpolation() { + if (interp == RenderingHints.VALUE_INTERPOLATION_BILINEAR) { + return "bilinear"; + } else if (interp == RenderingHints.VALUE_INTERPOLATION_BICUBIC) { + return "bicubic"; + } else { + return "nearest"; + } + } + + /** + * Set interpolation + * + * @param value Interpolation + */ + public void setInterpolation(String value) { + switch (value) { + case "nearest": + interp = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; + break; + case "bilinear": + interp = RenderingHints.VALUE_INTERPOLATION_BILINEAR; + break; + case "bicubic": + interp = RenderingHints.VALUE_INTERPOLATION_BICUBIC; + break; + } + } + // + } + + public static class ImageLayerBeanBeanInfo extends BaseBeanInfo { + + public ImageLayerBeanBeanInfo() { + super(ImageLayerBean.class); + addProperty("fileName").setCategory("Read only").setReadOnly().setDisplayName("File name"); + addProperty("layerType").setCategory("Read only").setReadOnly().setDisplayName("Layer type"); + addProperty("layerDrawType").setCategory("Read only").setReadOnly().setDisplayName("Layer draw type"); + addProperty("handle").setCategory("Read only").setReadOnly().setDisplayName("Handle"); + addProperty("layerName").setCategory("Editable").setDisplayName("Layer name"); + addProperty("visible").setCategory("Editable").setDisplayName("Visible"); + addProperty("maskout").setCategory("Editable").setDisplayName("Is maskout"); + addProperty("transparency").setCategory("Editable").setDisplayName("Transparency Percent"); + addProperty("useTransColor").setCategory("Editable").setDisplayName("If use transparency color"); + addProperty("transparencyColor").setCategory("Editable").setDisplayName("Transparency color"); + addProperty("xScale").setCategory("Editable").setDisplayName("X scale"); + addProperty("yScale").setCategory("Editable").setDisplayName("Y scale"); + addProperty("xUL").setCategory("Editable").setDisplayName("X upper left"); + addProperty("yUL").setCategory("Editable").setDisplayName("Y upper left"); + addProperty("xRotate").setCategory("Editable").setDisplayName("X rotate"); + addProperty("yRotate").setCategory("Editable").setDisplayName("Y rotate"); + ExtendedPropertyDescriptor e = addProperty("interpolation"); + e.setCategory("Editable").setPropertyEditorClass(InterpolationEditor.class); + e.setDisplayName("Interpolation"); + } + } + + public static class InterpolationEditor extends ComboBoxPropertyEditor { + + public InterpolationEditor() { + super(); + String[] names = new String[3]; + names[0] = "nearest"; + names[1] = "bilinear"; + names[2] = "bicubic"; + setAvailableValues(names); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/LabelSet.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/LabelSet.java index 5963662d..866283a1 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/LabelSet.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/LabelSet.java @@ -13,12 +13,12 @@ */ package org.meteoinfo.layer; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.legend.AlignType; import java.awt.Color; import java.awt.Font; -import org.meteoinfo.global.util.GlobalUtil; -/** + /** * Template * * @author Yaqiang Wang diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/MapLayer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/MapLayer.java index 3b6834c4..ba18247a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/MapLayer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/MapLayer.java @@ -13,7 +13,7 @@ */ package org.meteoinfo.layer; -import org.meteoinfo.global.Extent; +import org.meteoinfo.common.Extent; import org.meteoinfo.legend.LegendScheme; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.info.ProjectionInfo; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/RasterLayer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/RasterLayer.java index b1c7bcf0..73285c49 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/RasterLayer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/RasterLayer.java @@ -15,8 +15,10 @@ package org.meteoinfo.layer; import com.l2fprod.common.beans.BaseBeanInfo; import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.legend.LegendScheme; import org.meteoinfo.shape.ShapeTypes; import java.awt.Color; @@ -31,8 +33,6 @@ import javax.swing.JFileChooser; import javax.swing.JOptionPane; import org.meteoinfo.data.GridArray; import org.meteoinfo.data.mapdata.MapDataManage; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.ndarray.Index; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/VectorLayer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/VectorLayer.java index 88404c3c..5ce2f17f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/VectorLayer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/VectorLayer.java @@ -13,14 +13,14 @@ */ package org.meteoinfo.layer; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.data.mapdata.AttributeTable; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.data.mapdata.ShapeFileManage; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.global.colors.ColorUtil; import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.table.DataColumn; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/WebMapLayer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/WebMapLayer.java index 07ccbccf..4f3918e8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layer/WebMapLayer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layer/WebMapLayer.java @@ -1,922 +1,919 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.layer; - -//import com.sun.java.swing.Painter; -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.geom.Point2D; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import javax.imageio.ImageIO; - -import org.meteoinfo.data.mapdata.webmap.*; -import org.meteoinfo.data.mapdata.webmap.empty.EmptyTileFactory; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.util.GeoUtil; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.Reproject; -import org.meteoinfo.shape.ShapeTypes; - -/** - * - * @author wyq - */ -public class WebMapLayer extends MapLayer { - // - - private final boolean isNegativeYAllowed = true; //maybe rename to isNorthBounded and isSouthBounded? - /** - * The zoom level. Generally a value between 1 and 15 (TODO Is this true for - * all the mapping worlds? What does this mean if some mapping system - * doesn't support the zoom level? - */ - private int zoom = 11; - /** - * The position, in map coordinates of the center point. This is - * defined as the distance from the top and left edges of the map in pixels. - * Dragging the map component will change the center position. Zooming - * in/out will cause the center to be recalculated so as to remain in the - * center of the new "map". - */ - private Point2D center = new Point2D.Double(0, 0); - /** - * Indicates whether or not to draw the borders between tiles. Defaults to - * false. - * - * TODO Generally not very nice looking, very much a product of testing - * Consider whether this should really be a property or not. - */ - private boolean drawTileBorders = false; - /** - * Factory used by this component to grab the tiles necessary for painting - * the map. - */ - private TileFactory factory; - /** - * The position in latitude/longitude of the "address" being mapped. This is - * a special coordinate that, when moved, will cause the map to be moved as - * well. It is separate from "center" in that "center" tracks the current - * center (in pixels) of the viewport whereas this will not change when - * panning or zooming. Whenever the addressLocation is changed, however, the - * map will be repositioned. - */ - private GeoPosition addressLocation; - /** - * Specifies whether panning is enabled. Panning is being able to click and - * drag the map around to cause it to move - */ - private boolean panEnabled = true; - /** - * Specifies whether zooming is enabled (the mouse wheel, for example, - * zooms) - */ - private boolean zoomEnabled = true; - /** - * Indicates whether the component should recenter the map when the "middle" - * mouse button is pressed - */ - private boolean recenterOnClickEnabled = true; - /** - * The overlay to delegate to for painting the "foreground" of the map - * component. This would include painting waypoints, day/night, etc. Also - * receives mouse events. - */ - //private Painter overlay; - private boolean designTime; - private double webMapScale = 0.; - private Image loadingImage; - private boolean restrictOutsidePanning = false; - private boolean horizontalWrapped = true; - private WebMapProvider defaultProvider = WebMapProvider.OpenStreetMap; - private Graphics2D graphics; - private int width; - private int height; - private List scales = new ArrayList<>(); - // - // - // a property change listener which forces repaints when tiles finish loading - //private TileLoadListener tileLoadListener = new TileLoadListener(); - -// private final class TileLoadListener implements PropertyChangeListener { -// -// @Override -// public void propertyChange(PropertyChangeEvent evt) { -// if ("loaded".equals(evt.getPropertyName()) -// && Boolean.TRUE.equals(evt.getNewValue())) { -// Tile t = (Tile) evt.getSource(); -// if (t.getZoom() == getZoom()) { -// repaint(); -// /* this optimization doesn't save much and it doesn't work if you -// * wrap around the world -// Rectangle viewportBounds = getViewportBounds(); -// TilePoint tilePoint = t.getLocation(); -// Point point = new Point(tilePoint.getX() * getTileFactory().getTileSize(), tilePoint.getY() * getTileFactory().getTileSize()); -// Rectangle tileRect = new Rectangle(point, new Dimension(getTileFactory().getTileSize(), getTileFactory().getTileSize())); -// if (viewportBounds.intersects(tileRect)) { -// //convert tileRect from world space to viewport space -// repaint(new Rectangle( -// tileRect.x - viewportBounds.x, -// tileRect.y - viewportBounds.y, -// tileRect.width, -// tileRect.height -// )); -// }*/ -// } -// } -// } -// } - // - // - - /** - * Constructor - */ - public WebMapLayer() { - super(); - this.setLayerType(LayerTypes.WebMapLayer); - this.setShapeType(ShapeTypes.Image); - this.setLayerDrawType(LayerDrawType.Image); - this.setLayerName("OpenStreetMap"); - this.setExtent(new Extent(-2.0037508342789244E7, 2.0037508342789244E7, -1.8375854901481014E7, 1.8375854901481014E7)); - factory = new EmptyTileFactory(); - - // make a dummy loading image - try { - URL url = this.getClass().getResource("/images/loading.png"); - this.setLoadingImage(ImageIO.read(url)); - } catch (Throwable ex) { - System.out.println("could not load 'loading.png'"); - BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = img.createGraphics(); - g2.setColor(Color.black); - g2.fillRect(0, 0, 16, 16); - g2.dispose(); - this.setLoadingImage(img); - } - } - // - // - - /** - * Gets the current zoom level - * - * @return the current zoom level - */ - public int getZoom() { - return this.zoom; - } - - /** - * Set the current zoom level - * - * @param zoom the new zoom level - */ - public void setZoom(int zoom) { - if (zoom == this.zoom) { - return; - } - - TileFactoryInfo info = getTileFactory().getInfo(); - // don't repaint if we are out of the valid zoom levels - if (info != null - && (zoom < info.getMinimumZoomLevel() - || zoom > info.getMaximumZoomLevel())) { - return; - } - - //if(zoom >= 0 && zoom <= 15 && zoom != this.zoom) { - int oldzoom = this.zoom; - Point2D oldCenter = getCenter(); - Dimension oldMapSize = getTileFactory().getMapSize(oldzoom); - this.zoom = zoom; - //this.firePropertyChange("zoom", oldzoom, zoom); - - Dimension mapSize = getTileFactory().getMapSize(zoom); - - setCenter(new Point2D.Double( - oldCenter.getX() * (mapSize.getWidth() / oldMapSize.getWidth()), - oldCenter.getY() * (mapSize.getHeight() / oldMapSize.getHeight()))); - - //repaint(); - } - - /** - * Gets the current pixel center of the map. This point is in the global - * bitmap coordinate system, not as lat/longs. - * - * @return the current center of the map as a pixel value - */ - public Point2D getCenter() { - return center; - } - - public boolean isRestrictOutsidePanning() { - return restrictOutsidePanning; - } - - public void setRestrictOutsidePanning(boolean restrictOutsidePanning) { - this.restrictOutsidePanning = restrictOutsidePanning; - } - - /** - * Sets the new center of the map in pixel coordinates. - * - * @param center the new center of the map in pixel coordinates - */ - public void setCenter(Point2D center) { - this.center = center; -// if(isRestrictOutsidePanning()) { -// Insets insets = getInsets(); -// int viewportHeight = getHeight() - insets.top - insets.bottom; -// int viewportWidth = getWidth() - insets.left - insets.right; -// -// // don't let the user pan over the top edge -// Rectangle newVP = calculateViewportBounds(center); -// if(newVP.getY() < 0) { -// double centerY = viewportHeight/2; -// center = new Point2D.Double(center.getX(),centerY); -// } -// -// // don't let the user pan over the left edge -// if(!isHorizontalWrapped() && newVP.getX() <0) { -// double centerX = viewportWidth/2; -// center = new Point2D.Double(centerX, center.getY()); -// } -// -// // don't let the user pan over the bottom edge -// Dimension mapSize = getTileFactory().getMapSize(getZoom()); -// int mapHeight = (int)mapSize.getHeight()*getTileFactory().getTileSize(getZoom()); -// if(newVP.getY() + newVP.getHeight() > mapHeight) { -// double centerY = mapHeight - viewportHeight/2; -// center = new Point2D.Double(center.getX(),centerY); -// } -// -// //don't let the user pan over the right edge -// int mapWidth = (int)mapSize.getWidth()*getTileFactory().getTileSize(getZoom()); -// if(!isHorizontalWrapped() && (newVP.getX() + newVP.getWidth() > mapWidth)) { -// double centerX = mapWidth - viewportWidth/2; -// center = new Point2D.Double(centerX, center.getY()); -// } -// -// // if map is to small then just center it vert -// if(mapHeight < newVP.getHeight()) { -// double centerY = mapHeight/2;//viewportHeight/2;// - mapHeight/2; -// center = new Point2D.Double(center.getX(),centerY); -// } -// -// // if map is too small then just center it horiz -// if(!isHorizontalWrapped() && mapWidth < newVP.getWidth()) { -// double centerX = mapWidth/2; -// center = new Point2D.Double(centerX, center.getY()); -// } -// } -// -// //joshy: this is an evil hack to force a property change event -// //i don't know why it doesn't work normally -// old = new Point(5,6); -// -// GeoPosition oldGP = this.getCenterPosition(); - } - - /** - * A property indicating the center position of the map - * - * @param geoPosition the new property value - */ - public void setCenterPosition(GeoPosition geoPosition) { - GeoPosition oldVal = getCenterPosition(); - setCenter(getTileFactory().geoToPixel(geoPosition, zoom)); - //repaint(); - GeoPosition newVal = getCenterPosition(); - //firePropertyChange("centerPosition", oldVal, newVal); - } - - /** - * A property indicating the center position of the map - * - * @return the current center position - */ - public GeoPosition getCenterPosition() { - return getTileFactory().pixelToGeo(getCenter(), zoom); - } - - /** - * Get the current factory - * - * @return the current property value - */ - public TileFactory getTileFactory() { - return factory; - } - - /** - * Set the current tile factory - * - * @param factory the new property value - */ - public void setTileFactory(TileFactory factory) { - this.factory = factory; - this.setZoom(factory.getInfo().getDefaultZoomLevel()); - this.setCenterPosition(new GeoPosition(0, 0)); - } - - /** - * Get web map scale - * @return Web map scale - */ - public double getWebMapScale() { - return this.webMapScale; - } - - /** - * Set web map scale - * @param value Web map scale - */ - public void setWebMapScale(double value) { - this.webMapScale = value; - } - - /** - * A property for an image which will be display when an image is still - * loading. - * - * @return the current property value - */ - public Image getLoadingImage() { - return loadingImage; - } - - /** - * A property for an image which will be display when an image is still - * loading. - * - * @param loadingImage the new property value - */ - public void setLoadingImage(Image loadingImage) { - this.loadingImage = loadingImage; - } - - /** - * Indicates if the tile borders should be drawn. Mainly used for debugging. - * - * @return the value of this property - */ - public boolean isDrawTileBorders() { - return drawTileBorders; - } - - /** - * Set if the tile borders should be drawn. Mainly used for debugging. - * - * @param drawTileBorders new value of this drawTileBorders - */ - public void setDrawTileBorders(boolean drawTileBorders) { - //boolean old = isDrawTileBorders(); - this.drawTileBorders = drawTileBorders; - //firePropertyChange("drawTileBorders", old, isDrawTileBorders()); - //repaint(); - } - - /** - * Set web map provider - * @param prov The web map provider - */ - public void setWebMapProvider(WebMapProvider prov) { - TileFactoryInfo info = null; - switch (prov) { -// case SwingLabsBlueMarble: -// setTileFactory(new CylindricalProjectionTileFactory()); -// setZoom(3); -// return; - case OpenStreetMap: - info = new OpenStreetMapInfo(); - break; - case OpenStreetMapQuestSatellite: - info = new OpenStreetMapQuestSatelliteInfo(); - break; - case BingMap: - info = new BingMapInfo(); - break; - case BingSatelliteMap: - info = new BingSatelliteMapInfo(); - break; - case BingHybridMap: - info = new BingHybridMapInfo(); - break; -// case OviMap: -// info = new OviMapInfo(); -// break; -// case OviSatelliteMap: -// info = new OviSatelliteMapInfo(); -// break; -// case OviTerrainMap: -// info = new OviTerrainMapInfo(); -// break; -// case OviHybridMap: -// info = new OviHybridMapInfo(); -// break; - case YahooMap: - info = new YahooMapInfo(); - break; - case YahooSatelliteMap: - info = new YahooSatelliteMapInfo(); - break; - case YahooHybridMap: - info = new YahooHybridMapInfo(); - break; - case GoogleMap: - info = new GoogleMapInfo(); - break; - case GoogleSatelliteMap: - info = new GoogleSatelliteMapInfo(); - break; - case GoogleTerrainMap: - info = new GoogleTerrainMapInfo(); - break; - case GoogleHybridMap: - info = new GoogleHybridMapInfo(); - break; - case GoogleHybridTerrainMap: - info = new GoogleHybridTerrainMapInfo(); - break; -// case BaiduMap: -// info = new BaiduMapInfo(); -// break; -// case BaiduSatelliteMap: -// info = new BaiduSatelliteMapInfo(); -// break; - case AMap: - info = new AMapInfo(); - break; - case ASatelliteMap: - info = new ASatelliteMapInfo(); - break; - case AHybridMap: - info = new AHybridMapInfo(); - break; - case TencentMap: - info = new TencentMapInfo(); - break; - case CMA_CVA_MAP: - info = new CMACvaMapInfo(); - break; - case CMA_VEC_MAP: - info = new CMAVecMapInfo(); - break; - case CMA_IMG_MAP: - info = new CMAImgMapInfo(); - break; -// case ArcGISImage: -// info = new ArcGISImageInfo(); -// break; - } - - if (info != null) { - this.defaultProvider = prov; - this.setLayerName("WebMap_" + info.getName()); - TileFactory tf = new DefaultTileFactory(info); - setTileFactory(tf); - //setZoom(11); - setAddressLocation(new GeoPosition(51.5, 0)); - } - } - - /** - * Get web map provider - * @return Web map provider - */ - public WebMapProvider getWebMapProvider() { - return this.defaultProvider; - } - - public GeoPosition getAddressLocation() { - return this.addressLocation; - } - - public void setAddressLocation(GeoPosition pos, int zoom) { - this.addressLocation = pos; - setCenter(getTileFactory().geoToPixel(pos, zoom)); - } - - public void setAddressLocation(GeoPosition pos) { - this.addressLocation = pos; - setCenter(getTileFactory().geoToPixel(addressLocation, getZoom())); - } - // - // - - /** - * Repaint - */ - public void repaint() { - Rectangle rect = this.calculateViewportBounds(graphics, width, height); - this.drawMapTiles(graphics, zoom, rect); - } - - /** - * Draw the map tiles - * - * @param g Graphics2D - * @param zoom Zoom level to draw at - * @param width The width - * @param height The height - */ - public void drawMapTiles(final Graphics2D g, final int zoom, int width, int height) { - this.graphics = g; - this.zoom = zoom; - this.width = width; - this.height = height; - Rectangle rect = this.calculateViewportBounds(g, width, height); - this.drawMapTiles(g, zoom, rect); - } - - /** - * Draw the map tiles. This method is for implementation use only. - * - * @param g Graphics - * @param zoom zoom level to draw at - * @param viewportBounds View bounds - */ - public void drawMapTiles(final Graphics2D g, final int zoom, final Rectangle viewportBounds) { - int size = getTileFactory().getTileSize(zoom); - Dimension mapSize = getTileFactory().getMapSize(zoom); - - //calculate the "visible" viewport area in tiles - int numWide = viewportBounds.width / size + 2; - int numHigh = viewportBounds.height / size + 2; - - //TilePoint topLeftTile = getTileFactory().getTileCoordinate( - // new Point2D.Double(viewportBounds.x, viewportBounds.y)); - TileFactoryInfo info = getTileFactory().getInfo(); - int tpx = (int) Math.floor(viewportBounds.getX() / info.getTileSize(0)); - int tpy = (int) Math.floor(viewportBounds.getY() / info.getTileSize(0)); - //TilePoint topLeftTile = new TilePoint(tpx, tpy); - - //p("top tile = " + topLeftTile); - //fetch the tiles from the factory and store them in the tiles cache - //attach the tileLoadListener - for (int x = 0; x <= numWide; x++) { - for (int y = 0; y <= numHigh; y++) { - int itpx = x + tpx;//topLeftTile.getX(); - int itpy = y + tpy;//topLeftTile.getY(); - //TilePoint point = new TilePoint(x + topLeftTile.getX(), y + topLeftTile.getY()); - //only proceed if the specified tile point lies within the area being painted - //if (g.getClipBounds().intersects(new Rectangle(itpx * size - viewportBounds.x, - //itpy * size - viewportBounds.y, size, size))) { - Tile tile = getTileFactory().getTile(itpx, itpy, zoom); - //tile.addUniquePropertyChangeListener("loaded", tileLoadListener); //this is a filthy hack - int ox = ((itpx * getTileFactory().getTileSize(zoom)) - viewportBounds.x); - int oy = ((itpy * getTileFactory().getTileSize(zoom)) - viewportBounds.y); - - //if the tile is off the map to the north/south, then just don't paint anything - if (isTileOnMap(itpx, itpy, mapSize)) { -// if (isOpaque()) { -// g.setColor(getBackground()); -// g.fillRect(ox,oy,size,size); -// } - } else if (tile.isLoaded()) { - g.drawImage(tile.getImage(), ox, oy, null); - } -// else { -// int imageX = (getTileFactory().getTileSize(zoom) - getLoadingImage().getWidth(null)) / 2; -// int imageY = (getTileFactory().getTileSize(zoom) - getLoadingImage().getHeight(null)) / 2; -// g.setColor(Color.GRAY); -// g.fillRect(ox, oy, size, size); -// g.drawImage(getLoadingImage(), ox + imageX, oy + imageY, null); -// } - if (isDrawTileBorders()) { - - g.setColor(Color.black); - g.drawRect(ox, oy, size, size); - g.drawRect(ox + size / 2 - 5, oy + size / 2 - 5, 10, 10); - g.setColor(Color.white); - g.drawRect(ox + 1, oy + 1, size, size); - - String text = itpx + ", " + itpy + ", " + getZoom(); - g.setColor(Color.BLACK); - g.drawString(text, ox + 10, oy + 30); - g.drawString(text, ox + 10 + 2, oy + 30 + 2); - g.setColor(Color.WHITE); - g.drawString(text, ox + 10 + 1, oy + 30 + 1); - } - //} - } - } - } - - /** - * Draw layer - * @param g The Graphics2D - * @param width Canvas width - * @param height Canvas height - * @param tll TileLoadListener - */ - public void drawWebMapLayer(Graphics2D g, int width, int height, TileLoadListener tll) { - //layer.setZoom(zoom); - //layer.drawMapTiles(g, zoom, width, height); - Rectangle viewportBounds = this.calculateViewportBounds(g, width, height); - int size = this.getTileFactory().getTileSize(zoom); - Dimension mapSize = this.getTileFactory().getMapSize(zoom); - - //calculate the "visible" viewport area in tiles - int numWide = viewportBounds.width / size + 2; - int numHigh = viewportBounds.height / size + 2; - - //TilePoint topLeftTile = getTileFactory().getTileCoordinate( - // new Point2D.Double(viewportBounds.x, viewportBounds.y)); - TileFactoryInfo info = this.getTileFactory().getInfo(); - int tpx = (int) Math.floor(viewportBounds.getX() / info.getTileSize(0)); - int tpy = (int) Math.floor(viewportBounds.getY() / info.getTileSize(0)); - //TilePoint topLeftTile = new TilePoint(tpx, tpy); - - //p("top tile = " + topLeftTile); - //fetch the tiles from the factory and store them in the tiles cache - //attach the TileLoadListener - //String language = layer.getTileFactory().getInfo().getLanguage(); - for (int x = 0; x <= numWide; x++) { - for (int y = 0; y <= numHigh; y++) { - int itpx = x + tpx;//topLeftTile.getX(); - int itpy = y + tpy;//topLeftTile.getY(); - //TilePoint point = new TilePoint(x + topLeftTile.getX(), y + topLeftTile.getY()); - //only proceed if the specified tile point lies within the area being painted - //if (g.getClipBounds().intersects(new Rectangle(itpx * size - viewportBounds.x, - //itpy * size - viewportBounds.y, size, size))) { - Tile tile = this.getTileFactory().getTile(itpx, itpy, zoom); - tile.addUniquePropertyChangeListener("loaded", tll); //this is a filthy hack - int ox = ((itpx * this.getTileFactory().getTileSize(zoom)) - viewportBounds.x); - int oy = ((itpy * this.getTileFactory().getTileSize(zoom)) - viewportBounds.y); - - //if the tile is off the map to the north/south, then just don't paint anything - if (this.isTileOnMap(itpx, itpy, mapSize)) { -// if (isOpaque()) { -// g.setColor(getBackground()); -// g.fillRect(ox,oy,size,size); -// } - } else if (tile.isLoaded()) { - g.drawImage(tile.getImage(), ox, oy, null); - } else { - int imageX = (this.getTileFactory().getTileSize(zoom) - this.getLoadingImage().getWidth(null)) / 2; - int imageY = (this.getTileFactory().getTileSize(zoom) - this.getLoadingImage().getHeight(null)) / 2; - g.setColor(Color.GRAY); - g.fillRect(ox, oy, size, size); - g.drawImage(this.getLoadingImage(), ox + imageX, oy + imageY, null); - } - if (this.isDrawTileBorders()) { - - g.setColor(Color.black); - g.drawRect(ox, oy, size, size); - g.drawRect(ox + size / 2 - 5, oy + size / 2 - 5, 10, 10); - g.setColor(Color.white); - g.drawRect(ox + 1, oy + 1, size, size); - - String text = itpx + ", " + itpy + ", " + this.getZoom(); - g.setColor(Color.BLACK); - g.drawString(text, ox + 10, oy + 30); - g.drawString(text, ox + 10 + 2, oy + 30 + 2); - g.setColor(Color.WHITE); - g.drawString(text, ox + 10 + 1, oy + 30 + 1); - } - //} - } - } - } - - private double getWebMapScale(int zoom, int width, int height) { - Point2D center = this.getCenter(); - double minx = center.getX() - width / 2; - double miny = center.getY() - height / 2; - double maxx = center.getX() + width / 2; - double maxy = center.getY() + height / 2; - GeoPosition pos1 = GeoUtil.getPosition(new Point2D.Double(minx, miny), zoom, this.getTileFactory().getInfo()); - GeoPosition pos2 = GeoUtil.getPosition(new Point2D.Double(maxx, maxy), zoom, this.getTileFactory().getInfo()); - PointD p1 = Reproject.reprojectPoint(new PointD(pos1.getLongitude(), pos1.getLatitude()), - KnownCoordinateSystems.geographic.world.WGS1984, this.getProjInfo()); - PointD p2 = Reproject.reprojectPoint(new PointD(pos2.getLongitude(), pos2.getLatitude()), - KnownCoordinateSystems.geographic.world.WGS1984, this.getProjInfo()); - if (pos2.getLongitude() - pos1.getLongitude() < 360.0) { - double xlen = p2.X - p1.X; -// if (pos2.getLongitude() - pos1.getLongitude() > 360) -// xlen += 2.0037497210840166E7 * 2; - return (double) width / xlen; - } else { - double ylen = Math.abs(p2.Y - p1.Y); - return (double) height / ylen; - } - } - - public boolean isTileOnMap(int x, int y, Dimension mapSize) { - return !isNegativeYAllowed && y < 0 || y >= mapSize.getHeight(); - } - - /** - * Calculate view port bounds - * - * @param g Graphic2D - * @param width The width - * @param height The height - * @return View port bounds rectangle - */ - public Rectangle calculateViewportBounds(Graphics2D g, int width, int height) { - //calculate the "visible" viewport area in pixels - //double sx = g.getTransform().getTranslateX(); - //double sy = g.getTransform().getTranslateY(); - double viewportX = (center.getX() - width / 2); - double viewportY = (center.getY() - height / 2); - return new Rectangle((int) viewportX, (int) viewportY, width, height); - } - - /** - * To string - * @return String - */ - @Override - public String getLayerInfo(){ - String str = "Layer name: " + this.getLayerName(); - str += System.getProperty("line.separator") + "Layer file: " + this.getFileName(); - str += System.getProperty("line.separator") + "Layer type: " + this.getLayerType(); - str += System.getProperty("line.separator") + "Data provider: " + this.defaultProvider; - - return str; - } - // - // - public class WebMapLayerBean { - public WebMapLayerBean(){ - - } - - // - /** - * Get layer type - * - * @return Layer type - */ - public LayerTypes getLayerType() { - return WebMapLayer.this.getLayerType(); - } - - /** - * Get layer draw type - * - * @return Layer draw type - */ - public LayerDrawType getLayerDrawType() { - return WebMapLayer.this.getLayerDrawType(); - } - - /** - * Get layer handle - * - * @return Layer handle - */ - public int getHandle() { - return WebMapLayer.this.getHandle(); - } - - /** - * Get layer name - * - * @return Layer name - */ - public String getLayerName() { - return WebMapLayer.this.getLayerName(); - } - - /** - * Set layer name - * - * @param name Layer name - */ - public void setLayerName(String name) { - WebMapLayer.this.setLayerName(name); - } - - /** - * Get web map provider - * @return The web map provider - */ - public String getWebMapProvider(){ - return WebMapLayer.this.defaultProvider.toString(); - } - - /** - * Set web map provider - * @param provider The web map provider - */ - public void setWebMapProvider(String provider){ - WebMapLayer.this.setWebMapProvider(WebMapProvider.valueOf(provider)); - } - - /** - * Get if is maskout - * - * @return If is maskout - */ - public boolean isMaskout() { - return WebMapLayer.this.isMaskout(); - } - - /** - * Set if maskout - * - * @param value If maskout - */ - public void setMaskout(boolean value) { - WebMapLayer.this.setMaskout(value); - } - - /** - * Get if is visible - * - * @return If is visible - */ - public boolean isVisible() { - return WebMapLayer.this.isVisible(); - } - - /** - * Set if is visible - * - * @param value If is visible - */ - public void setVisible(boolean value) { - WebMapLayer.this.setVisible(value); - } - - /** - * Get language - * @return The language - */ - public String getLanguage(){ - return WebMapLayer.this.getTileFactory().getInfo().getLanguage(); - } - - /** - * Set language - * @param value The language - */ - public void setLanguage(String value) { - WebMapLayer.this.getTileFactory().getInfo().setLanguage(value); - } - - // - } - - public static class WebMapLayerBeanBeanInfo extends BaseBeanInfo { - - public WebMapLayerBeanBeanInfo() { - super(WebMapLayer.WebMapLayerBean.class); - addProperty("layerType").setCategory("Read only").setReadOnly().setDisplayName("Layer type"); - addProperty("layerDrawType").setCategory("Read only").setReadOnly().setDisplayName("Layer draw type"); - addProperty("handle").setCategory("Read only").setReadOnly().setDisplayName("Handle"); - ExtendedPropertyDescriptor e = addProperty("webMapProvider"); - e.setCategory("Editable").setDisplayName("Web Map Provider"); - e.setPropertyEditorClass(WebMapProviderEditor.class); - e = addProperty("language"); - e.setCategory("Editable").setDisplayName("Language"); - e.setPropertyEditorClass(LanguageEditor.class); - addProperty("visible").setCategory("Editable").setDisplayName("Visible"); - addProperty("maskout").setCategory("Editable").setDisplayName("Is maskout"); - } - } - - public static class WebMapProviderEditor extends ComboBoxPropertyEditor { - - public WebMapProviderEditor() { - super(); - WebMapProvider[] providers = WebMapProvider.values(); - String[] types = new String[providers.length]; - int i = 0; - for (WebMapProvider prov : providers) { - types[i] = prov.toString(); - i += 1; - } - setAvailableValues(types); - } - } - - public static class LanguageEditor extends ComboBoxPropertyEditor { - - public LanguageEditor() { - super(); - String[] langs = new String[]{"en-us", "zh-cn"}; - setAvailableValues(langs); - } - } - // -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.layer; + +//import com.sun.java.swing.Painter; +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import javax.imageio.ImageIO; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.data.mapdata.webmap.*; +import org.meteoinfo.data.mapdata.webmap.empty.EmptyTileFactory; +import org.meteoinfo.global.util.GeoUtil; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.Reproject; +import org.meteoinfo.shape.ShapeTypes; + +/** + * + * @author wyq + */ +public class WebMapLayer extends MapLayer { + // + + private final boolean isNegativeYAllowed = true; //maybe rename to isNorthBounded and isSouthBounded? + /** + * The zoom level. Generally a value between 1 and 15 (TODO Is this true for + * all the mapping worlds? What does this mean if some mapping system + * doesn't support the zoom level? + */ + private int zoom = 11; + /** + * The position, in map coordinates of the center point. This is + * defined as the distance from the top and left edges of the map in pixels. + * Dragging the map component will change the center position. Zooming + * in/out will cause the center to be recalculated so as to remain in the + * center of the new "map". + */ + private Point2D center = new Point2D.Double(0, 0); + /** + * Indicates whether or not to draw the borders between tiles. Defaults to + * false. + * + * TODO Generally not very nice looking, very much a product of testing + * Consider whether this should really be a property or not. + */ + private boolean drawTileBorders = false; + /** + * Factory used by this component to grab the tiles necessary for painting + * the map. + */ + private TileFactory factory; + /** + * The position in latitude/longitude of the "address" being mapped. This is + * a special coordinate that, when moved, will cause the map to be moved as + * well. It is separate from "center" in that "center" tracks the current + * center (in pixels) of the viewport whereas this will not change when + * panning or zooming. Whenever the addressLocation is changed, however, the + * map will be repositioned. + */ + private GeoPosition addressLocation; + /** + * Specifies whether panning is enabled. Panning is being able to click and + * drag the map around to cause it to move + */ + private boolean panEnabled = true; + /** + * Specifies whether zooming is enabled (the mouse wheel, for example, + * zooms) + */ + private boolean zoomEnabled = true; + /** + * Indicates whether the component should recenter the map when the "middle" + * mouse button is pressed + */ + private boolean recenterOnClickEnabled = true; + /** + * The overlay to delegate to for painting the "foreground" of the map + * component. This would include painting waypoints, day/night, etc. Also + * receives mouse events. + */ + //private Painter overlay; + private boolean designTime; + private double webMapScale = 0.; + private Image loadingImage; + private boolean restrictOutsidePanning = false; + private boolean horizontalWrapped = true; + private WebMapProvider defaultProvider = WebMapProvider.OpenStreetMap; + private Graphics2D graphics; + private int width; + private int height; + private List scales = new ArrayList<>(); + // + // + // a property change listener which forces repaints when tiles finish loading + //private TileLoadListener tileLoadListener = new TileLoadListener(); + +// private final class TileLoadListener implements PropertyChangeListener { +// +// @Override +// public void propertyChange(PropertyChangeEvent evt) { +// if ("loaded".equals(evt.getPropertyName()) +// && Boolean.TRUE.equals(evt.getNewValue())) { +// Tile t = (Tile) evt.getSource(); +// if (t.getZoom() == getZoom()) { +// repaint(); +// /* this optimization doesn't save much and it doesn't work if you +// * wrap around the world +// Rectangle viewportBounds = getViewportBounds(); +// TilePoint tilePoint = t.getLocation(); +// Point point = new Point(tilePoint.getX() * getTileFactory().getTileSize(), tilePoint.getY() * getTileFactory().getTileSize()); +// Rectangle tileRect = new Rectangle(point, new Dimension(getTileFactory().getTileSize(), getTileFactory().getTileSize())); +// if (viewportBounds.intersects(tileRect)) { +// //convert tileRect from world space to viewport space +// repaint(new Rectangle( +// tileRect.x - viewportBounds.x, +// tileRect.y - viewportBounds.y, +// tileRect.width, +// tileRect.height +// )); +// }*/ +// } +// } +// } +// } + // + // + + /** + * Constructor + */ + public WebMapLayer() { + super(); + this.setLayerType(LayerTypes.WebMapLayer); + this.setShapeType(ShapeTypes.Image); + this.setLayerDrawType(LayerDrawType.Image); + this.setLayerName("OpenStreetMap"); + this.setExtent(new Extent(-2.0037508342789244E7, 2.0037508342789244E7, -1.8375854901481014E7, 1.8375854901481014E7)); + factory = new EmptyTileFactory(); + + // make a dummy loading image + try { + URL url = this.getClass().getResource("/images/loading.png"); + this.setLoadingImage(ImageIO.read(url)); + } catch (Throwable ex) { + System.out.println("could not load 'loading.png'"); + BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = img.createGraphics(); + g2.setColor(Color.black); + g2.fillRect(0, 0, 16, 16); + g2.dispose(); + this.setLoadingImage(img); + } + } + // + // + + /** + * Gets the current zoom level + * + * @return the current zoom level + */ + public int getZoom() { + return this.zoom; + } + + /** + * Set the current zoom level + * + * @param zoom the new zoom level + */ + public void setZoom(int zoom) { + if (zoom == this.zoom) { + return; + } + + TileFactoryInfo info = getTileFactory().getInfo(); + // don't repaint if we are out of the valid zoom levels + if (info != null + && (zoom < info.getMinimumZoomLevel() + || zoom > info.getMaximumZoomLevel())) { + return; + } + + //if(zoom >= 0 && zoom <= 15 && zoom != this.zoom) { + int oldzoom = this.zoom; + Point2D oldCenter = getCenter(); + Dimension oldMapSize = getTileFactory().getMapSize(oldzoom); + this.zoom = zoom; + //this.firePropertyChange("zoom", oldzoom, zoom); + + Dimension mapSize = getTileFactory().getMapSize(zoom); + + setCenter(new Point2D.Double( + oldCenter.getX() * (mapSize.getWidth() / oldMapSize.getWidth()), + oldCenter.getY() * (mapSize.getHeight() / oldMapSize.getHeight()))); + + //repaint(); + } + + /** + * Gets the current pixel center of the map. This point is in the global + * bitmap coordinate system, not as lat/longs. + * + * @return the current center of the map as a pixel value + */ + public Point2D getCenter() { + return center; + } + + public boolean isRestrictOutsidePanning() { + return restrictOutsidePanning; + } + + public void setRestrictOutsidePanning(boolean restrictOutsidePanning) { + this.restrictOutsidePanning = restrictOutsidePanning; + } + + /** + * Sets the new center of the map in pixel coordinates. + * + * @param center the new center of the map in pixel coordinates + */ + public void setCenter(Point2D center) { + this.center = center; +// if(isRestrictOutsidePanning()) { +// Insets insets = getInsets(); +// int viewportHeight = getHeight() - insets.top - insets.bottom; +// int viewportWidth = getWidth() - insets.left - insets.right; +// +// // don't let the user pan over the top edge +// Rectangle newVP = calculateViewportBounds(center); +// if(newVP.getY() < 0) { +// double centerY = viewportHeight/2; +// center = new Point2D.Double(center.getX(),centerY); +// } +// +// // don't let the user pan over the left edge +// if(!isHorizontalWrapped() && newVP.getX() <0) { +// double centerX = viewportWidth/2; +// center = new Point2D.Double(centerX, center.getY()); +// } +// +// // don't let the user pan over the bottom edge +// Dimension mapSize = getTileFactory().getMapSize(getZoom()); +// int mapHeight = (int)mapSize.getHeight()*getTileFactory().getTileSize(getZoom()); +// if(newVP.getY() + newVP.getHeight() > mapHeight) { +// double centerY = mapHeight - viewportHeight/2; +// center = new Point2D.Double(center.getX(),centerY); +// } +// +// //don't let the user pan over the right edge +// int mapWidth = (int)mapSize.getWidth()*getTileFactory().getTileSize(getZoom()); +// if(!isHorizontalWrapped() && (newVP.getX() + newVP.getWidth() > mapWidth)) { +// double centerX = mapWidth - viewportWidth/2; +// center = new Point2D.Double(centerX, center.getY()); +// } +// +// // if map is to small then just center it vert +// if(mapHeight < newVP.getHeight()) { +// double centerY = mapHeight/2;//viewportHeight/2;// - mapHeight/2; +// center = new Point2D.Double(center.getX(),centerY); +// } +// +// // if map is too small then just center it horiz +// if(!isHorizontalWrapped() && mapWidth < newVP.getWidth()) { +// double centerX = mapWidth/2; +// center = new Point2D.Double(centerX, center.getY()); +// } +// } +// +// //joshy: this is an evil hack to force a property change event +// //i don't know why it doesn't work normally +// old = new Point(5,6); +// +// GeoPosition oldGP = this.getCenterPosition(); + } + + /** + * A property indicating the center position of the map + * + * @param geoPosition the new property value + */ + public void setCenterPosition(GeoPosition geoPosition) { + GeoPosition oldVal = getCenterPosition(); + setCenter(getTileFactory().geoToPixel(geoPosition, zoom)); + //repaint(); + GeoPosition newVal = getCenterPosition(); + //firePropertyChange("centerPosition", oldVal, newVal); + } + + /** + * A property indicating the center position of the map + * + * @return the current center position + */ + public GeoPosition getCenterPosition() { + return getTileFactory().pixelToGeo(getCenter(), zoom); + } + + /** + * Get the current factory + * + * @return the current property value + */ + public TileFactory getTileFactory() { + return factory; + } + + /** + * Set the current tile factory + * + * @param factory the new property value + */ + public void setTileFactory(TileFactory factory) { + this.factory = factory; + this.setZoom(factory.getInfo().getDefaultZoomLevel()); + this.setCenterPosition(new GeoPosition(0, 0)); + } + + /** + * Get web map scale + * @return Web map scale + */ + public double getWebMapScale() { + return this.webMapScale; + } + + /** + * Set web map scale + * @param value Web map scale + */ + public void setWebMapScale(double value) { + this.webMapScale = value; + } + + /** + * A property for an image which will be display when an image is still + * loading. + * + * @return the current property value + */ + public Image getLoadingImage() { + return loadingImage; + } + + /** + * A property for an image which will be display when an image is still + * loading. + * + * @param loadingImage the new property value + */ + public void setLoadingImage(Image loadingImage) { + this.loadingImage = loadingImage; + } + + /** + * Indicates if the tile borders should be drawn. Mainly used for debugging. + * + * @return the value of this property + */ + public boolean isDrawTileBorders() { + return drawTileBorders; + } + + /** + * Set if the tile borders should be drawn. Mainly used for debugging. + * + * @param drawTileBorders new value of this drawTileBorders + */ + public void setDrawTileBorders(boolean drawTileBorders) { + //boolean old = isDrawTileBorders(); + this.drawTileBorders = drawTileBorders; + //firePropertyChange("drawTileBorders", old, isDrawTileBorders()); + //repaint(); + } + + /** + * Set web map provider + * @param prov The web map provider + */ + public void setWebMapProvider(WebMapProvider prov) { + TileFactoryInfo info = null; + switch (prov) { +// case SwingLabsBlueMarble: +// setTileFactory(new CylindricalProjectionTileFactory()); +// setZoom(3); +// return; + case OpenStreetMap: + info = new OpenStreetMapInfo(); + break; + case OpenStreetMapQuestSatellite: + info = new OpenStreetMapQuestSatelliteInfo(); + break; + case BingMap: + info = new BingMapInfo(); + break; + case BingSatelliteMap: + info = new BingSatelliteMapInfo(); + break; + case BingHybridMap: + info = new BingHybridMapInfo(); + break; +// case OviMap: +// info = new OviMapInfo(); +// break; +// case OviSatelliteMap: +// info = new OviSatelliteMapInfo(); +// break; +// case OviTerrainMap: +// info = new OviTerrainMapInfo(); +// break; +// case OviHybridMap: +// info = new OviHybridMapInfo(); +// break; + case YahooMap: + info = new YahooMapInfo(); + break; + case YahooSatelliteMap: + info = new YahooSatelliteMapInfo(); + break; + case YahooHybridMap: + info = new YahooHybridMapInfo(); + break; + case GoogleMap: + info = new GoogleMapInfo(); + break; + case GoogleSatelliteMap: + info = new GoogleSatelliteMapInfo(); + break; + case GoogleTerrainMap: + info = new GoogleTerrainMapInfo(); + break; + case GoogleHybridMap: + info = new GoogleHybridMapInfo(); + break; + case GoogleHybridTerrainMap: + info = new GoogleHybridTerrainMapInfo(); + break; +// case BaiduMap: +// info = new BaiduMapInfo(); +// break; +// case BaiduSatelliteMap: +// info = new BaiduSatelliteMapInfo(); +// break; + case AMap: + info = new AMapInfo(); + break; + case ASatelliteMap: + info = new ASatelliteMapInfo(); + break; + case AHybridMap: + info = new AHybridMapInfo(); + break; + case TencentMap: + info = new TencentMapInfo(); + break; + case CMA_CVA_MAP: + info = new CMACvaMapInfo(); + break; + case CMA_VEC_MAP: + info = new CMAVecMapInfo(); + break; + case CMA_IMG_MAP: + info = new CMAImgMapInfo(); + break; +// case ArcGISImage: +// info = new ArcGISImageInfo(); +// break; + } + + if (info != null) { + this.defaultProvider = prov; + this.setLayerName("WebMap_" + info.getName()); + TileFactory tf = new DefaultTileFactory(info); + setTileFactory(tf); + //setZoom(11); + setAddressLocation(new GeoPosition(51.5, 0)); + } + } + + /** + * Get web map provider + * @return Web map provider + */ + public WebMapProvider getWebMapProvider() { + return this.defaultProvider; + } + + public GeoPosition getAddressLocation() { + return this.addressLocation; + } + + public void setAddressLocation(GeoPosition pos, int zoom) { + this.addressLocation = pos; + setCenter(getTileFactory().geoToPixel(pos, zoom)); + } + + public void setAddressLocation(GeoPosition pos) { + this.addressLocation = pos; + setCenter(getTileFactory().geoToPixel(addressLocation, getZoom())); + } + // + // + + /** + * Repaint + */ + public void repaint() { + Rectangle rect = this.calculateViewportBounds(graphics, width, height); + this.drawMapTiles(graphics, zoom, rect); + } + + /** + * Draw the map tiles + * + * @param g Graphics2D + * @param zoom Zoom level to draw at + * @param width The width + * @param height The height + */ + public void drawMapTiles(final Graphics2D g, final int zoom, int width, int height) { + this.graphics = g; + this.zoom = zoom; + this.width = width; + this.height = height; + Rectangle rect = this.calculateViewportBounds(g, width, height); + this.drawMapTiles(g, zoom, rect); + } + + /** + * Draw the map tiles. This method is for implementation use only. + * + * @param g Graphics + * @param zoom zoom level to draw at + * @param viewportBounds View bounds + */ + public void drawMapTiles(final Graphics2D g, final int zoom, final Rectangle viewportBounds) { + int size = getTileFactory().getTileSize(zoom); + Dimension mapSize = getTileFactory().getMapSize(zoom); + + //calculate the "visible" viewport area in tiles + int numWide = viewportBounds.width / size + 2; + int numHigh = viewportBounds.height / size + 2; + + //TilePoint topLeftTile = getTileFactory().getTileCoordinate( + // new Point2D.Double(viewportBounds.x, viewportBounds.y)); + TileFactoryInfo info = getTileFactory().getInfo(); + int tpx = (int) Math.floor(viewportBounds.getX() / info.getTileSize(0)); + int tpy = (int) Math.floor(viewportBounds.getY() / info.getTileSize(0)); + //TilePoint topLeftTile = new TilePoint(tpx, tpy); + + //p("top tile = " + topLeftTile); + //fetch the tiles from the factory and store them in the tiles cache + //attach the tileLoadListener + for (int x = 0; x <= numWide; x++) { + for (int y = 0; y <= numHigh; y++) { + int itpx = x + tpx;//topLeftTile.getX(); + int itpy = y + tpy;//topLeftTile.getY(); + //TilePoint point = new TilePoint(x + topLeftTile.getX(), y + topLeftTile.getY()); + //only proceed if the specified tile point lies within the area being painted + //if (g.getClipBounds().intersects(new Rectangle(itpx * size - viewportBounds.x, + //itpy * size - viewportBounds.y, size, size))) { + Tile tile = getTileFactory().getTile(itpx, itpy, zoom); + //tile.addUniquePropertyChangeListener("loaded", tileLoadListener); //this is a filthy hack + int ox = ((itpx * getTileFactory().getTileSize(zoom)) - viewportBounds.x); + int oy = ((itpy * getTileFactory().getTileSize(zoom)) - viewportBounds.y); + + //if the tile is off the map to the north/south, then just don't paint anything + if (isTileOnMap(itpx, itpy, mapSize)) { +// if (isOpaque()) { +// g.setColor(getBackground()); +// g.fillRect(ox,oy,size,size); +// } + } else if (tile.isLoaded()) { + g.drawImage(tile.getImage(), ox, oy, null); + } +// else { +// int imageX = (getTileFactory().getTileSize(zoom) - getLoadingImage().getWidth(null)) / 2; +// int imageY = (getTileFactory().getTileSize(zoom) - getLoadingImage().getHeight(null)) / 2; +// g.setColor(Color.GRAY); +// g.fillRect(ox, oy, size, size); +// g.drawImage(getLoadingImage(), ox + imageX, oy + imageY, null); +// } + if (isDrawTileBorders()) { + + g.setColor(Color.black); + g.drawRect(ox, oy, size, size); + g.drawRect(ox + size / 2 - 5, oy + size / 2 - 5, 10, 10); + g.setColor(Color.white); + g.drawRect(ox + 1, oy + 1, size, size); + + String text = itpx + ", " + itpy + ", " + getZoom(); + g.setColor(Color.BLACK); + g.drawString(text, ox + 10, oy + 30); + g.drawString(text, ox + 10 + 2, oy + 30 + 2); + g.setColor(Color.WHITE); + g.drawString(text, ox + 10 + 1, oy + 30 + 1); + } + //} + } + } + } + + /** + * Draw layer + * @param g The Graphics2D + * @param width Canvas width + * @param height Canvas height + * @param tll TileLoadListener + */ + public void drawWebMapLayer(Graphics2D g, int width, int height, TileLoadListener tll) { + //layer.setZoom(zoom); + //layer.drawMapTiles(g, zoom, width, height); + Rectangle viewportBounds = this.calculateViewportBounds(g, width, height); + int size = this.getTileFactory().getTileSize(zoom); + Dimension mapSize = this.getTileFactory().getMapSize(zoom); + + //calculate the "visible" viewport area in tiles + int numWide = viewportBounds.width / size + 2; + int numHigh = viewportBounds.height / size + 2; + + //TilePoint topLeftTile = getTileFactory().getTileCoordinate( + // new Point2D.Double(viewportBounds.x, viewportBounds.y)); + TileFactoryInfo info = this.getTileFactory().getInfo(); + int tpx = (int) Math.floor(viewportBounds.getX() / info.getTileSize(0)); + int tpy = (int) Math.floor(viewportBounds.getY() / info.getTileSize(0)); + //TilePoint topLeftTile = new TilePoint(tpx, tpy); + + //p("top tile = " + topLeftTile); + //fetch the tiles from the factory and store them in the tiles cache + //attach the TileLoadListener + //String language = layer.getTileFactory().getInfo().getLanguage(); + for (int x = 0; x <= numWide; x++) { + for (int y = 0; y <= numHigh; y++) { + int itpx = x + tpx;//topLeftTile.getX(); + int itpy = y + tpy;//topLeftTile.getY(); + //TilePoint point = new TilePoint(x + topLeftTile.getX(), y + topLeftTile.getY()); + //only proceed if the specified tile point lies within the area being painted + //if (g.getClipBounds().intersects(new Rectangle(itpx * size - viewportBounds.x, + //itpy * size - viewportBounds.y, size, size))) { + Tile tile = this.getTileFactory().getTile(itpx, itpy, zoom); + tile.addUniquePropertyChangeListener("loaded", tll); //this is a filthy hack + int ox = ((itpx * this.getTileFactory().getTileSize(zoom)) - viewportBounds.x); + int oy = ((itpy * this.getTileFactory().getTileSize(zoom)) - viewportBounds.y); + + //if the tile is off the map to the north/south, then just don't paint anything + if (this.isTileOnMap(itpx, itpy, mapSize)) { +// if (isOpaque()) { +// g.setColor(getBackground()); +// g.fillRect(ox,oy,size,size); +// } + } else if (tile.isLoaded()) { + g.drawImage(tile.getImage(), ox, oy, null); + } else { + int imageX = (this.getTileFactory().getTileSize(zoom) - this.getLoadingImage().getWidth(null)) / 2; + int imageY = (this.getTileFactory().getTileSize(zoom) - this.getLoadingImage().getHeight(null)) / 2; + g.setColor(Color.GRAY); + g.fillRect(ox, oy, size, size); + g.drawImage(this.getLoadingImage(), ox + imageX, oy + imageY, null); + } + if (this.isDrawTileBorders()) { + + g.setColor(Color.black); + g.drawRect(ox, oy, size, size); + g.drawRect(ox + size / 2 - 5, oy + size / 2 - 5, 10, 10); + g.setColor(Color.white); + g.drawRect(ox + 1, oy + 1, size, size); + + String text = itpx + ", " + itpy + ", " + this.getZoom(); + g.setColor(Color.BLACK); + g.drawString(text, ox + 10, oy + 30); + g.drawString(text, ox + 10 + 2, oy + 30 + 2); + g.setColor(Color.WHITE); + g.drawString(text, ox + 10 + 1, oy + 30 + 1); + } + //} + } + } + } + + private double getWebMapScale(int zoom, int width, int height) { + Point2D center = this.getCenter(); + double minx = center.getX() - width / 2; + double miny = center.getY() - height / 2; + double maxx = center.getX() + width / 2; + double maxy = center.getY() + height / 2; + GeoPosition pos1 = GeoUtil.getPosition(new Point2D.Double(minx, miny), zoom, this.getTileFactory().getInfo()); + GeoPosition pos2 = GeoUtil.getPosition(new Point2D.Double(maxx, maxy), zoom, this.getTileFactory().getInfo()); + PointD p1 = Reproject.reprojectPoint(new PointD(pos1.getLongitude(), pos1.getLatitude()), + KnownCoordinateSystems.geographic.world.WGS1984, this.getProjInfo()); + PointD p2 = Reproject.reprojectPoint(new PointD(pos2.getLongitude(), pos2.getLatitude()), + KnownCoordinateSystems.geographic.world.WGS1984, this.getProjInfo()); + if (pos2.getLongitude() - pos1.getLongitude() < 360.0) { + double xlen = p2.X - p1.X; +// if (pos2.getLongitude() - pos1.getLongitude() > 360) +// xlen += 2.0037497210840166E7 * 2; + return (double) width / xlen; + } else { + double ylen = Math.abs(p2.Y - p1.Y); + return (double) height / ylen; + } + } + + public boolean isTileOnMap(int x, int y, Dimension mapSize) { + return !isNegativeYAllowed && y < 0 || y >= mapSize.getHeight(); + } + + /** + * Calculate view port bounds + * + * @param g Graphic2D + * @param width The width + * @param height The height + * @return View port bounds rectangle + */ + public Rectangle calculateViewportBounds(Graphics2D g, int width, int height) { + //calculate the "visible" viewport area in pixels + //double sx = g.getTransform().getTranslateX(); + //double sy = g.getTransform().getTranslateY(); + double viewportX = (center.getX() - width / 2); + double viewportY = (center.getY() - height / 2); + return new Rectangle((int) viewportX, (int) viewportY, width, height); + } + + /** + * To string + * @return String + */ + @Override + public String getLayerInfo(){ + String str = "Layer name: " + this.getLayerName(); + str += System.getProperty("line.separator") + "Layer file: " + this.getFileName(); + str += System.getProperty("line.separator") + "Layer type: " + this.getLayerType(); + str += System.getProperty("line.separator") + "Data provider: " + this.defaultProvider; + + return str; + } + // + // + public class WebMapLayerBean { + public WebMapLayerBean(){ + + } + + // + /** + * Get layer type + * + * @return Layer type + */ + public LayerTypes getLayerType() { + return WebMapLayer.this.getLayerType(); + } + + /** + * Get layer draw type + * + * @return Layer draw type + */ + public LayerDrawType getLayerDrawType() { + return WebMapLayer.this.getLayerDrawType(); + } + + /** + * Get layer handle + * + * @return Layer handle + */ + public int getHandle() { + return WebMapLayer.this.getHandle(); + } + + /** + * Get layer name + * + * @return Layer name + */ + public String getLayerName() { + return WebMapLayer.this.getLayerName(); + } + + /** + * Set layer name + * + * @param name Layer name + */ + public void setLayerName(String name) { + WebMapLayer.this.setLayerName(name); + } + + /** + * Get web map provider + * @return The web map provider + */ + public String getWebMapProvider(){ + return WebMapLayer.this.defaultProvider.toString(); + } + + /** + * Set web map provider + * @param provider The web map provider + */ + public void setWebMapProvider(String provider){ + WebMapLayer.this.setWebMapProvider(WebMapProvider.valueOf(provider)); + } + + /** + * Get if is maskout + * + * @return If is maskout + */ + public boolean isMaskout() { + return WebMapLayer.this.isMaskout(); + } + + /** + * Set if maskout + * + * @param value If maskout + */ + public void setMaskout(boolean value) { + WebMapLayer.this.setMaskout(value); + } + + /** + * Get if is visible + * + * @return If is visible + */ + public boolean isVisible() { + return WebMapLayer.this.isVisible(); + } + + /** + * Set if is visible + * + * @param value If is visible + */ + public void setVisible(boolean value) { + WebMapLayer.this.setVisible(value); + } + + /** + * Get language + * @return The language + */ + public String getLanguage(){ + return WebMapLayer.this.getTileFactory().getInfo().getLanguage(); + } + + /** + * Set language + * @param value The language + */ + public void setLanguage(String value) { + WebMapLayer.this.getTileFactory().getInfo().setLanguage(value); + } + + // + } + + public static class WebMapLayerBeanBeanInfo extends BaseBeanInfo { + + public WebMapLayerBeanBeanInfo() { + super(WebMapLayer.WebMapLayerBean.class); + addProperty("layerType").setCategory("Read only").setReadOnly().setDisplayName("Layer type"); + addProperty("layerDrawType").setCategory("Read only").setReadOnly().setDisplayName("Layer draw type"); + addProperty("handle").setCategory("Read only").setReadOnly().setDisplayName("Handle"); + ExtendedPropertyDescriptor e = addProperty("webMapProvider"); + e.setCategory("Editable").setDisplayName("Web Map Provider"); + e.setPropertyEditorClass(WebMapProviderEditor.class); + e = addProperty("language"); + e.setCategory("Editable").setDisplayName("Language"); + e.setPropertyEditorClass(LanguageEditor.class); + addProperty("visible").setCategory("Editable").setDisplayName("Visible"); + addProperty("maskout").setCategory("Editable").setDisplayName("Is maskout"); + } + } + + public static class WebMapProviderEditor extends ComboBoxPropertyEditor { + + public WebMapProviderEditor() { + super(); + WebMapProvider[] providers = WebMapProvider.values(); + String[] types = new String[providers.length]; + int i = 0; + for (WebMapProvider prov : providers) { + types[i] = prov.toString(); + i += 1; + } + setAvailableValues(types); + } + } + + public static class LanguageEditor extends ComboBoxPropertyEditor { + + public LanguageEditor() { + super(); + String[] langs = new String[]{"en-us", "zh-cn"}; + setAvailableValues(langs); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutChart.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutChart.java index 22cbaf9b..3eb65f45 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutChart.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutChart.java @@ -1,78 +1,78 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.layout; - -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; -import org.meteoinfo.chart.Chart; -import org.meteoinfo.global.PointF; - -/** - * - * @author yaqiang - */ -public class LayoutChart extends LayoutElement { - - // - private Chart chart; - // - // - - /** - * Constructor - */ - public LayoutChart() { - super(); - this.setElementType(ElementType.LayoutChart); - this.setResizeAbility(ResizeAbility.ResizeAll); - this.setWidth(200); - this.setHeight(150); - } - // - // - - /** - * Get chart - * - * @return The chart - */ - public Chart getChart() { - return chart; - } - - /** - * Set chart - * - * @param value The chart - */ - public void setChart(Chart value) { - chart = value; - } - // - // - - @Override - public void paint(Graphics2D g) { - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (chart == null) - return; - - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - Rectangle2D area = new Rectangle2D.Double(aP.X, aP.Y, this.getWidth() * zoom, this.getHeight() * zoom); - chart.draw(g, area); - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.layout; + +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import org.meteoinfo.chart.Chart; +import org.meteoinfo.common.PointF; + +/** + * + * @author yaqiang + */ +public class LayoutChart extends LayoutElement { + + // + private Chart chart; + // + // + + /** + * Constructor + */ + public LayoutChart() { + super(); + this.setElementType(ElementType.LayoutChart); + this.setResizeAbility(ResizeAbility.ResizeAll); + this.setWidth(200); + this.setHeight(150); + } + // + // + + /** + * Get chart + * + * @return The chart + */ + public Chart getChart() { + return chart; + } + + /** + * Set chart + * + * @param value The chart + */ + public void setChart(Chart value) { + chart = value; + } + // + // + + @Override + public void paint(Graphics2D g) { + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (chart == null) + return; + + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + Rectangle2D area = new Rectangle2D.Double(aP.X, aP.Y, this.getWidth() * zoom, this.getHeight() * zoom); + chart.draw(g, area); + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutElement.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutElement.java index 80748a4b..c6d234eb 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutElement.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutElement.java @@ -1,370 +1,371 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import org.meteoinfo.global.event.ILocationChangedListener; -import org.meteoinfo.global.event.ISizeChangedListener; -import org.meteoinfo.global.event.LocationChangedEvent; -import org.meteoinfo.global.event.SizeChangedEvent; -import org.meteoinfo.global.PointF; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import javax.swing.event.EventListenerList; - -/** - * - * @author yaqiang - */ -public abstract class LayoutElement { - // - - public void addLocationChangedListener(ILocationChangedListener listener) { - this._listeners.add(ILocationChangedListener.class, listener); - } - - public void removeLocationChangedListener(ILocationChangedListener listener) { - this._listeners.remove(ILocationChangedListener.class, listener); - } - - public void fireLocationChangedEvent() { - fireLocationChangedEvent(new LocationChangedEvent(this)); - } - - private void fireLocationChangedEvent(LocationChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ILocationChangedListener.class) { - ((ILocationChangedListener) listeners[i + 1]).locationChangedEvent(event); - } - } - } - - public void addSizeChangedListener(ISizeChangedListener listener) { - this._listeners.add(ISizeChangedListener.class, listener); - } - - public void removeSizeChangedListener(ISizeChangedListener listener) { - this._listeners.remove(ISizeChangedListener.class, listener); - } - - public void fireSizeChangedEvent() { - fireSizeChangedEvent(new SizeChangedEvent(this)); - } - - private void fireSizeChangedEvent(SizeChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ISizeChangedListener.class) { - ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); - } - } - } - // - // - private final EventListenerList _listeners = new EventListenerList(); - private int _left; - private int _top; - private int _width; - private int _height; - private ElementType _elementType; - private Color _foreColor; - private Color _backColor; - private boolean _selected; - private ResizeAbility _resizeAbility; - private boolean _visible = true; - private boolean drawBackColor = false; - // - // - - public LayoutElement() { - _foreColor = Color.black; - _backColor = Color.white; - _selected = false; - _resizeAbility = ResizeAbility.None; - } - // - // - - /** - * Get if visible - * - * @return Boolean - */ - public boolean isVisible() { - return _visible; - } - - /** - * Set if visible - * - * @param istrue Boolean - */ - public void setVisible(boolean istrue) { - _visible = istrue; - } - - /** - * Get left - * - * @return Left - */ - public int getLeft() { - return _left; - } - - /** - * Set left - * - * @param left - */ - public void setLeft(int left) { - _left = left; - this.fireLocationChangedEvent(); - } - - /** - * Get top - * - * @return Top - */ - public int getTop() { - return _top; - } - - /** - * Set top - * - * @param top Top - */ - public void setTop(int top) { - _top = top; - this.fireLocationChangedEvent(); - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return _width; - } - - /** - * Set width - * - * @param width Width - */ - public void setWidth(int width) { - _width = width; - this.fireSizeChangedEvent(); - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return _height; - } - - /** - * Set height - * - * @param height Height - */ - public void setHeight(int height) { - _height = height; - this.fireSizeChangedEvent(); - } - - /** - * Get right - * - * @return Right - */ - public int getRight() { - return _left + _width; - } - - /** - * Get bottom - * - * @return Bottom - */ - public int getBottom() { - return _top + _height; - } - - /** - * Get bounds rectangle - * - * @return Bounds rectangle - */ - public Rectangle getBounds() { - return new Rectangle(_left, _top, _width, _height); - } - - /** - * Get element type - * - * @return The element type - */ - public ElementType getElementType() { - return _elementType; - } - - /** - * Set element type - * - * @param type Element type - */ - public void setElementType(ElementType type) { - _elementType = type; - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeColor() { - return _foreColor; - } - - /** - * Set foreground color - * - * @param color Foreground color - */ - public void setForeColor(Color color) { - _foreColor = color; - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackColor() { - return _backColor; - } - - /** - * Set background color - * - * @param color Background color - */ - public void setBackColor(Color color) { - _backColor = color; - } - - /** - * Get if is selected - * - * @return Boolean - */ - public boolean isSelected() { - return _selected; - } - - /** - * Set if is selected - * - * @param istrue Boolean - */ - public void setSelected(boolean istrue) { - _selected = istrue; - } - - /** - * Get resize ability - * - * @return Resize ability - */ - public ResizeAbility getResizeAbility() { - return _resizeAbility; - } - - /** - * Set resize ability - * - * @param ra Resize ability - */ - public void setResizeAbility(ResizeAbility ra) { - _resizeAbility = ra; - } - - /** - * Get is draw backcolor - * @return Boolean - */ - public boolean isDrawBackColor(){ - return drawBackColor; - } - - /** - * Set is draw backcolor - * @param value Boolean - */ - public void setDrawBackColor(boolean value){ - drawBackColor = value; - } - // - // - - /** - * Paint method - * - * @param g Graphics2D - */ - public abstract void paint(Graphics2D g); - - /** - * Paint on layout method - * - * @param g Grahpics2D - * @param pageLocation Page location - * @param zoom Zoom - */ - public abstract void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom); - - /** - * Move update method - */ - public abstract void moveUpdate(); - - /** - * Resize update method - */ - public abstract void resizeUpdate(); - - /** - * Page to screen - * - * @param pageX Page X - * @param pageY Page Y - * @param pageLocation Page location - * @param zoom Zoom - * @return Screen point - */ - public PointF pageToScreen(float pageX, float pageY, PointF pageLocation, float zoom) { - float x = pageX * zoom + pageLocation.X; - float y = pageY * zoom + pageLocation.Y; - return (new PointF(x, y)); - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.global.event.ILocationChangedListener; +import org.meteoinfo.global.event.ISizeChangedListener; +import org.meteoinfo.global.event.LocationChangedEvent; +import org.meteoinfo.global.event.SizeChangedEvent; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.swing.event.EventListenerList; + +/** + * + * @author yaqiang + */ +public abstract class LayoutElement { + // + + public void addLocationChangedListener(ILocationChangedListener listener) { + this._listeners.add(ILocationChangedListener.class, listener); + } + + public void removeLocationChangedListener(ILocationChangedListener listener) { + this._listeners.remove(ILocationChangedListener.class, listener); + } + + public void fireLocationChangedEvent() { + fireLocationChangedEvent(new LocationChangedEvent(this)); + } + + private void fireLocationChangedEvent(LocationChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ILocationChangedListener.class) { + ((ILocationChangedListener) listeners[i + 1]).locationChangedEvent(event); + } + } + } + + public void addSizeChangedListener(ISizeChangedListener listener) { + this._listeners.add(ISizeChangedListener.class, listener); + } + + public void removeSizeChangedListener(ISizeChangedListener listener) { + this._listeners.remove(ISizeChangedListener.class, listener); + } + + public void fireSizeChangedEvent() { + fireSizeChangedEvent(new SizeChangedEvent(this)); + } + + private void fireSizeChangedEvent(SizeChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ISizeChangedListener.class) { + ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); + } + } + } + // + // + private final EventListenerList _listeners = new EventListenerList(); + private int _left; + private int _top; + private int _width; + private int _height; + private ElementType _elementType; + private Color _foreColor; + private Color _backColor; + private boolean _selected; + private ResizeAbility _resizeAbility; + private boolean _visible = true; + private boolean drawBackColor = false; + // + // + + public LayoutElement() { + _foreColor = Color.black; + _backColor = Color.white; + _selected = false; + _resizeAbility = ResizeAbility.None; + } + // + // + + /** + * Get if visible + * + * @return Boolean + */ + public boolean isVisible() { + return _visible; + } + + /** + * Set if visible + * + * @param istrue Boolean + */ + public void setVisible(boolean istrue) { + _visible = istrue; + } + + /** + * Get left + * + * @return Left + */ + public int getLeft() { + return _left; + } + + /** + * Set left + * + * @param left + */ + public void setLeft(int left) { + _left = left; + this.fireLocationChangedEvent(); + } + + /** + * Get top + * + * @return Top + */ + public int getTop() { + return _top; + } + + /** + * Set top + * + * @param top Top + */ + public void setTop(int top) { + _top = top; + this.fireLocationChangedEvent(); + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return _width; + } + + /** + * Set width + * + * @param width Width + */ + public void setWidth(int width) { + _width = width; + this.fireSizeChangedEvent(); + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return _height; + } + + /** + * Set height + * + * @param height Height + */ + public void setHeight(int height) { + _height = height; + this.fireSizeChangedEvent(); + } + + /** + * Get right + * + * @return Right + */ + public int getRight() { + return _left + _width; + } + + /** + * Get bottom + * + * @return Bottom + */ + public int getBottom() { + return _top + _height; + } + + /** + * Get bounds rectangle + * + * @return Bounds rectangle + */ + public Rectangle getBounds() { + return new Rectangle(_left, _top, _width, _height); + } + + /** + * Get element type + * + * @return The element type + */ + public ElementType getElementType() { + return _elementType; + } + + /** + * Set element type + * + * @param type Element type + */ + public void setElementType(ElementType type) { + _elementType = type; + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeColor() { + return _foreColor; + } + + /** + * Set foreground color + * + * @param color Foreground color + */ + public void setForeColor(Color color) { + _foreColor = color; + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackColor() { + return _backColor; + } + + /** + * Set background color + * + * @param color Background color + */ + public void setBackColor(Color color) { + _backColor = color; + } + + /** + * Get if is selected + * + * @return Boolean + */ + public boolean isSelected() { + return _selected; + } + + /** + * Set if is selected + * + * @param istrue Boolean + */ + public void setSelected(boolean istrue) { + _selected = istrue; + } + + /** + * Get resize ability + * + * @return Resize ability + */ + public ResizeAbility getResizeAbility() { + return _resizeAbility; + } + + /** + * Set resize ability + * + * @param ra Resize ability + */ + public void setResizeAbility(ResizeAbility ra) { + _resizeAbility = ra; + } + + /** + * Get is draw backcolor + * @return Boolean + */ + public boolean isDrawBackColor(){ + return drawBackColor; + } + + /** + * Set is draw backcolor + * @param value Boolean + */ + public void setDrawBackColor(boolean value){ + drawBackColor = value; + } + // + // + + /** + * Paint method + * + * @param g Graphics2D + */ + public abstract void paint(Graphics2D g); + + /** + * Paint on layout method + * + * @param g Grahpics2D + * @param pageLocation Page location + * @param zoom Zoom + */ + public abstract void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom); + + /** + * Move update method + */ + public abstract void moveUpdate(); + + /** + * Resize update method + */ + public abstract void resizeUpdate(); + + /** + * Page to screen + * + * @param pageX Page X + * @param pageY Page Y + * @param pageLocation Page location + * @param zoom Zoom + * @return Screen point + */ + public PointF pageToScreen(float pageX, float pageY, PointF pageLocation, float zoom) { + float x = pageX * zoom + pageLocation.X; + float y = pageY * zoom + pageLocation.Y; + return (new PointF(x, y)); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutGraphic.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutGraphic.java index 9f9db4bc..7bf08f98 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutGraphic.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutGraphic.java @@ -1,554 +1,554 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.event.IMapViewUpdatedListener; -import org.meteoinfo.global.event.ISizeChangedListener; -import org.meteoinfo.global.event.MapViewUpdatedEvent; -import org.meteoinfo.global.event.SizeChangedEvent; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; -import org.meteoinfo.layer.LayerDrawType; -import org.meteoinfo.layer.LayerTypes; -import org.meteoinfo.layer.MapLayer; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.legend.BreakTypes; -import org.meteoinfo.legend.LabelBreak; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import org.meteoinfo.legend.VectorBreak; -import org.meteoinfo.shape.Graphic; -import org.meteoinfo.shape.PointShape; -import org.meteoinfo.shape.ShapeTypes; -import org.meteoinfo.shape.WindArrow; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.shape.EllipseShape; - -/** - * - * @author yaqiang - */ -public class LayoutGraphic extends LayoutElement { -// - - private MapLayout _mapLayout; - private LayoutMap _layoutMap; - private Graphic _graphic; - private boolean _updatingSize = false; - private boolean _isTitle = false; - private boolean _isPaint; - private boolean _antiAlias = true; - // - // - - /** - * Constructor - * - * @param aGraphic Graphic - * @param aMapLayout MapLayout - */ - public LayoutGraphic(Graphic aGraphic, MapLayout aMapLayout) { - super(); - this.setElementType(ElementType.LayoutGraphic); - this.setResizeAbility(ResizeAbility.ResizeAll); - - _mapLayout = aMapLayout; - _isPaint = true; - this.setGraphic(aGraphic); - if (_graphic.getLegend() != null) { - if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - ((LabelBreak) _graphic.getLegend()).addSizeChangedListener(new ISizeChangedListener() { - @Override - public void sizeChangedEvent(SizeChangedEvent event) { - updateControlSize(); - } - }); - } - } - } - - /** - * Constructor - * - * @param aGraphic Graphic - * @param aMapLayout MapLayout - * @param aLayoutMap LayoutMap - */ - public LayoutGraphic(Graphic aGraphic, MapLayout aMapLayout, LayoutMap aLayoutMap) { - super(); - this.setElementType(ElementType.LayoutGraphic); - this.setResizeAbility(ResizeAbility.ResizeAll); - - _mapLayout = aMapLayout; - _isPaint = true; - this.setGraphic(aGraphic); - if (_graphic.getLegend() != null) { - if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - ((LabelBreak) _graphic.getLegend()).addSizeChangedListener(new ISizeChangedListener() { - @Override - public void sizeChangedEvent(SizeChangedEvent event) { - updateControlSize(); - } - }); - } - } - - _layoutMap = aLayoutMap; - _layoutMap.addMapViewUpdatedListener(new IMapViewUpdatedListener() { - @Override - public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { - if (_graphic.getLegend().getBreakType() == BreakTypes.VectorBreak) { - for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { - MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). - get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); - if (aLayer.getLayerType() == LayerTypes.VectorLayer) { - if (aLayer.isVisible() && aLayer.getLayerDrawType() == LayerDrawType.Vector) { - setVisible(true); - float zoom = ((VectorLayer) aLayer).getDrawingZoom(); - ((VectorBreak) _graphic.getLegend()).setZoom(zoom); -// float max = 30.0f / zoom; -// WindArraw aWA = (WindArraw) _graphic.getShape(); -// int llen = 5; -// for (i = 10; i <= 100; i += 5) { -// if (max < i) { -// llen = i - 5; -// break; -// } -// } -// aWA.length = llen; -// aWA.size = 5; -// aWA.setValue(0); - updateControlSize(); - break; - } - } - } - } - } - }); - } - // - // - - public Graphic getGraphic() { - return _graphic; - } - - public void setGraphic(Graphic graphic) { - _graphic = graphic; - if (_graphic.getShape() != null) { - switch (_graphic.getShape().getShapeType()) { - case Point: - if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { - this.setResizeAbility(ResizeAbility.SameWidthHeight); - } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - this.setResizeAbility(ResizeAbility.None); - } - break; - case Circle: - this.setResizeAbility(ResizeAbility.SameWidthHeight); - break; - case WindArraw: - this.setResizeAbility(ResizeAbility.None); - break; - default: - this.setResizeAbility(ResizeAbility.ResizeAll); - break; - } - updateControlSize(); - } - } - - /** - * Get if is title - * - * @return If is title - */ - public boolean isTitle() { - return _isTitle; - } - - /** - * Set if is title - * - * @param istrue Boolean - */ - public void setIsTitle(boolean istrue) { - _isTitle = istrue; - } - - /** - * Get if paint - * - * @return If paint - */ - public boolean isPaint() { - return _isPaint; - } - - /** - * Set if paint - * - * @param istrue If paint - */ - public void setIsPaint(boolean istrue) { - _isPaint = istrue; - } - - // - // - /** - * Set label text - * - * @param text Label text - */ - public void setLabelText(String text) { - switch (_graphic.getShape().getShapeType()) { - case Point: - if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - ((LabelBreak) _graphic.getLegend()).setText(text); - updateControlSize(); - } - break; - } - } - - /** - * Update control size - */ - public void updateControlSize() { - if (_graphic.getShape() == null) { - return; - } - - _updatingSize = true; - - switch (_graphic.getShape().getShapeType()) { - case Point: - PointShape aPS = (PointShape) _graphic.getShape(); - this.setLeft((int) aPS.getPoint().X); - this.setTop((int) aPS.getPoint().Y); - if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { - PointBreak aPB = (PointBreak) _graphic.getLegend(); - this.setLeft(this.getLeft() - (int) (aPB.getSize() / 2)); - this.setTop(this.getTop() - (int) (aPB.getSize() / 2)); - this.setWidth((int) Math.ceil(aPB.getSize())); - this.setHeight((int) Math.ceil(aPB.getSize())); - } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - LabelBreak aLB = (LabelBreak) _graphic.getLegend(); - //FontMetrics metrics = _mapLayout.getGraphics().getFontMetrics(aLB.getFont()); - BufferedImage image = new BufferedImage(_mapLayout.getPageBounds().width, _mapLayout.getPageBounds().height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D)image.getGraphics(); - g.setFont(aLB.getFont()); - Dimension aSF = Draw.getStringDimension(aLB.getText(), g); - //FontMetrics metrics = image.getGraphics().getFontMetrics(aLB.getFont()); - //Dimension aSF = new Dimension(metrics.stringWidth(aLB.getText()), metrics.getHeight()); - this.setLeft(this.getLeft() - (int) (aSF.width / 2)); - this.setTop(this.getTop() - (int) (aSF.height * 2 / 3)); - this.setWidth((int) Math.ceil(aSF.width)); - this.setHeight((int) Math.ceil(aSF.getHeight())); - } - break; - case WindArraw: - WindArrow aWA = (WindArrow)_graphic.getShape(); - this.setLeft((int)aWA.getPoint().X); - this.setTop((int)aWA.getPoint().Y); - if (aWA.length == 0){ - aWA.length = 20; - } - this.setWidth((int)(aWA.length * ((VectorBreak)_graphic.getLegend()).getZoom())); - this.setHeight(20); - break; - case Polyline: - case Polygon: - case Rectangle: - case Circle: - case CurveLine: - case CurvePolygon: - case Ellipse: - Extent extent = _graphic.getShape().getExtent(); - this.setLeft((int) Math.ceil(extent.minX)); - this.setTop((int) Math.ceil(extent.minY)); - this.setWidth((int) Math.ceil(extent.getWidth())); - this.setHeight((int) Math.ceil((extent.getHeight()))); - break; - } - - _updatingSize = false; - } - - /** - * Vertice edited update - * - * @param vIdx Vertice index - * @param newX New x - * @param newY New y - */ - public void verticeEditUpdate(int vIdx, double newX, double newY) { - List points = (List) _graphic.getShape().getPoints(); - switch (_graphic.getShape().getShapeType()) { - case Polygon: - case CurvePolygon: - case Rectangle: - int last = points.size() - 1; - if (vIdx == 0) { - if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { - points.get(last).X = newX; - points.get(last).Y = newY; - } - } else if (vIdx == last) { - if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { - points.get(0).X = newX; - points.get(0).Y = newY; - } - } - break; - } - - PointD aP = points.get(vIdx); - aP.X = newX; - aP.Y = newY; - _graphic.getShape().setPoints(points); - updateControlSize(); - } - - @Override - public void paint(Graphics2D g) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (this.isDrawBackColor()){ - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - Rectangle rect = new Rectangle((int) aP.X, (int) aP.Y, (int) (this.getWidth() * zoom), (int) (this.getHeight() * zoom)); - g.setColor(this.getBackColor()); - g.fill(rect); - } - - //Draw graphics - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - paintGraphics(g, pageLocation, zoom); - } - - /** - * Paint graphics - * - * @param g Graphics2D - * @param pageLocation page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { - switch (_graphic.getShape().getShapeType()) { - case Point: - PointD dPoint = _graphic.getShape().getPoints().get(0); - PointF aPoint = pageToScreen((float) dPoint.X, (float) dPoint.Y, pageLocation, zoom); - if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { - PointBreak aPB = (PointBreak) ((PointBreak) _graphic.getLegend()).clone(); - float size = aPB.getSize(); - aPB.setSize(aPB.getSize() * zoom); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Draw.drawPoint(aPoint, aPB, g); - aPB.setSize(size); - if (!_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } - } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { - LabelBreak aLB = (LabelBreak) ((LabelBreak) _graphic.getLegend()).clone(); - Font font = new Font(aLB.getFont().getFontName(), aLB.getFont().getStyle(), aLB.getFont().getSize()); - aLB.setFont(new Font(font.getFontName(), font.getStyle(), (int) (font.getSize() * zoom))); - Rectangle rect = new Rectangle(); - Draw.drawLabelPoint(aPoint, aLB, g, rect); - aLB.setFont(font); - } - break; - case WindArraw: - dPoint = _graphic.getShape().getPoints().get(0); - aPoint = pageToScreen((float) dPoint.X, (float) dPoint.Y, pageLocation, zoom); - WindArrow aArraw = (WindArrow) _graphic.getShape(); - VectorBreak aVB = (VectorBreak) _graphic.getLegend(); - Draw.drawArraw(aVB.getColor(), aPoint, aArraw, g, aVB.getZoom() * zoom); - Font drawFont = new Font("Arial", Font.PLAIN, (int) (12 * zoom)); - FontMetrics metrics = g.getFontMetrics(drawFont); - String drawStr = DataConvert.removeTailingZeros(String.valueOf(aArraw.length)); - Dimension fsize = new Dimension(metrics.stringWidth(drawStr), metrics.getHeight()); - g.setColor(aVB.getColor()); - g.setFont(drawFont); - g.drawString(drawStr, aPoint.X, aPoint.Y + fsize.height); - break; - case Polyline: - case Polygon: - case Rectangle: - case Circle: - case CurveLine: - case CurvePolygon: - case Ellipse: - List pList = (List) _graphic.getShape().getPoints(); - PointF[] points = new PointF[pList.size()]; - for (int i = 0; i < pList.size(); i++) { - points[i] = pageToScreen((float) pList.get(i).X, (float) pList.get(i).Y, pageLocation, zoom); - } - - switch (_graphic.getShape().getShapeType()) { - case Polyline: - PolylineBreak aPLB = (PolylineBreak) ((PolylineBreak) _graphic.getLegend()).clone(); - float size = aPLB.getWidth(); - aPLB.setWidth(size * zoom); - Draw.drawPolyline(points, (PolylineBreak) _graphic.getLegend(), g); - aPLB.setWidth(size); - break; - case Polygon: - case Rectangle: - PolygonBreak aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); - size = aPGB.getOutlineSize(); - aPGB.setOutlineSize(size * zoom); - Draw.drawPolygon(points, (PolygonBreak) _graphic.getLegend(), g); - aPGB.setOutlineSize(size); - break; - case Circle: - aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); - size = aPGB.getOutlineSize(); - aPGB.setOutlineSize(size * zoom); - Draw.drawCircle(points, (PolygonBreak) _graphic.getLegend(), g); - aPGB.setOutlineSize(size); - break; - case CurveLine: - aPLB = (PolylineBreak) ((PolylineBreak) _graphic.getLegend()).clone(); - size = aPLB.getWidth(); - aPLB.setWidth(size * zoom); - Draw.drawCurveLine(points, (PolylineBreak) _graphic.getLegend(), g); - aPLB.setWidth(size); - break; - case CurvePolygon: - aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); - size = aPGB.getOutlineSize(); - aPGB.setOutlineSize(size * zoom); - Draw.drawCurvePolygon(points, (PolygonBreak) _graphic.getLegend(), g); - aPGB.setOutlineSize(size); - break; - case Ellipse: - aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); - size = aPGB.getOutlineSize(); - aPGB.setOutlineSize(size * zoom); - float angle = ((EllipseShape)_graphic.getShape()).getAngle(); - Draw.drawEllipse(points, angle, (PolygonBreak) _graphic.getLegend(), g); - aPGB.setOutlineSize(size); - break; - } - break; - } - } - - @Override - public void moveUpdate() { - if (_graphic.getShape() != null) { - List points = (List) _graphic.getShape().getPoints(); - Extent aExtent = _graphic.getShape().getExtent(); - double minX = aExtent.minX; - double minY = aExtent.minY; - if (_graphic.getShape().getShapeType() == ShapeTypes.Point) { - minX -= this.getWidth() / 2; - if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) - minY -= this.getHeight() / 2; - else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) - minY -= this.getHeight() * 2 / 3; - } - int shiftX = this.getLeft() - (int) minX; - int shiftY = this.getTop() - (int) minY; - for (int i = 0; i < points.size(); i++) { - PointD aP = points.get(i); - aP.X += shiftX; - aP.Y += shiftY; - } - _graphic.getShape().setPoints(points); - } - } - - @Override - public void resizeUpdate() { - if (_graphic.getShape() != null) { - switch (_graphic.getShape().getShapeType()) { - case Point: - if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { - PointBreak aPB = (PointBreak) _graphic.getLegend(); - aPB.setSize(this.getWidth()); - updateControlSize(); - } - break; - case Polyline: - case Polygon: - case CurveLine: - case CurvePolygon: - moveUpdate(); - List points = (List) _graphic.getShape().getPoints(); - Extent aExtent = _graphic.getShape().getExtent(); - int deltaX = this.getWidth() - (int) aExtent.getWidth(); - int deltaY = this.getHeight() - (int) aExtent.getHeight(); - - for (int i = 0; i < points.size(); i++) { - PointD aP = points.get(i); - aP.X = aP.X + deltaX * (aP.X - aExtent.minX) / aExtent.getWidth(); - aP.Y = aP.Y + deltaY * (aP.Y - aExtent.minY) / aExtent.getHeight(); - } - _graphic.getShape().setPoints(points); - break; - case Rectangle: - case Ellipse: - points = new ArrayList<>(); - points.add(new PointD(this.getLeft(), this.getTop())); - points.add(new PointD(this.getLeft(), this.getBottom())); - points.add(new PointD(this.getRight(), this.getBottom())); - points.add(new PointD(this.getRight(), this.getTop())); - if (_graphic.getShape().getShapeType() == ShapeTypes.Rectangle) { - points.add((PointD) points.get(0).clone()); - } - _graphic.getShape().setPoints(points); - break; - case Circle: - points = new ArrayList<>(); - points.add(new PointD(this.getLeft(), this.getTop() + this.getWidth() / 2)); - points.add(new PointD(this.getLeft() + this.getWidth() / 2, this.getTop())); - points.add(new PointD(this.getLeft() + this.getWidth(), this.getTop() + this.getWidth() / 2)); - points.add(new PointD(this.getLeft() + this.getWidth() / 2, this.getTop() + this.getWidth())); - _graphic.getShape().setPoints(points); - break; - } - } - } - - @Override - public void fireLocationChangedEvent() { - super.fireLocationChangedEvent(); - - if (!this._updatingSize) - this.moveUpdate(); - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.global.event.IMapViewUpdatedListener; +import org.meteoinfo.global.event.ISizeChangedListener; +import org.meteoinfo.global.event.MapViewUpdatedEvent; +import org.meteoinfo.global.event.SizeChangedEvent; +import org.meteoinfo.layer.LayerDrawType; +import org.meteoinfo.layer.LayerTypes; +import org.meteoinfo.layer.MapLayer; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.legend.BreakTypes; +import org.meteoinfo.legend.LabelBreak; +import org.meteoinfo.legend.PointBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.legend.PolylineBreak; +import org.meteoinfo.legend.VectorBreak; +import org.meteoinfo.shape.Graphic; +import org.meteoinfo.shape.PointShape; +import org.meteoinfo.shape.ShapeTypes; +import org.meteoinfo.shape.WindArrow; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.shape.EllipseShape; + +/** + * + * @author yaqiang + */ +public class LayoutGraphic extends LayoutElement { +// + + private MapLayout _mapLayout; + private LayoutMap _layoutMap; + private Graphic _graphic; + private boolean _updatingSize = false; + private boolean _isTitle = false; + private boolean _isPaint; + private boolean _antiAlias = true; + // + // + + /** + * Constructor + * + * @param aGraphic Graphic + * @param aMapLayout MapLayout + */ + public LayoutGraphic(Graphic aGraphic, MapLayout aMapLayout) { + super(); + this.setElementType(ElementType.LayoutGraphic); + this.setResizeAbility(ResizeAbility.ResizeAll); + + _mapLayout = aMapLayout; + _isPaint = true; + this.setGraphic(aGraphic); + if (_graphic.getLegend() != null) { + if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + ((LabelBreak) _graphic.getLegend()).addSizeChangedListener(new ISizeChangedListener() { + @Override + public void sizeChangedEvent(SizeChangedEvent event) { + updateControlSize(); + } + }); + } + } + } + + /** + * Constructor + * + * @param aGraphic Graphic + * @param aMapLayout MapLayout + * @param aLayoutMap LayoutMap + */ + public LayoutGraphic(Graphic aGraphic, MapLayout aMapLayout, LayoutMap aLayoutMap) { + super(); + this.setElementType(ElementType.LayoutGraphic); + this.setResizeAbility(ResizeAbility.ResizeAll); + + _mapLayout = aMapLayout; + _isPaint = true; + this.setGraphic(aGraphic); + if (_graphic.getLegend() != null) { + if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + ((LabelBreak) _graphic.getLegend()).addSizeChangedListener(new ISizeChangedListener() { + @Override + public void sizeChangedEvent(SizeChangedEvent event) { + updateControlSize(); + } + }); + } + } + + _layoutMap = aLayoutMap; + _layoutMap.addMapViewUpdatedListener(new IMapViewUpdatedListener() { + @Override + public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { + if (_graphic.getLegend().getBreakType() == BreakTypes.VectorBreak) { + for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { + MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). + get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); + if (aLayer.getLayerType() == LayerTypes.VectorLayer) { + if (aLayer.isVisible() && aLayer.getLayerDrawType() == LayerDrawType.Vector) { + setVisible(true); + float zoom = ((VectorLayer) aLayer).getDrawingZoom(); + ((VectorBreak) _graphic.getLegend()).setZoom(zoom); +// float max = 30.0f / zoom; +// WindArraw aWA = (WindArraw) _graphic.getShape(); +// int llen = 5; +// for (i = 10; i <= 100; i += 5) { +// if (max < i) { +// llen = i - 5; +// break; +// } +// } +// aWA.length = llen; +// aWA.size = 5; +// aWA.setValue(0); + updateControlSize(); + break; + } + } + } + } + } + }); + } + // + // + + public Graphic getGraphic() { + return _graphic; + } + + public void setGraphic(Graphic graphic) { + _graphic = graphic; + if (_graphic.getShape() != null) { + switch (_graphic.getShape().getShapeType()) { + case Point: + if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { + this.setResizeAbility(ResizeAbility.SameWidthHeight); + } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + this.setResizeAbility(ResizeAbility.None); + } + break; + case Circle: + this.setResizeAbility(ResizeAbility.SameWidthHeight); + break; + case WindArraw: + this.setResizeAbility(ResizeAbility.None); + break; + default: + this.setResizeAbility(ResizeAbility.ResizeAll); + break; + } + updateControlSize(); + } + } + + /** + * Get if is title + * + * @return If is title + */ + public boolean isTitle() { + return _isTitle; + } + + /** + * Set if is title + * + * @param istrue Boolean + */ + public void setIsTitle(boolean istrue) { + _isTitle = istrue; + } + + /** + * Get if paint + * + * @return If paint + */ + public boolean isPaint() { + return _isPaint; + } + + /** + * Set if paint + * + * @param istrue If paint + */ + public void setIsPaint(boolean istrue) { + _isPaint = istrue; + } + + // + // + /** + * Set label text + * + * @param text Label text + */ + public void setLabelText(String text) { + switch (_graphic.getShape().getShapeType()) { + case Point: + if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + ((LabelBreak) _graphic.getLegend()).setText(text); + updateControlSize(); + } + break; + } + } + + /** + * Update control size + */ + public void updateControlSize() { + if (_graphic.getShape() == null) { + return; + } + + _updatingSize = true; + + switch (_graphic.getShape().getShapeType()) { + case Point: + PointShape aPS = (PointShape) _graphic.getShape(); + this.setLeft((int) aPS.getPoint().X); + this.setTop((int) aPS.getPoint().Y); + if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { + PointBreak aPB = (PointBreak) _graphic.getLegend(); + this.setLeft(this.getLeft() - (int) (aPB.getSize() / 2)); + this.setTop(this.getTop() - (int) (aPB.getSize() / 2)); + this.setWidth((int) Math.ceil(aPB.getSize())); + this.setHeight((int) Math.ceil(aPB.getSize())); + } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + LabelBreak aLB = (LabelBreak) _graphic.getLegend(); + //FontMetrics metrics = _mapLayout.getGraphics().getFontMetrics(aLB.getFont()); + BufferedImage image = new BufferedImage(_mapLayout.getPageBounds().width, _mapLayout.getPageBounds().height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = (Graphics2D)image.getGraphics(); + g.setFont(aLB.getFont()); + Dimension aSF = Draw.getStringDimension(aLB.getText(), g); + //FontMetrics metrics = image.getGraphics().getFontMetrics(aLB.getFont()); + //Dimension aSF = new Dimension(metrics.stringWidth(aLB.getText()), metrics.getHeight()); + this.setLeft(this.getLeft() - (int) (aSF.width / 2)); + this.setTop(this.getTop() - (int) (aSF.height * 2 / 3)); + this.setWidth((int) Math.ceil(aSF.width)); + this.setHeight((int) Math.ceil(aSF.getHeight())); + } + break; + case WindArraw: + WindArrow aWA = (WindArrow)_graphic.getShape(); + this.setLeft((int)aWA.getPoint().X); + this.setTop((int)aWA.getPoint().Y); + if (aWA.length == 0){ + aWA.length = 20; + } + this.setWidth((int)(aWA.length * ((VectorBreak)_graphic.getLegend()).getZoom())); + this.setHeight(20); + break; + case Polyline: + case Polygon: + case Rectangle: + case Circle: + case CurveLine: + case CurvePolygon: + case Ellipse: + Extent extent = _graphic.getShape().getExtent(); + this.setLeft((int) Math.ceil(extent.minX)); + this.setTop((int) Math.ceil(extent.minY)); + this.setWidth((int) Math.ceil(extent.getWidth())); + this.setHeight((int) Math.ceil((extent.getHeight()))); + break; + } + + _updatingSize = false; + } + + /** + * Vertice edited update + * + * @param vIdx Vertice index + * @param newX New x + * @param newY New y + */ + public void verticeEditUpdate(int vIdx, double newX, double newY) { + List points = (List) _graphic.getShape().getPoints(); + switch (_graphic.getShape().getShapeType()) { + case Polygon: + case CurvePolygon: + case Rectangle: + int last = points.size() - 1; + if (vIdx == 0) { + if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { + points.get(last).X = newX; + points.get(last).Y = newY; + } + } else if (vIdx == last) { + if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { + points.get(0).X = newX; + points.get(0).Y = newY; + } + } + break; + } + + PointD aP = points.get(vIdx); + aP.X = newX; + aP.Y = newY; + _graphic.getShape().setPoints(points); + updateControlSize(); + } + + @Override + public void paint(Graphics2D g) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (this.isDrawBackColor()){ + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + Rectangle rect = new Rectangle((int) aP.X, (int) aP.Y, (int) (this.getWidth() * zoom), (int) (this.getHeight() * zoom)); + g.setColor(this.getBackColor()); + g.fill(rect); + } + + //Draw graphics + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + paintGraphics(g, pageLocation, zoom); + } + + /** + * Paint graphics + * + * @param g Graphics2D + * @param pageLocation page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { + switch (_graphic.getShape().getShapeType()) { + case Point: + PointD dPoint = _graphic.getShape().getPoints().get(0); + PointF aPoint = pageToScreen((float) dPoint.X, (float) dPoint.Y, pageLocation, zoom); + if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { + PointBreak aPB = (PointBreak) ((PointBreak) _graphic.getLegend()).clone(); + float size = aPB.getSize(); + aPB.setSize(aPB.getSize() * zoom); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Draw.drawPoint(aPoint, aPB, g); + aPB.setSize(size); + if (!_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + } else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) { + LabelBreak aLB = (LabelBreak) ((LabelBreak) _graphic.getLegend()).clone(); + Font font = new Font(aLB.getFont().getFontName(), aLB.getFont().getStyle(), aLB.getFont().getSize()); + aLB.setFont(new Font(font.getFontName(), font.getStyle(), (int) (font.getSize() * zoom))); + Rectangle rect = new Rectangle(); + Draw.drawLabelPoint(aPoint, aLB, g, rect); + aLB.setFont(font); + } + break; + case WindArraw: + dPoint = _graphic.getShape().getPoints().get(0); + aPoint = pageToScreen((float) dPoint.X, (float) dPoint.Y, pageLocation, zoom); + WindArrow aArraw = (WindArrow) _graphic.getShape(); + VectorBreak aVB = (VectorBreak) _graphic.getLegend(); + Draw.drawArraw(aVB.getColor(), aPoint, aArraw, g, aVB.getZoom() * zoom); + Font drawFont = new Font("Arial", Font.PLAIN, (int) (12 * zoom)); + FontMetrics metrics = g.getFontMetrics(drawFont); + String drawStr = DataConvert.removeTailingZeros(String.valueOf(aArraw.length)); + Dimension fsize = new Dimension(metrics.stringWidth(drawStr), metrics.getHeight()); + g.setColor(aVB.getColor()); + g.setFont(drawFont); + g.drawString(drawStr, aPoint.X, aPoint.Y + fsize.height); + break; + case Polyline: + case Polygon: + case Rectangle: + case Circle: + case CurveLine: + case CurvePolygon: + case Ellipse: + List pList = (List) _graphic.getShape().getPoints(); + PointF[] points = new PointF[pList.size()]; + for (int i = 0; i < pList.size(); i++) { + points[i] = pageToScreen((float) pList.get(i).X, (float) pList.get(i).Y, pageLocation, zoom); + } + + switch (_graphic.getShape().getShapeType()) { + case Polyline: + PolylineBreak aPLB = (PolylineBreak) ((PolylineBreak) _graphic.getLegend()).clone(); + float size = aPLB.getWidth(); + aPLB.setWidth(size * zoom); + Draw.drawPolyline(points, (PolylineBreak) _graphic.getLegend(), g); + aPLB.setWidth(size); + break; + case Polygon: + case Rectangle: + PolygonBreak aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); + size = aPGB.getOutlineSize(); + aPGB.setOutlineSize(size * zoom); + Draw.drawPolygon(points, (PolygonBreak) _graphic.getLegend(), g); + aPGB.setOutlineSize(size); + break; + case Circle: + aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); + size = aPGB.getOutlineSize(); + aPGB.setOutlineSize(size * zoom); + Draw.drawCircle(points, (PolygonBreak) _graphic.getLegend(), g); + aPGB.setOutlineSize(size); + break; + case CurveLine: + aPLB = (PolylineBreak) ((PolylineBreak) _graphic.getLegend()).clone(); + size = aPLB.getWidth(); + aPLB.setWidth(size * zoom); + Draw.drawCurveLine(points, (PolylineBreak) _graphic.getLegend(), g); + aPLB.setWidth(size); + break; + case CurvePolygon: + aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); + size = aPGB.getOutlineSize(); + aPGB.setOutlineSize(size * zoom); + Draw.drawCurvePolygon(points, (PolygonBreak) _graphic.getLegend(), g); + aPGB.setOutlineSize(size); + break; + case Ellipse: + aPGB = (PolygonBreak) ((PolygonBreak) _graphic.getLegend()).clone(); + size = aPGB.getOutlineSize(); + aPGB.setOutlineSize(size * zoom); + float angle = ((EllipseShape)_graphic.getShape()).getAngle(); + Draw.drawEllipse(points, angle, (PolygonBreak) _graphic.getLegend(), g); + aPGB.setOutlineSize(size); + break; + } + break; + } + } + + @Override + public void moveUpdate() { + if (_graphic.getShape() != null) { + List points = (List) _graphic.getShape().getPoints(); + Extent aExtent = _graphic.getShape().getExtent(); + double minX = aExtent.minX; + double minY = aExtent.minY; + if (_graphic.getShape().getShapeType() == ShapeTypes.Point) { + minX -= this.getWidth() / 2; + if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) + minY -= this.getHeight() / 2; + else if (_graphic.getLegend().getBreakType() == BreakTypes.LabelBreak) + minY -= this.getHeight() * 2 / 3; + } + int shiftX = this.getLeft() - (int) minX; + int shiftY = this.getTop() - (int) minY; + for (int i = 0; i < points.size(); i++) { + PointD aP = points.get(i); + aP.X += shiftX; + aP.Y += shiftY; + } + _graphic.getShape().setPoints(points); + } + } + + @Override + public void resizeUpdate() { + if (_graphic.getShape() != null) { + switch (_graphic.getShape().getShapeType()) { + case Point: + if (_graphic.getLegend().getBreakType() == BreakTypes.PointBreak) { + PointBreak aPB = (PointBreak) _graphic.getLegend(); + aPB.setSize(this.getWidth()); + updateControlSize(); + } + break; + case Polyline: + case Polygon: + case CurveLine: + case CurvePolygon: + moveUpdate(); + List points = (List) _graphic.getShape().getPoints(); + Extent aExtent = _graphic.getShape().getExtent(); + int deltaX = this.getWidth() - (int) aExtent.getWidth(); + int deltaY = this.getHeight() - (int) aExtent.getHeight(); + + for (int i = 0; i < points.size(); i++) { + PointD aP = points.get(i); + aP.X = aP.X + deltaX * (aP.X - aExtent.minX) / aExtent.getWidth(); + aP.Y = aP.Y + deltaY * (aP.Y - aExtent.minY) / aExtent.getHeight(); + } + _graphic.getShape().setPoints(points); + break; + case Rectangle: + case Ellipse: + points = new ArrayList<>(); + points.add(new PointD(this.getLeft(), this.getTop())); + points.add(new PointD(this.getLeft(), this.getBottom())); + points.add(new PointD(this.getRight(), this.getBottom())); + points.add(new PointD(this.getRight(), this.getTop())); + if (_graphic.getShape().getShapeType() == ShapeTypes.Rectangle) { + points.add((PointD) points.get(0).clone()); + } + _graphic.getShape().setPoints(points); + break; + case Circle: + points = new ArrayList<>(); + points.add(new PointD(this.getLeft(), this.getTop() + this.getWidth() / 2)); + points.add(new PointD(this.getLeft() + this.getWidth() / 2, this.getTop())); + points.add(new PointD(this.getLeft() + this.getWidth(), this.getTop() + this.getWidth() / 2)); + points.add(new PointD(this.getLeft() + this.getWidth() / 2, this.getTop() + this.getWidth())); + _graphic.getShape().setPoints(points); + break; + } + } + } + + @Override + public void fireLocationChangedEvent() { + super.fireLocationChangedEvent(); + + if (!this._updatingSize) + this.moveUpdate(); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutLegend.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutLegend.java index 0d5b4ed8..362088c8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutLegend.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutLegend.java @@ -1,2145 +1,2145 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.event.IMapViewUpdatedListener; -import org.meteoinfo.global.event.MapViewUpdatedEvent; -import org.meteoinfo.global.PointF; -import org.meteoinfo.layer.LayerDrawType; -import org.meteoinfo.layer.LayerTypes; -import org.meteoinfo.layer.MapLayer; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.legend.ChartBreak; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.LegendScheme; -import org.meteoinfo.legend.LegendType; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import org.meteoinfo.shape.ShapeTypes; -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.legend.ChartTypes; - -/** - * - * @author Yaqiang Wang - */ -public class LayoutLegend extends LayoutElement { - // - - private MapLayout _mapLayout; - private static LayoutMap _layoutMap; - private MapLayer _legendLayer; - private boolean forceDrawOutline; - private boolean _isAntiAlias; - private LayerUpdateTypes _layerUpdateType; - private LegendStyles _legendStyle; - private String _title; - private Font _font; - private Font _titleFont; - private boolean _drawNeatLine; - private Color _neatLineColor; - private float _neatLineSize; - private float _breakSpace; - private float _topSpace; - private float _leftSpace; - private float _vBarWidth; - private float _hBarHeight; - private int _columnNum = 1; - private boolean drawChartBreaks = true; - private boolean drawPieLabel = false; - // - // - - /** - * Constructor - * - * @param mapLayout Map layout - * @param layoutMap Layout map - */ - public LayoutLegend(MapLayout mapLayout, LayoutMap layoutMap) { - super(); - this.setElementType(ElementType.LayoutLegend); - this.setResizeAbility(ResizeAbility.ResizeAll); - - _mapLayout = mapLayout; - _layoutMap = layoutMap; - _layoutMap.addMapViewUpdatedListener(new IMapViewUpdatedListener() { - @Override - public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { - onMapViewUpdated(event); - } - }); - _isAntiAlias = true; - this.forceDrawOutline = true; - _layerUpdateType = LayerUpdateTypes.FirstMeteoLayer; - _legendStyle = LegendStyles.Normal; - _title = ""; - _drawNeatLine = false; - _neatLineColor = Color.black; - _neatLineSize = 1; - _breakSpace = 3; - _topSpace = 5; - _leftSpace = 5; - _vBarWidth = 10; - _hBarHeight = 10; - _font = new Font("宋体", Font.PLAIN, 12); - _titleFont = new Font("Arial", Font.PLAIN, 12); - } - - // - // - public void onMapViewUpdated(MapViewUpdatedEvent e) { - if (_layoutMap.getMapFrame().getMapView().getLayerNum() == 0) { - return; - } - - switch (_layerUpdateType) { - case FirstExpandedLayer: - for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { - MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). - get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); - if (aLayer.hasLegendScheme()) { - if (aLayer.isVisible() && aLayer.isExpanded() && aLayer.getLegendScheme().getLegendType() != LegendType.SingleSymbol) { - this.setVisible(true); - this.setLegendLayer(aLayer); - break; - } - } - } - break; - case FirstMeteoLayer: - for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { - MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). - get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); - if (aLayer.hasLegendScheme()) { - if (aLayer.isVisible() && aLayer.getLayerDrawType() != LayerDrawType.Map - && aLayer.getLegendScheme().getLegendType() != LegendType.SingleSymbol) { - this.setVisible(true); - this.setLegendLayer(aLayer); - break; - } - } - } - break; - case LastAddedLayer: - if (_layoutMap.getMapFrame().getMapView().getLastAddedLayer().hasLegendScheme()) { - this.setVisible(true); - this.setLegendLayer(_layoutMap.getMapFrame().getMapView().getLastAddedLayer()); - } - break; - } - - updateLegendSize(); - } - // - // - - /** - * Get layout map - * - * @return The layout map - */ - public LayoutMap getLayoutMap() { - return _layoutMap; - } - - /** - * Get legend layer - * - * @return The legend alyer - */ - public MapLayer getLegendLayer() { - return _legendLayer; - } - - /** - * Set legend layer - * - * @param layer The legend layer - */ - public void setLegendLayer(MapLayer layer) { - if (layer == null) { - return; - } - - _legendLayer = layer; - String aStr = _legendLayer.getLayerName(); - if (aStr.contains("_")) { - aStr = aStr.split("_")[1]; - } - _title = aStr; - updateLegendSize(); - } - - /** - * Get legend layer name - * - * @return Legend layer name - */ - public String getLayerName() { - if (_legendLayer != null) { - return _legendLayer.getLayerName(); - } else { - return ""; - } - } - - /** - * Set legend layer name - * - * @param name Layer name - */ - public void setLayerName(String name) { - MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayer(name); - if (aLayer != null) { - _legendLayer = aLayer; - } - } - - /** - * Get if force to draw polygon outline - for normal legend - * - * @return Boolean - */ - public boolean isForceDrawOutline() { - return this.forceDrawOutline; - } - - /** - * Set if force to draw polygon outline - for normal legend - * - * @param value Boolean - */ - public void setForceDrawOutline(boolean value) { - this.forceDrawOutline = value; - } - - /** - * Get layer update type - * - * @return Layer update type - */ - public LayerUpdateTypes getLayerUpdateType() { - return _layerUpdateType; - } - - /** - * Set layer update type - * - * @param type Layer update type - */ - public void setLayerUpdateType(LayerUpdateTypes type) { - _layerUpdateType = type; - } - - /** - * Get legend style - * - * @return Legend style - */ - public LegendStyles getLegendStyle() { - return _legendStyle; - } - - /** - * Set legend style - * - * @param style Legend style - */ - public void setLegendStyle(LegendStyles style) { - _legendStyle = style; - if (this.isVisible()) { - updateLegendSize(); - } - } - - /** - * Get title - * - * @return The title - */ - public String getTitle() { - return _title; - } - - /** - * Set title - * - * @param title The title - */ - public void setTitle(String title) { - _title = title; - updateLegendSize(); - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get font - * - * @return The font - */ - public Font getFont() { - return _font; - } - - /** - * Set font - * - * @param font The font - */ - public void setFont(Font font) { - _font = font; - _titleFont = new Font(_font.getFontName(), Font.PLAIN, _font.getSize() + 2); - updateLegendSize(); - } - - /** - * Get column number - * - * @return Column number - */ - public int getColumnNumber() { - return _columnNum; - } - - /** - * Set column number - * - * @param value Column number - */ - public void setColumnNumber(int value) { - _columnNum = value; - } - - /** - * Get if draw chart breaks - * - * @return Boolean - */ - public boolean isDrawChartBreaks() { - return this.drawChartBreaks; - } - - /** - * Set if draw chart breaks - * - * @param value Boolean - */ - public void setDrawChartBreaks(boolean value) { - this.drawChartBreaks = value; - } - - /** - * Get if draw pie label - * - * @return Boolean - */ - public boolean isDrawPieLabel() { - return this.drawPieLabel; - } - - /** - * Set if draw pie label - * - * @param value Boolean - */ - public void setDrawPieLabel(boolean value) { - this.drawPieLabel = value; - } - - // - // - /** - * Paint graphics - * - * @param g Graphics2D - * @param pageLocation Page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { - if (_legendLayer == null) { - return; - } - - if (_legendLayer.getLayerType() == LayerTypes.ImageLayer) { - return; - } - - AffineTransform oldMatrix = g.getTransform(); - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - g.translate(aP.X, aP.Y); - g.scale(zoom, zoom); - if (this._isAntiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()) { - g.setColor(this.getBackColor()); - g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); - } - - int gap = this.getTickGap(g); - switch (_legendStyle) { - case Bar_Horizontal: - if (gap > 1) { - drawHorizontalBarLegend_Ex(g, zoom); - } else { - drawHorizontalBarLegend(g, zoom); - } - break; - case Bar_Vertical: - if (gap > 1) { - drawVerticalBarLegend_Ex(g, zoom); - } else { - drawVerticalBarLegend(g, zoom); - } - break; - case Normal: - drawNormalLegend(g, zoom); - break; - } - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawChartLegend(Graphics2D g, float zoom, PointF aPoint, boolean drawBreaks) { - VectorLayer aLayer = (VectorLayer) _legendLayer; - ChartBreak aCB = ((ChartBreak) aLayer.getChartPoints().get(0).getLegend()).getSampleChartBreak(); - - //Draw chart symbol - aPoint.X = 5; - aPoint.Y += aCB.getHeight(); - switch (aCB.getChartType()) { - case BarChart: - Draw.drawBarChartSymbol(aPoint, aCB, g, true); - break; - case PieChart: - if (this.drawChartBreaks) { - Draw.drawPieChartSymbol(aPoint, aCB, g, null); - } else { - List rStrs = new ArrayList<>(); - for (int i = 0; i < aCB.getItemNum(); i++) { - rStrs.add(aCB.getLegendScheme().getLegendBreaks().get(i).getCaption()); - } - Draw.drawPieChartSymbol(aPoint, aCB, g, rStrs); - } - aPoint.Y += aCB.getHeight(); - break; - } - aPoint.Y += _breakSpace; - - //Draw breaks - if (drawBreaks) { - LegendScheme aLS = aCB.getLegendScheme(); - drawNormalLegend(g, zoom, aLS, aPoint, false); - } - } - - private void drawNormalLegend(Graphics2D g, float zoom) { - boolean drawChart = false; - if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { - if (((VectorLayer) _legendLayer).getChartSet().isDrawCharts()) { - drawChart = true; - } - } - - PointF aP = new PointF(0, 0); -// if (!drawChart) { -// LegendScheme aLS = _legendLayer.getLegendScheme(); -// drawNormalLegend(g, zoom, aLS, aP, true); -// float height = getBreakHeight(g) * zoom; -// aP.Y += height + _breakSpace; -// } - - LegendScheme aLS = _legendLayer.getLegendScheme(); - drawNormalLegend(g, zoom, aLS, aP, true); - float height = getBreakHeight(g) * zoom; - aP.Y += height + _breakSpace; - - //Draw chart legend - if (drawChart) { - drawChartLegend(g, zoom, aP, this.drawChartBreaks); - } - } - - private void drawNormalLegend(Graphics2D g, float zoom, LegendScheme aLS, PointF aP, boolean drawTitle) { - String caption = ""; - Dimension aSF; - float leftSpace = _leftSpace * zoom; - float topSpace = _topSpace * zoom; - float breakSpace = _breakSpace * zoom; - float height = getBreakHeight(g) * zoom; - float width = height * 2; - float colWidth = getBreakHeight(g) * 2 + getLabelWidth(g) + 10; - - //Draw title - if (drawTitle) { - Font tFont = new Font(_titleFont.getFontName(), _titleFont.getStyle(), (int) (_titleFont.getSize() * zoom)); - String Title = _title; - aP.X = leftSpace; - aP.Y = leftSpace; - FontMetrics metrics = g.getFontMetrics(tFont); - aSF = new Dimension(metrics.stringWidth(Title), metrics.getHeight()); - float titleHeight = aSF.height; - g.setColor(this.getForeColor()); - g.setFont(tFont); - g.drawString(_title, aP.X, aP.Y + aSF.height * 3 / 4); - aP.Y += titleHeight + breakSpace - height / 2; - } - - //Set columns - int[] rowNums = new int[_columnNum]; - int ave = aLS.getVisibleBreakNum() / _columnNum; - int num = 0; - int i; - for (i = 1; i < _columnNum; i++) { - rowNums[i] = ave; - num += ave; - } - rowNums[0] = aLS.getVisibleBreakNum() - num; - - //Draw legend - Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); - float sX = aP.X; - float sY = aP.Y; - i = 0; - for (int col = 0; col < _columnNum; col++) { - aP.X = width / 2 + leftSpace + col * colWidth; - aP.Y = sY; - for (int row = 0; row < rowNums[col]; row++) { - if (!aLS.getLegendBreaks().get(i).isDrawShape()) { - i += 1; - row -= 1; - continue; - } - - aP.Y += height + breakSpace; - //boolean isVisible = true; - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) ((PointBreak) aLS.getLegendBreaks().get(i)).clone(); - caption = aPB.getCaption(); - aPB.setSize(aPB.getSize() * zoom); - Draw.drawPoint((PointF) aP.clone(), aPB, g); - break; - case Polyline: - case PolylineZ: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); - caption = aPLB.getCaption(); - Draw.drawPolylineSymbol((PointF) aP.clone(), width, height, aPLB, g); - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); - caption = aPGB.getCaption(); - if (this.forceDrawOutline) { - aPGB = (PolygonBreak) aPGB.clone(); - aPGB.setDrawOutline(true); - } - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(i); - caption = aCB.getCaption(); - Draw.drawPolygonSymbol((PointF) aP.clone(), aCB.getColor(), Color.black, width, - height, true, true, g); - break; - } - - PointF sP = new PointF(0, 0); - sP.X = aP.X + width / 2; - sP.Y = aP.Y; - FontMetrics metrics = g.getFontMetrics(lFont); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(this.getForeColor()); - g.setFont(lFont); - //g.drawString(caption, sP.X + 5, sP.Y + aSF.height / 3); - g.drawString(caption, sP.X + 5, sP.Y + aSF.height / 4); - - i += 1; - } - } - } - - /** - * Update tick gap - * - * @param g Graphics2D - */ - private int getTickGap(Graphics2D g) { - double len; - int n = this._legendLayer.getLegendScheme().getBreakNum(); - int nn; - if (this.getLegendStyle() == LegendStyles.Bar_Horizontal) { - len = this.getWidth(); - int labLen = this.getLabelWidth(g); - nn = (int) ((len * 0.8) / labLen); - } else { - len = this.getHeight(); - FontMetrics metrics = g.getFontMetrics(this._font); - nn = (int) (len / metrics.getHeight()); - } - if (nn == 0) { - nn = 1; - } - return n / nn + 1; - } - - private void drawVerticalBarLegend(Graphics2D g, float zoom) { - LegendScheme aLS = _legendLayer.getLegendScheme(); - PointF aP = new PointF(0, 0); - PointF sP = new PointF(0, 0); - boolean DrawShape = true, DrawFill = true, DrawOutline = true; - Color FillColor = Color.red, OutlineColor = this.getForeColor(); - String caption = ""; - Dimension aSF; - - int bNum = aLS.getBreakNum(); - if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - - _vBarWidth = this.getWidth() - this.getLabelWidth(g) - 5; - float width = _vBarWidth * zoom; - float height = (this.getHeight() - 5) * zoom / bNum; - Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); - - boolean order = true; - if (aLS.getBreakNum() > 1) { - try { - double v1 = Double.parseDouble(aLS.getLegendBreaks().get(0).getEndValue().toString()); - double v2 = Double.parseDouble(aLS.getLegendBreaks().get(1).getEndValue().toString()); - if (v2 < v1) { - order = false; - } - } catch (Exception e) { - - } - } - - int idx; - for (int i = 0; i < bNum; i++) { - if (order) { - idx = bNum - i - 1; - } else { - idx = i; - } - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPB.isDrawShape(); - DrawFill = aPB.isDrawFill(); - FillColor = aPB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPB.getCaption(); - } else if (!order) { - caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); - } else { - caption = DataConvert.removeTailingZeros(aPB.getStartValue().toString()); - } - break; - case Polyline: - case PolylineZ: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPLB.getDrawPolyline(); - FillColor = aPLB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPLB.getCaption(); - } else if (!order) { - caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); - } else { - caption = DataConvert.removeTailingZeros(aPLB.getStartValue().toString()); - } - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPGB.isDrawShape(); - DrawFill = aPGB.isDrawFill(); - FillColor = aPGB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPGB.getCaption(); - } else if (!order) { - caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); - } else { - caption = DataConvert.removeTailingZeros(aPGB.getStartValue().toString()); - } - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(idx); - DrawShape = true; - DrawFill = true; - FillColor = aCB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aCB.getCaption(); - } else if (!order) { - caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); - } else { - caption = DataConvert.removeTailingZeros(aCB.getStartValue().toString()); - } - break; - } - - aP.X = width / 2; - aP.Y = i * height + height / 2; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (DrawShape) { - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - - sP.X = aP.X + width / 2 + 5; - sP.Y = aP.Y; - FontMetrics metrics = g.getFontMetrics(lFont); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(this.getForeColor()); - g.setFont(lFont); - g.drawString(caption, sP.X, sP.Y + aSF.height / 2); - } else { - if (DrawShape) { - if (i == 0) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = aP.X; - Points[0].Y = 0; - Points[1] = new PointF(); - Points[1].X = 0; - Points[1].Y = height; - Points[2] = new PointF(); - Points[2].X = width; - Points[2].Y = height; - Points[3] = new PointF(); - Points[3].X = aP.X; - Points[3].Y = 0; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (i == bNum - 1) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = 0; - Points[0].Y = i * height; - Points[1] = new PointF(); - Points[1].X = width; - Points[1].Y = i * height; - Points[2] = new PointF(); - Points[2].X = aP.X; - Points[2].Y = i * height + height; - Points[3] = new PointF(); - Points[3].X = 0; - Points[3].Y = i * height; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - - sP.X = aP.X + width / 2 + 5; - sP.Y = aP.Y + height / 2; - if (i < bNum - 1) { - FontMetrics metrics = g.getFontMetrics(lFont); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(this.getForeColor()); - g.setFont(lFont); - g.drawString(caption, sP.X, sP.Y + aSF.height / 2); - } - } - } - } - - private void drawVerticalBarLegend_Ex(Graphics2D g, float zoom) { - LegendScheme aLS = _legendLayer.getLegendScheme(); - PointF aP = new PointF(0, 0); - PointF sP = new PointF(0, 0); - boolean DrawShape = true, DrawFill = true, DrawOutline = false; - Color FillColor = Color.red, OutlineColor = this.getForeColor(); - String caption; - Dimension aSF; - - int bNum = aLS.getBreakNum(); - if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - - int tickGap = this.getTickGap(g); - List labelIdxs = new ArrayList<>(); - int sIdx = (bNum % tickGap) / 2; - int labNum = bNum - 1; - if (aLS.getLegendType() == LegendType.UniqueValue) { - labNum += 1; - } - while (sIdx < labNum) { - labelIdxs.add(sIdx); - sIdx += tickGap; - } - - _vBarWidth = this.getWidth() - this.getLabelWidth(g) - 5; - float width = _vBarWidth; - //float width = _vBarWidth * zoom; - _hBarHeight = (float) this.getHeight() / bNum; - float height = _hBarHeight; - //float height = (this.getHeight() - 5) * zoom / bNum; - //Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); - - boolean order = true; - if (aLS.getBreakNum() > 1) { - try { - double v1 = Double.parseDouble(aLS.getLegendBreaks().get(0).getEndValue().toString()); - double v2 = Double.parseDouble(aLS.getLegendBreaks().get(1).getEndValue().toString()); - if (v2 < v1) { - order = false; - } - } catch (Exception e) { - - } - } - int idx; - for (int i = 0; i < bNum; i++) { - if (order) { - idx = bNum - i - 1; - } else { - idx = i; - } - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPB.isDrawShape(); - DrawFill = aPB.isDrawFill(); - FillColor = aPB.getColor(); - break; - case Polyline: - case PolylineZ: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPLB.getDrawPolyline(); - FillColor = aPLB.getColor(); - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx); - DrawShape = aPGB.isDrawShape(); - DrawFill = aPGB.isDrawFill(); - FillColor = aPGB.getColor(); - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(idx); - DrawShape = true; - DrawFill = true; - FillColor = aCB.getColor(); - break; - } - - aP.X = width / 2; - aP.Y = i * height + height / 2; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (DrawShape) { - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - } else if (DrawShape) { - if (i == 0) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = aP.X; - Points[0].Y = 0; - Points[1] = new PointF(); - Points[1].X = 0; - Points[1].Y = height; - Points[2] = new PointF(); - Points[2].X = width; - Points[2].Y = height; - Points[3] = new PointF(); - Points[3].X = aP.X; - Points[3].Y = 0; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (i == bNum - 1) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = 0; - Points[0].Y = i * height; - Points[1] = new PointF(); - Points[1].X = width; - Points[1].Y = i * height; - Points[2] = new PointF(); - Points[2].X = aP.X; - Points[2].Y = i * height + height; - Points[3] = new PointF(); - Points[3].X = 0; - Points[3].Y = i * height; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - } - - //Draw neatline - g.setColor(Color.black); - if (aLS.getLegendType() == LegendType.UniqueValue) { - g.draw(new Rectangle.Float(0, 0, this._vBarWidth, this._hBarHeight * bNum)); - } else { - Polygon p = new Polygon(); - p.addPoint((int) (width / 2), 0); - p.addPoint(0, (int) height); - p.addPoint(0, (int) (height * (bNum - 1))); - p.addPoint((int) (width / 2), (int) (height * bNum)); - p.addPoint((int) width, (int) (height * (bNum - 1))); - p.addPoint((int) width, (int) height); - g.drawPolygon(p); - } - //Draw ticks - aP.Y = this.getHeight() + _hBarHeight / 2; - int labLen = (int) (this._vBarWidth / 3); - if (labLen < 5) { - labLen = 5; - if (this._vBarWidth < 5) { - labLen = (int) this._vBarWidth; - } - } - - for (int i = 0; i < bNum; i++) { - if (order) { - idx = i; - } else { - idx = bNum - i - 1; - } - ColorBreak cb = aLS.getLegendBreaks().get(idx); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = cb.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(cb.getEndValue().toString()); - } - - aP.X = _vBarWidth / 2; - aP.Y = aP.Y - _hBarHeight; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (labelIdxs.contains(idx)) { - sP.X = aP.X + _vBarWidth / 2 + 5; - sP.Y = aP.Y; - FontMetrics metrics = g.getFontMetrics(this._font); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(Color.black); - g.setFont(this._font); - //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); - Draw.drawString(g, caption, sP.X, sP.Y + aSF.height / 4); - } - } else if (labelIdxs.contains(idx)) { - //g.setColor(Color.black); - sP.X = aP.X + _vBarWidth / 2; - sP.Y = aP.Y - _hBarHeight / 2; - g.draw(new Line2D.Float(sP.X - labLen, sP.Y, sP.X, sP.Y)); - sP.X = sP.X + 5; - if (i < bNum - 1) { - FontMetrics metrics = g.getFontMetrics(this._font); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setFont(this._font); - //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); - Draw.drawString(g, caption, sP.X, sP.Y + aSF.height / 4); - } - } - } - } - - private void drawHorizontalBarLegend(Graphics2D g, float zoom) { - LegendScheme aLS = _legendLayer.getLegendScheme(); - PointF aP = new PointF(0, 0); - PointF sP = new PointF(0, 0); - float width, height; - boolean DrawShape = true, DrawFill = true, DrawOutline = true; - Color FillColor = Color.red, OutlineColor = this.getForeColor(); - String caption = ""; - Dimension aSF; - - int bNum = aLS.getBreakNum(); - if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - - Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); - FontMetrics metrics = g.getFontMetrics(lFont); - _vBarWidth = this.getHeight() - metrics.getHeight() - 5; - width = (this.getWidth() - 5) * zoom / bNum; - height = _vBarWidth * zoom; - - for (int i = 0; i < bNum; i++) { - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPB.isDrawShape(); - DrawFill = aPB.isDrawFill(); - FillColor = aPB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPB.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); - } - break; - case Polyline: - case PolylineZ: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPLB.getDrawPolyline(); - FillColor = aPLB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPLB.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); - } - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPGB.isDrawShape(); - DrawFill = aPGB.isDrawFill(); - FillColor = aPGB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aPGB.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); - } - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(i); - DrawShape = true; - DrawFill = true; - FillColor = aCB.getColor(); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = aCB.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); - } - break; - } - - aP.X = i * width + width / 2; - aP.Y = height / 2; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (DrawShape) { - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - - sP.X = aP.X; - sP.Y = aP.Y + height / 2; - //FontMetrics metrics = g.getFontMetrics(lFont); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(this.getForeColor()); - g.setFont(lFont); - g.drawString(caption, sP.X - aSF.width / 2, sP.Y + aSF.height); - } else { - if (DrawShape) { - if (i == 0) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = 0; - Points[0].Y = aP.Y; - Points[1] = new PointF(); - Points[1].X = width; - Points[1].Y = 0; - Points[2] = new PointF(); - Points[2].X = width; - Points[2].Y = height; - Points[3] = new PointF(); - Points[3].X = 0; - Points[3].Y = aP.Y; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (i == bNum - 1) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = i * width; - Points[0].Y = height; - Points[1] = new PointF(); - Points[1].X = i * width; - Points[1].Y = 0; - Points[2] = new PointF(); - Points[2].X = i * width + width; - Points[2].Y = aP.Y; - Points[3] = new PointF(); - Points[3].X = i * width; - Points[3].Y = height; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(true); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - - sP.X = aP.X + width / 2; - sP.Y = aP.Y + height / 2; - if (i < bNum - 1) { - //FontMetrics metrics = g.getFontMetrics(lFont); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(this.getForeColor()); - g.setFont(lFont); - g.drawString(caption, sP.X - aSF.width / 2, sP.Y + aSF.height); - } - } - } - } - - private void drawHorizontalBarLegend_Ex(Graphics2D g, float zoom) { - LegendScheme aLS = _legendLayer.getLegendScheme(); - PointF aP = new PointF(0, 0); - PointF sP = new PointF(0, 0); - float width, height; - boolean DrawShape = true, DrawFill = true, DrawOutline = false; - Color FillColor = Color.red, OutlineColor = this.getForeColor(); - String caption = ""; - Dimension aSF; - - int bNum = aLS.getBreakNum(); - if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - - int tickGap = this.getTickGap(g); - List labelIdxs = new ArrayList<>(); - int sIdx = (bNum % tickGap) / 2; - int labNum = bNum - 1; - if (aLS.getLegendType() == LegendType.UniqueValue) { - labNum += 1; - } - while (sIdx < labNum) { - labelIdxs.add(sIdx); - sIdx += tickGap; - } - - Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); - FontMetrics metrics = g.getFontMetrics(lFont); - _vBarWidth = this.getHeight() - metrics.getHeight() - 5; - //width = (this.getWidth() - 5) * zoom / bNum; - width = this.getWidth() / bNum; - //height = _vBarWidth * zoom; - height = _vBarWidth; - int idx; - for (int i = 0; i < bNum; i++) { - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPB.isDrawShape(); - DrawFill = aPB.isDrawFill(); - FillColor = aPB.getColor(); - break; - case Polyline: - case PolylineZ: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPLB.getDrawPolyline(); - FillColor = aPLB.getColor(); - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); - DrawShape = aPGB.isDrawShape(); - DrawFill = aPGB.isDrawFill(); - FillColor = aPGB.getColor(); - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(i); - DrawShape = true; - DrawFill = true; - FillColor = aCB.getColor(); - break; - } - - aP.X = i * width + width / 2; - aP.Y = height / 2; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (DrawShape) { - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - } else if (DrawShape) { - if (i == 0) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = 0; - Points[0].Y = aP.Y; - Points[1] = new PointF(); - Points[1].X = width; - Points[1].Y = 0; - Points[2] = new PointF(); - Points[2].X = width; - Points[2].Y = height; - Points[3] = new PointF(); - Points[3].X = 0; - Points[3].Y = aP.Y; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (i == bNum - 1) { - PointF[] Points = new PointF[4]; - Points[0] = new PointF(); - Points[0].X = i * width; - Points[0].Y = height; - Points[1] = new PointF(); - Points[1].X = i * width; - Points[1].Y = 0; - Points[2] = new PointF(); - Points[2].X = i * width + width; - Points[2].Y = aP.Y; - Points[3] = new PointF(); - Points[3].X = i * width; - Points[3].Y = height; - if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygon(Points, aPGB, g); - } else { - Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); - } - } else if (aLS.getShapeType() == ShapeTypes.Polygon) { - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); - aPGB.setDrawOutline(DrawOutline); - aPGB.setOutlineColor(Color.black); - Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); - } else { - Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, - height, DrawFill, DrawOutline, g); - } - } - } - - //Draw neatline - g.setColor(Color.black); - if (aLS.getLegendType() == LegendType.UniqueValue) { - g.draw(new Rectangle.Float(0, 0, width * bNum, height)); - } else { - float extendw = width; -// if (this.autoExtendFrac) -// extendw = _hBarHeight; - Polygon p = new Polygon(); - p.addPoint((int) (width - extendw), (int) (height / 2)); - p.addPoint((int) width, 0); - p.addPoint((int) (width * (bNum - 1)), 0); - p.addPoint((int) (width * (bNum - 1) + extendw), (int) (height / 2)); - p.addPoint((int) (width * (bNum - 1)), (int) height); - p.addPoint((int) width, (int) height); - g.drawPolygon(p); - } - //Draw tick and label - aP.X = -_vBarWidth / 2; - int labLen = (int) (this._hBarHeight / 3); - if (labLen < 5) { - labLen = 5; - if (this._hBarHeight < 5) { - labLen = (int) this._hBarHeight; - } - } - for (int i = 0; i < bNum; i++) { - idx = i; - ColorBreak cb = aLS.getLegendBreaks().get(idx); - if (aLS.getLegendType() == LegendType.UniqueValue) { - caption = cb.getCaption(); - } else { - caption = DataConvert.removeTailingZeros(cb.getEndValue().toString()); - } - - aP.X += width; - aP.Y = height / 2; - - if (aLS.getLegendType() == LegendType.UniqueValue) { - if (labelIdxs.contains(idx)) { - sP.X = aP.X; - sP.Y = aP.Y + height / 2 + 5; - metrics = g.getFontMetrics(this._font); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setColor(Color.black); - g.setFont(this._font); - //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); - Draw.drawString(g, caption, sP.X - aSF.width / 2, sP.Y + aSF.height * 3 / 4); - } - } else if (labelIdxs.contains(idx)) { - //g.setColor(Color.black); - sP.X = aP.X + _vBarWidth / 2; - sP.Y = aP.Y + height / 2; - g.draw(new Line2D.Float(sP.X, sP.Y, sP.X, sP.Y - labLen)); - sP.Y = sP.Y + 5; - if (i < bNum - 1) { - metrics = g.getFontMetrics(this._font); - aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); - g.setFont(this._font); - //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); - Draw.drawString(g, caption, sP.X - aSF.width / 2, sP.Y + aSF.height * 3 / 4); - } - } - } - } - - private int getLabelWidth(Graphics2D g) { - LegendScheme aLS = _legendLayer.getLegendScheme(); - float width = 0; - String caption = ""; - Dimension aSF; - int bNum = aLS.getBreakNum(); - FontMetrics metrics = g.getFontMetrics(_font); - if (_legendStyle == LegendStyles.Normal) { - aSF = new Dimension(metrics.stringWidth(_title), metrics.getHeight()); - width = aSF.width; - } else if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - for (int i = 0; i < bNum; i++) { - switch (aLS.getShapeType()) { - case Point: - PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); - if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { - caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); - } else { - caption = aPB.getCaption(); - } - break; - case Polyline: - PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); - if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { - caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); - } else { - caption = aPLB.getCaption(); - } - break; - case Polygon: - PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); - if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { - caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); - } else { - caption = aPGB.getCaption(); - } - break; - case Image: - ColorBreak aCB = aLS.getLegendBreaks().get(i); - if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { - caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); - } else { - caption = aCB.getCaption(); - } - break; - } - - boolean isValid = true; - switch (aLS.getLegendType()) { - case GraduatedColor: - if (_legendStyle != LegendStyles.Normal) { - if (i == bNum - 1) { - isValid = false; - } - } - break; - } - if (isValid) { - float labwidth = metrics.stringWidth(caption); - if (width < labwidth) { - width = labwidth; - } - } - } - - if (_legendStyle == LegendStyles.Normal) { - if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { - if (((VectorLayer) _legendLayer).getChartSet().isDrawCharts()) { - ChartBreak aCB = ((ChartBreak) ((VectorLayer) _legendLayer).getChartPoints().get(0).getLegend()).getSampleChartBreak(); - if (aCB.getChartType() == ChartTypes.BarChart) { - LegendScheme ls = aCB.getLegendScheme(); - for (ColorBreak cb : ls.getLegendBreaks()) { - float labwidth = metrics.stringWidth(cb.getCaption()); - if (width < labwidth) { - width = metrics.stringWidth(cb.getCaption()); - } - } - } - } - } - } - - return (int) width; - } - - private int getBreakHeight(Graphics2D g) { - String title = _title; - if ("".equals(title.trim())) { - title = "Temp"; - } - - FontMetrics metrics = g.getFontMetrics(_font); - Dimension aSF = new Dimension(metrics.stringWidth(title), metrics.getHeight()); - return aSF.height; - } - - private int getTitleHeight(Graphics2D g) { - FontMetrics metrics = g.getFontMetrics(_titleFont); - Dimension aSF = new Dimension(metrics.stringWidth(_title), metrics.getHeight()); - return aSF.height; - } - - /** - * Update legend control size - */ - public void updateLegendSize() { - if (this._legendStyle != LegendStyles.Normal) { - return; - } - - if (_legendLayer != null) { - if (_legendLayer.getLegendScheme() == null) { - return; - } - - //Graphics2D g = (Graphics2D) _mapLayout.getGraphics(); - BufferedImage image = new BufferedImage(_mapLayout.getPageBounds().width, _mapLayout.getPageBounds().height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - int bNum = _legendLayer.getLegendScheme().getBreakNum(); - if (_legendLayer.getLegendScheme().getLegendBreaks().get(bNum - 1).isNoData()) { - bNum -= 1; - } - - int w = this.getWidth(); - int h = this.getHeight(); - int nw, nh; - switch (_legendStyle) { - case Bar_Vertical: - nw = 10 + getLabelWidth(g) + 5; - nh = bNum * 20; - if (nw > w) { - this.setWidth(nw); - } - if (nh > h) { - this.setHeight(bNum * 20); - } - break; - case Bar_Horizontal: - nw = bNum * 30; - nh = 30; - if (nw > w) { - this.setWidth(nw); - } - if (nh > h) { - this.setHeight(bNum * 20); - } - break; - case Normal: - int aHeight = getBreakHeight(g); - int colWidth = aHeight * 2 + getLabelWidth(g) + 15; - this.setWidth(colWidth * _columnNum); - - //Set columns - int[] rowNums = new int[_columnNum]; - int ave = _legendLayer.getLegendScheme().getVisibleBreakNum() / _columnNum; - int num = 0; - int i; - for (i = 1; i < _columnNum; i++) { - rowNums[i] = ave; - num += ave; - } - rowNums[0] = _legendLayer.getLegendScheme().getVisibleBreakNum() - num; - - this.setHeight((int) (rowNums[0] * (aHeight + _breakSpace) - + getTitleHeight(g) + _breakSpace * 2 + aHeight / 2 + 5)); - if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { - VectorLayer aLayer = (VectorLayer) _legendLayer; - if (aLayer.getChartSet().isDrawCharts()) { - ChartBreak aCB = ((ChartBreak) aLayer.getChartPoints().get(0).getLegend()).getSampleChartBreak(); - this.setHeight(this.getHeight() + (int) (_breakSpace * 2 + aCB.getHeight() - + aCB.getLegendScheme().getBreakNum() * (aHeight + _breakSpace) + aHeight / 2 + 5)); - } - } - break; - } - } - } - - @Override - public void paint(Graphics2D g) { - //throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (this.isVisible()) { - paintGraphics(g, pageLocation, zoom); - } - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - - /** - * Get layer names - * - * @return Layer names - */ - public static List getLayerNames() { - List layerNames = new ArrayList<>(); - for (MapLayer aLayer : _layoutMap.getMapFrame().getMapView().getLayers()) { - if (aLayer.getLayerType() == LayerTypes.VectorLayer || aLayer.getLayerType() == LayerTypes.RasterLayer) { - layerNames.add(aLayer.getLayerName()); - } - } - - return layerNames; - } - // - - // - public class LayoutLegendBean { - - LayoutLegendBean() { - } - - // - /** - * Get layout map - * - * @return The layout map - */ - public LayoutMap getLayoutMap() { - return _layoutMap; - } - - /** - * Get legend layer - * - * @return The legend alyer - */ - public MapLayer getLegendLayer() { - return _legendLayer; - } - - /** - * Set legend layer - * - * @param layer The legend layer - */ - public void setLegendLayer(MapLayer layer) { - _legendLayer = layer; - String aStr = _legendLayer.getLayerName(); - if (aStr.contains("_")) { - aStr = aStr.split("_")[1]; - } - _title = aStr; - updateLegendSize(); - } - - /** - * Get legend layer name - * - * @return Legend layer name - */ - public String getLayerName() { - if (_legendLayer != null) { - return _legendLayer.getLayerName(); - } else { - return null; - } - } - - /** - * Set legend layer name - * - * @param name Layer name - */ - public void setLayerName(String name) { - MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayer(name); - if (aLayer != null) { - this.setLegendLayer(aLayer); - } - } - - /** - * Get if force to draw polygon outline - for normal legend - * - * @return Boolean - */ - public boolean isForceDrawOutline() { - return forceDrawOutline; - } - - /** - * Set if force to draw polygon outline - for normal legend - * - * @param value Boolean - */ - public void setForceDrawOutline(boolean value) { - forceDrawOutline = value; - } - - /** - * Get layer update type string - * - * @return Layer update type string - */ - public String getLayerUpdateType() { - return _layerUpdateType.toString(); - } - - /** - * Set layer update type - * - * @param typeStr Layer update type string - */ - public void setLayerUpdateType(String typeStr) { - _layerUpdateType = LayerUpdateTypes.valueOf(typeStr); - } - - /** - * Get legend style string - * - * @return Legend style string - */ - public String getLegendStyle() { - return _legendStyle.toString(); - } - - /** - * Set legend style - * - * @param style Legend style string - */ - public void setLegendStyle(String style) { - _legendStyle = LegendStyles.valueOf(style); - if (isVisible()) { - updateLegendSize(); - } - } - - /** - * Get title - * - * @return The title - */ - public String getTitle() { - return _title; - } - - /** - * Set title - * - * @param title The title - */ - public void setTitle(String title) { - _title = title; - updateLegendSize(); - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get font - * - * @return The font - */ - public Font getFont() { - return _font; - } - - /** - * Set font - * - * @param font The font - */ - public void setFont(Font font) { - _font = font; - _titleFont = new Font(_font.getFontName(), Font.PLAIN, _font.getSize() + 2); - updateLegendSize(); - } - - /** - * Get column number - * - * @return Column number - */ - public int getColumnNumber() { - return _columnNum; - } - - /** - * Set column number - * - * @param value Column number - */ - public void setColumnNumber(int value) { - _columnNum = value; - if (isVisible()) { - updateLegendSize(); - } - } - - /** - * Get is draw chart breaks - * - * @return Boolean - */ - public boolean isDrawChartBreaks() { - return drawChartBreaks; - } - - /** - * Set if draw chart breaks - * - * @param value Boolean - */ - public void setDrawChartBreaks(boolean value) { - drawChartBreaks = value; - } - - /** - * Get is draw backcolor - * - * @return Boolean - */ - public boolean isDrawBackColor() { - return LayoutLegend.this.isDrawBackColor(); - } - - /** - * Set is draw backcolor - * - * @param value Boolean - */ - public void setDrawBackColor(boolean value) { - LayoutLegend.this.setDrawBackColor(value); - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackColor() { - return LayoutLegend.this.getBackColor(); - } - - /** - * Set background color - * - * @param c Background color - */ - public void setBackColor(Color c) { - LayoutLegend.this.setBackColor(c); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeColor() { - return LayoutLegend.this.getForeColor(); - } - - /** - * Set foreground color - * - * @param c Foreground color - */ - public void setForeColor(Color c) { - LayoutLegend.this.setForeColor(c); - } - - /** - * Get left - * - * @return Left - */ - public int getLeft() { - return LayoutLegend.this.getLeft(); - } - - /** - * Set left - * - * @param left Left - */ - public void setLeft(int left) { - LayoutLegend.this.setLeft(left); - } - - /** - * Get top - * - * @return Top - */ - public int getTop() { - return LayoutLegend.this.getTop(); - } - - /** - * Set top - * - * @param top Top - */ - public void setTop(int top) { - LayoutLegend.this.setTop(top); - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return LayoutLegend.this.getWidth(); - } - - /** - * Set width - * - * @param value Width - */ - public void setWidth(int value) { - LayoutLegend.this.setWidth(value); - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return LayoutLegend.this.getHeight(); - } - - /** - * Set height - * - * @param value Height - */ - public void setHeight(int value) { - LayoutLegend.this.setHeight(value); - } - - /** - * Get bar width - * - * @return Bar width - */ - public float getBarWidth() { - return LayoutLegend.this._vBarWidth; - } - - /** - * Set bar width - * - * @param value Bar width - */ - public void setBarWidth(float value) { - LayoutLegend.this._vBarWidth = value; - } - // - } - - public static class LayoutLegendBeanBeanInfo extends BaseBeanInfo { - - public LayoutLegendBeanBeanInfo() { - super(LayoutLegendBean.class); - ExtendedPropertyDescriptor e = addProperty("layerName"); - e.setCategory("General").setPropertyEditorClass(LayerNameEditor.class); - e.setDisplayName("Layer Name"); - e.setShortDescription("The name of the layer of this legend"); - e = addProperty("layerUpdateType"); - e.setCategory("General").setDisplayName("Layer Update Type"); - e.setPropertyEditorClass(LayerUpdateTypeEditor.class); - e = addProperty("legendStyle"); - e.setCategory("General").setDisplayName("Legend Style"); - e.setPropertyEditorClass(LegendStyleEditor.class); - addProperty("title").setCategory("General").setDisplayName("Title"); - addProperty("font").setCategory("General").setDisplayName("Font"); - addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); - addProperty("backColor").setCategory("General").setDisplayName("Background"); - addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); - addProperty("columnNumber").setCategory("General").setDisplayName("Column Number"); - addProperty("forceDrawOutline").setCategory("General").setDisplayName("Force Draw Outline"); - addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); - addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); - addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); - addProperty("drawChartBreaks").setCategory("Chart").setDisplayName("Draw Chart Breaks"); - //addProperty("drawPieLabel").setCategory("Chart").setDisplayName("Draw Pie label"); - addProperty("left").setCategory("Location").setDisplayName("Left"); - addProperty("top").setCategory("Location").setDisplayName("Top"); - addProperty("width").setCategory("Location").setDisplayName("Width"); - addProperty("height").setCategory("Location").setDisplayName("Height"); - //addProperty("barWidth").setCategory("ColorBar").setDisplayName("Bar Width"); - } - } - - public static class LayerNameEditor extends ComboBoxPropertyEditor { - - public LayerNameEditor() { - super(); - String[] names = (String[]) getLayerNames().toArray(new String[0]); - setAvailableValues(names); -// Icon[] icons = new Icon[4]; -// Arrays.fill(icons, UIManager.getIcon("Tree.openIcon")); -// setAvailableIcons(icons); - } - } - - public static class LayerUpdateTypeEditor extends ComboBoxPropertyEditor { - - public LayerUpdateTypeEditor() { - super(); - LayerUpdateTypes[] lutypes = LayerUpdateTypes.values(); - String[] types = new String[lutypes.length]; - int i = 0; - for (LayerUpdateTypes type : lutypes) { - types[i] = type.toString(); - i += 1; - } - setAvailableValues(types); - } - } - - public static class LegendStyleEditor extends ComboBoxPropertyEditor { - - public LegendStyleEditor() { - super(); - LegendStyles[] styles = LegendStyles.values(); - String[] values = new String[styles.length]; - int i = 0; - for (LegendStyles s : styles) { - values[i] = s.toString(); - i += 1; - } - setAvailableValues(values); - } - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.global.event.IMapViewUpdatedListener; +import org.meteoinfo.global.event.MapViewUpdatedEvent; +import org.meteoinfo.layer.LayerDrawType; +import org.meteoinfo.layer.LayerTypes; +import org.meteoinfo.layer.MapLayer; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.legend.ChartBreak; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.LegendScheme; +import org.meteoinfo.legend.LegendType; +import org.meteoinfo.legend.PointBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.legend.PolylineBreak; +import org.meteoinfo.shape.ShapeTypes; +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import org.meteoinfo.global.DataConvert; +import org.meteoinfo.legend.ChartTypes; + +/** + * + * @author Yaqiang Wang + */ +public class LayoutLegend extends LayoutElement { + // + + private MapLayout _mapLayout; + private static LayoutMap _layoutMap; + private MapLayer _legendLayer; + private boolean forceDrawOutline; + private boolean _isAntiAlias; + private LayerUpdateTypes _layerUpdateType; + private LegendStyles _legendStyle; + private String _title; + private Font _font; + private Font _titleFont; + private boolean _drawNeatLine; + private Color _neatLineColor; + private float _neatLineSize; + private float _breakSpace; + private float _topSpace; + private float _leftSpace; + private float _vBarWidth; + private float _hBarHeight; + private int _columnNum = 1; + private boolean drawChartBreaks = true; + private boolean drawPieLabel = false; + // + // + + /** + * Constructor + * + * @param mapLayout Map layout + * @param layoutMap Layout map + */ + public LayoutLegend(MapLayout mapLayout, LayoutMap layoutMap) { + super(); + this.setElementType(ElementType.LayoutLegend); + this.setResizeAbility(ResizeAbility.ResizeAll); + + _mapLayout = mapLayout; + _layoutMap = layoutMap; + _layoutMap.addMapViewUpdatedListener(new IMapViewUpdatedListener() { + @Override + public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { + onMapViewUpdated(event); + } + }); + _isAntiAlias = true; + this.forceDrawOutline = true; + _layerUpdateType = LayerUpdateTypes.FirstMeteoLayer; + _legendStyle = LegendStyles.Normal; + _title = ""; + _drawNeatLine = false; + _neatLineColor = Color.black; + _neatLineSize = 1; + _breakSpace = 3; + _topSpace = 5; + _leftSpace = 5; + _vBarWidth = 10; + _hBarHeight = 10; + _font = new Font("宋体", Font.PLAIN, 12); + _titleFont = new Font("Arial", Font.PLAIN, 12); + } + + // + // + public void onMapViewUpdated(MapViewUpdatedEvent e) { + if (_layoutMap.getMapFrame().getMapView().getLayerNum() == 0) { + return; + } + + switch (_layerUpdateType) { + case FirstExpandedLayer: + for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { + MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). + get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); + if (aLayer.hasLegendScheme()) { + if (aLayer.isVisible() && aLayer.isExpanded() && aLayer.getLegendScheme().getLegendType() != LegendType.SingleSymbol) { + this.setVisible(true); + this.setLegendLayer(aLayer); + break; + } + } + } + break; + case FirstMeteoLayer: + for (int i = 0; i < _layoutMap.getMapFrame().getMapView().getLayerNum(); i++) { + MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayers(). + get(_layoutMap.getMapFrame().getMapView().getLayerNum() - 1 - i); + if (aLayer.hasLegendScheme()) { + if (aLayer.isVisible() && aLayer.getLayerDrawType() != LayerDrawType.Map + && aLayer.getLegendScheme().getLegendType() != LegendType.SingleSymbol) { + this.setVisible(true); + this.setLegendLayer(aLayer); + break; + } + } + } + break; + case LastAddedLayer: + if (_layoutMap.getMapFrame().getMapView().getLastAddedLayer().hasLegendScheme()) { + this.setVisible(true); + this.setLegendLayer(_layoutMap.getMapFrame().getMapView().getLastAddedLayer()); + } + break; + } + + updateLegendSize(); + } + // + // + + /** + * Get layout map + * + * @return The layout map + */ + public LayoutMap getLayoutMap() { + return _layoutMap; + } + + /** + * Get legend layer + * + * @return The legend alyer + */ + public MapLayer getLegendLayer() { + return _legendLayer; + } + + /** + * Set legend layer + * + * @param layer The legend layer + */ + public void setLegendLayer(MapLayer layer) { + if (layer == null) { + return; + } + + _legendLayer = layer; + String aStr = _legendLayer.getLayerName(); + if (aStr.contains("_")) { + aStr = aStr.split("_")[1]; + } + _title = aStr; + updateLegendSize(); + } + + /** + * Get legend layer name + * + * @return Legend layer name + */ + public String getLayerName() { + if (_legendLayer != null) { + return _legendLayer.getLayerName(); + } else { + return ""; + } + } + + /** + * Set legend layer name + * + * @param name Layer name + */ + public void setLayerName(String name) { + MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayer(name); + if (aLayer != null) { + _legendLayer = aLayer; + } + } + + /** + * Get if force to draw polygon outline - for normal legend + * + * @return Boolean + */ + public boolean isForceDrawOutline() { + return this.forceDrawOutline; + } + + /** + * Set if force to draw polygon outline - for normal legend + * + * @param value Boolean + */ + public void setForceDrawOutline(boolean value) { + this.forceDrawOutline = value; + } + + /** + * Get layer update type + * + * @return Layer update type + */ + public LayerUpdateTypes getLayerUpdateType() { + return _layerUpdateType; + } + + /** + * Set layer update type + * + * @param type Layer update type + */ + public void setLayerUpdateType(LayerUpdateTypes type) { + _layerUpdateType = type; + } + + /** + * Get legend style + * + * @return Legend style + */ + public LegendStyles getLegendStyle() { + return _legendStyle; + } + + /** + * Set legend style + * + * @param style Legend style + */ + public void setLegendStyle(LegendStyles style) { + _legendStyle = style; + if (this.isVisible()) { + updateLegendSize(); + } + } + + /** + * Get title + * + * @return The title + */ + public String getTitle() { + return _title; + } + + /** + * Set title + * + * @param title The title + */ + public void setTitle(String title) { + _title = title; + updateLegendSize(); + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get font + * + * @return The font + */ + public Font getFont() { + return _font; + } + + /** + * Set font + * + * @param font The font + */ + public void setFont(Font font) { + _font = font; + _titleFont = new Font(_font.getFontName(), Font.PLAIN, _font.getSize() + 2); + updateLegendSize(); + } + + /** + * Get column number + * + * @return Column number + */ + public int getColumnNumber() { + return _columnNum; + } + + /** + * Set column number + * + * @param value Column number + */ + public void setColumnNumber(int value) { + _columnNum = value; + } + + /** + * Get if draw chart breaks + * + * @return Boolean + */ + public boolean isDrawChartBreaks() { + return this.drawChartBreaks; + } + + /** + * Set if draw chart breaks + * + * @param value Boolean + */ + public void setDrawChartBreaks(boolean value) { + this.drawChartBreaks = value; + } + + /** + * Get if draw pie label + * + * @return Boolean + */ + public boolean isDrawPieLabel() { + return this.drawPieLabel; + } + + /** + * Set if draw pie label + * + * @param value Boolean + */ + public void setDrawPieLabel(boolean value) { + this.drawPieLabel = value; + } + + // + // + /** + * Paint graphics + * + * @param g Graphics2D + * @param pageLocation Page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { + if (_legendLayer == null) { + return; + } + + if (_legendLayer.getLayerType() == LayerTypes.ImageLayer) { + return; + } + + AffineTransform oldMatrix = g.getTransform(); + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + g.translate(aP.X, aP.Y); + g.scale(zoom, zoom); + if (this._isAntiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()) { + g.setColor(this.getBackColor()); + g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); + } + + int gap = this.getTickGap(g); + switch (_legendStyle) { + case Bar_Horizontal: + if (gap > 1) { + drawHorizontalBarLegend_Ex(g, zoom); + } else { + drawHorizontalBarLegend(g, zoom); + } + break; + case Bar_Vertical: + if (gap > 1) { + drawVerticalBarLegend_Ex(g, zoom); + } else { + drawVerticalBarLegend(g, zoom); + } + break; + case Normal: + drawNormalLegend(g, zoom); + break; + } + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawChartLegend(Graphics2D g, float zoom, PointF aPoint, boolean drawBreaks) { + VectorLayer aLayer = (VectorLayer) _legendLayer; + ChartBreak aCB = ((ChartBreak) aLayer.getChartPoints().get(0).getLegend()).getSampleChartBreak(); + + //Draw chart symbol + aPoint.X = 5; + aPoint.Y += aCB.getHeight(); + switch (aCB.getChartType()) { + case BarChart: + Draw.drawBarChartSymbol(aPoint, aCB, g, true); + break; + case PieChart: + if (this.drawChartBreaks) { + Draw.drawPieChartSymbol(aPoint, aCB, g, null); + } else { + List rStrs = new ArrayList<>(); + for (int i = 0; i < aCB.getItemNum(); i++) { + rStrs.add(aCB.getLegendScheme().getLegendBreaks().get(i).getCaption()); + } + Draw.drawPieChartSymbol(aPoint, aCB, g, rStrs); + } + aPoint.Y += aCB.getHeight(); + break; + } + aPoint.Y += _breakSpace; + + //Draw breaks + if (drawBreaks) { + LegendScheme aLS = aCB.getLegendScheme(); + drawNormalLegend(g, zoom, aLS, aPoint, false); + } + } + + private void drawNormalLegend(Graphics2D g, float zoom) { + boolean drawChart = false; + if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { + if (((VectorLayer) _legendLayer).getChartSet().isDrawCharts()) { + drawChart = true; + } + } + + PointF aP = new PointF(0, 0); +// if (!drawChart) { +// LegendScheme aLS = _legendLayer.getLegendScheme(); +// drawNormalLegend(g, zoom, aLS, aP, true); +// float height = getBreakHeight(g) * zoom; +// aP.Y += height + _breakSpace; +// } + + LegendScheme aLS = _legendLayer.getLegendScheme(); + drawNormalLegend(g, zoom, aLS, aP, true); + float height = getBreakHeight(g) * zoom; + aP.Y += height + _breakSpace; + + //Draw chart legend + if (drawChart) { + drawChartLegend(g, zoom, aP, this.drawChartBreaks); + } + } + + private void drawNormalLegend(Graphics2D g, float zoom, LegendScheme aLS, PointF aP, boolean drawTitle) { + String caption = ""; + Dimension aSF; + float leftSpace = _leftSpace * zoom; + float topSpace = _topSpace * zoom; + float breakSpace = _breakSpace * zoom; + float height = getBreakHeight(g) * zoom; + float width = height * 2; + float colWidth = getBreakHeight(g) * 2 + getLabelWidth(g) + 10; + + //Draw title + if (drawTitle) { + Font tFont = new Font(_titleFont.getFontName(), _titleFont.getStyle(), (int) (_titleFont.getSize() * zoom)); + String Title = _title; + aP.X = leftSpace; + aP.Y = leftSpace; + FontMetrics metrics = g.getFontMetrics(tFont); + aSF = new Dimension(metrics.stringWidth(Title), metrics.getHeight()); + float titleHeight = aSF.height; + g.setColor(this.getForeColor()); + g.setFont(tFont); + g.drawString(_title, aP.X, aP.Y + aSF.height * 3 / 4); + aP.Y += titleHeight + breakSpace - height / 2; + } + + //Set columns + int[] rowNums = new int[_columnNum]; + int ave = aLS.getVisibleBreakNum() / _columnNum; + int num = 0; + int i; + for (i = 1; i < _columnNum; i++) { + rowNums[i] = ave; + num += ave; + } + rowNums[0] = aLS.getVisibleBreakNum() - num; + + //Draw legend + Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); + float sX = aP.X; + float sY = aP.Y; + i = 0; + for (int col = 0; col < _columnNum; col++) { + aP.X = width / 2 + leftSpace + col * colWidth; + aP.Y = sY; + for (int row = 0; row < rowNums[col]; row++) { + if (!aLS.getLegendBreaks().get(i).isDrawShape()) { + i += 1; + row -= 1; + continue; + } + + aP.Y += height + breakSpace; + //boolean isVisible = true; + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) ((PointBreak) aLS.getLegendBreaks().get(i)).clone(); + caption = aPB.getCaption(); + aPB.setSize(aPB.getSize() * zoom); + Draw.drawPoint((PointF) aP.clone(), aPB, g); + break; + case Polyline: + case PolylineZ: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); + caption = aPLB.getCaption(); + Draw.drawPolylineSymbol((PointF) aP.clone(), width, height, aPLB, g); + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); + caption = aPGB.getCaption(); + if (this.forceDrawOutline) { + aPGB = (PolygonBreak) aPGB.clone(); + aPGB.setDrawOutline(true); + } + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(i); + caption = aCB.getCaption(); + Draw.drawPolygonSymbol((PointF) aP.clone(), aCB.getColor(), Color.black, width, + height, true, true, g); + break; + } + + PointF sP = new PointF(0, 0); + sP.X = aP.X + width / 2; + sP.Y = aP.Y; + FontMetrics metrics = g.getFontMetrics(lFont); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(this.getForeColor()); + g.setFont(lFont); + //g.drawString(caption, sP.X + 5, sP.Y + aSF.height / 3); + g.drawString(caption, sP.X + 5, sP.Y + aSF.height / 4); + + i += 1; + } + } + } + + /** + * Update tick gap + * + * @param g Graphics2D + */ + private int getTickGap(Graphics2D g) { + double len; + int n = this._legendLayer.getLegendScheme().getBreakNum(); + int nn; + if (this.getLegendStyle() == LegendStyles.Bar_Horizontal) { + len = this.getWidth(); + int labLen = this.getLabelWidth(g); + nn = (int) ((len * 0.8) / labLen); + } else { + len = this.getHeight(); + FontMetrics metrics = g.getFontMetrics(this._font); + nn = (int) (len / metrics.getHeight()); + } + if (nn == 0) { + nn = 1; + } + return n / nn + 1; + } + + private void drawVerticalBarLegend(Graphics2D g, float zoom) { + LegendScheme aLS = _legendLayer.getLegendScheme(); + PointF aP = new PointF(0, 0); + PointF sP = new PointF(0, 0); + boolean DrawShape = true, DrawFill = true, DrawOutline = true; + Color FillColor = Color.red, OutlineColor = this.getForeColor(); + String caption = ""; + Dimension aSF; + + int bNum = aLS.getBreakNum(); + if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + + _vBarWidth = this.getWidth() - this.getLabelWidth(g) - 5; + float width = _vBarWidth * zoom; + float height = (this.getHeight() - 5) * zoom / bNum; + Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); + + boolean order = true; + if (aLS.getBreakNum() > 1) { + try { + double v1 = Double.parseDouble(aLS.getLegendBreaks().get(0).getEndValue().toString()); + double v2 = Double.parseDouble(aLS.getLegendBreaks().get(1).getEndValue().toString()); + if (v2 < v1) { + order = false; + } + } catch (Exception e) { + + } + } + + int idx; + for (int i = 0; i < bNum; i++) { + if (order) { + idx = bNum - i - 1; + } else { + idx = i; + } + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPB.isDrawShape(); + DrawFill = aPB.isDrawFill(); + FillColor = aPB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPB.getCaption(); + } else if (!order) { + caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); + } else { + caption = DataConvert.removeTailingZeros(aPB.getStartValue().toString()); + } + break; + case Polyline: + case PolylineZ: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPLB.getDrawPolyline(); + FillColor = aPLB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPLB.getCaption(); + } else if (!order) { + caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); + } else { + caption = DataConvert.removeTailingZeros(aPLB.getStartValue().toString()); + } + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPGB.isDrawShape(); + DrawFill = aPGB.isDrawFill(); + FillColor = aPGB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPGB.getCaption(); + } else if (!order) { + caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); + } else { + caption = DataConvert.removeTailingZeros(aPGB.getStartValue().toString()); + } + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(idx); + DrawShape = true; + DrawFill = true; + FillColor = aCB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aCB.getCaption(); + } else if (!order) { + caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); + } else { + caption = DataConvert.removeTailingZeros(aCB.getStartValue().toString()); + } + break; + } + + aP.X = width / 2; + aP.Y = i * height + height / 2; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (DrawShape) { + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + + sP.X = aP.X + width / 2 + 5; + sP.Y = aP.Y; + FontMetrics metrics = g.getFontMetrics(lFont); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(this.getForeColor()); + g.setFont(lFont); + g.drawString(caption, sP.X, sP.Y + aSF.height / 2); + } else { + if (DrawShape) { + if (i == 0) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = aP.X; + Points[0].Y = 0; + Points[1] = new PointF(); + Points[1].X = 0; + Points[1].Y = height; + Points[2] = new PointF(); + Points[2].X = width; + Points[2].Y = height; + Points[3] = new PointF(); + Points[3].X = aP.X; + Points[3].Y = 0; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (i == bNum - 1) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = 0; + Points[0].Y = i * height; + Points[1] = new PointF(); + Points[1].X = width; + Points[1].Y = i * height; + Points[2] = new PointF(); + Points[2].X = aP.X; + Points[2].Y = i * height + height; + Points[3] = new PointF(); + Points[3].X = 0; + Points[3].Y = i * height; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + + sP.X = aP.X + width / 2 + 5; + sP.Y = aP.Y + height / 2; + if (i < bNum - 1) { + FontMetrics metrics = g.getFontMetrics(lFont); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(this.getForeColor()); + g.setFont(lFont); + g.drawString(caption, sP.X, sP.Y + aSF.height / 2); + } + } + } + } + + private void drawVerticalBarLegend_Ex(Graphics2D g, float zoom) { + LegendScheme aLS = _legendLayer.getLegendScheme(); + PointF aP = new PointF(0, 0); + PointF sP = new PointF(0, 0); + boolean DrawShape = true, DrawFill = true, DrawOutline = false; + Color FillColor = Color.red, OutlineColor = this.getForeColor(); + String caption; + Dimension aSF; + + int bNum = aLS.getBreakNum(); + if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + + int tickGap = this.getTickGap(g); + List labelIdxs = new ArrayList<>(); + int sIdx = (bNum % tickGap) / 2; + int labNum = bNum - 1; + if (aLS.getLegendType() == LegendType.UniqueValue) { + labNum += 1; + } + while (sIdx < labNum) { + labelIdxs.add(sIdx); + sIdx += tickGap; + } + + _vBarWidth = this.getWidth() - this.getLabelWidth(g) - 5; + float width = _vBarWidth; + //float width = _vBarWidth * zoom; + _hBarHeight = (float) this.getHeight() / bNum; + float height = _hBarHeight; + //float height = (this.getHeight() - 5) * zoom / bNum; + //Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); + + boolean order = true; + if (aLS.getBreakNum() > 1) { + try { + double v1 = Double.parseDouble(aLS.getLegendBreaks().get(0).getEndValue().toString()); + double v2 = Double.parseDouble(aLS.getLegendBreaks().get(1).getEndValue().toString()); + if (v2 < v1) { + order = false; + } + } catch (Exception e) { + + } + } + int idx; + for (int i = 0; i < bNum; i++) { + if (order) { + idx = bNum - i - 1; + } else { + idx = i; + } + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPB.isDrawShape(); + DrawFill = aPB.isDrawFill(); + FillColor = aPB.getColor(); + break; + case Polyline: + case PolylineZ: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPLB.getDrawPolyline(); + FillColor = aPLB.getColor(); + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx); + DrawShape = aPGB.isDrawShape(); + DrawFill = aPGB.isDrawFill(); + FillColor = aPGB.getColor(); + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(idx); + DrawShape = true; + DrawFill = true; + FillColor = aCB.getColor(); + break; + } + + aP.X = width / 2; + aP.Y = i * height + height / 2; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (DrawShape) { + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + } else if (DrawShape) { + if (i == 0) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = aP.X; + Points[0].Y = 0; + Points[1] = new PointF(); + Points[1].X = 0; + Points[1].Y = height; + Points[2] = new PointF(); + Points[2].X = width; + Points[2].Y = height; + Points[3] = new PointF(); + Points[3].X = aP.X; + Points[3].Y = 0; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (i == bNum - 1) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = 0; + Points[0].Y = i * height; + Points[1] = new PointF(); + Points[1].X = width; + Points[1].Y = i * height; + Points[2] = new PointF(); + Points[2].X = aP.X; + Points[2].Y = i * height + height; + Points[3] = new PointF(); + Points[3].X = 0; + Points[3].Y = i * height; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(idx).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + } + + //Draw neatline + g.setColor(Color.black); + if (aLS.getLegendType() == LegendType.UniqueValue) { + g.draw(new Rectangle.Float(0, 0, this._vBarWidth, this._hBarHeight * bNum)); + } else { + Polygon p = new Polygon(); + p.addPoint((int) (width / 2), 0); + p.addPoint(0, (int) height); + p.addPoint(0, (int) (height * (bNum - 1))); + p.addPoint((int) (width / 2), (int) (height * bNum)); + p.addPoint((int) width, (int) (height * (bNum - 1))); + p.addPoint((int) width, (int) height); + g.drawPolygon(p); + } + //Draw ticks + aP.Y = this.getHeight() + _hBarHeight / 2; + int labLen = (int) (this._vBarWidth / 3); + if (labLen < 5) { + labLen = 5; + if (this._vBarWidth < 5) { + labLen = (int) this._vBarWidth; + } + } + + for (int i = 0; i < bNum; i++) { + if (order) { + idx = i; + } else { + idx = bNum - i - 1; + } + ColorBreak cb = aLS.getLegendBreaks().get(idx); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = cb.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(cb.getEndValue().toString()); + } + + aP.X = _vBarWidth / 2; + aP.Y = aP.Y - _hBarHeight; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (labelIdxs.contains(idx)) { + sP.X = aP.X + _vBarWidth / 2 + 5; + sP.Y = aP.Y; + FontMetrics metrics = g.getFontMetrics(this._font); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(Color.black); + g.setFont(this._font); + //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); + Draw.drawString(g, caption, sP.X, sP.Y + aSF.height / 4); + } + } else if (labelIdxs.contains(idx)) { + //g.setColor(Color.black); + sP.X = aP.X + _vBarWidth / 2; + sP.Y = aP.Y - _hBarHeight / 2; + g.draw(new Line2D.Float(sP.X - labLen, sP.Y, sP.X, sP.Y)); + sP.X = sP.X + 5; + if (i < bNum - 1) { + FontMetrics metrics = g.getFontMetrics(this._font); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setFont(this._font); + //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); + Draw.drawString(g, caption, sP.X, sP.Y + aSF.height / 4); + } + } + } + } + + private void drawHorizontalBarLegend(Graphics2D g, float zoom) { + LegendScheme aLS = _legendLayer.getLegendScheme(); + PointF aP = new PointF(0, 0); + PointF sP = new PointF(0, 0); + float width, height; + boolean DrawShape = true, DrawFill = true, DrawOutline = true; + Color FillColor = Color.red, OutlineColor = this.getForeColor(); + String caption = ""; + Dimension aSF; + + int bNum = aLS.getBreakNum(); + if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + + Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); + FontMetrics metrics = g.getFontMetrics(lFont); + _vBarWidth = this.getHeight() - metrics.getHeight() - 5; + width = (this.getWidth() - 5) * zoom / bNum; + height = _vBarWidth * zoom; + + for (int i = 0; i < bNum; i++) { + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPB.isDrawShape(); + DrawFill = aPB.isDrawFill(); + FillColor = aPB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPB.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); + } + break; + case Polyline: + case PolylineZ: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPLB.getDrawPolyline(); + FillColor = aPLB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPLB.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); + } + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPGB.isDrawShape(); + DrawFill = aPGB.isDrawFill(); + FillColor = aPGB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aPGB.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); + } + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(i); + DrawShape = true; + DrawFill = true; + FillColor = aCB.getColor(); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = aCB.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); + } + break; + } + + aP.X = i * width + width / 2; + aP.Y = height / 2; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (DrawShape) { + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + + sP.X = aP.X; + sP.Y = aP.Y + height / 2; + //FontMetrics metrics = g.getFontMetrics(lFont); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(this.getForeColor()); + g.setFont(lFont); + g.drawString(caption, sP.X - aSF.width / 2, sP.Y + aSF.height); + } else { + if (DrawShape) { + if (i == 0) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = 0; + Points[0].Y = aP.Y; + Points[1] = new PointF(); + Points[1].X = width; + Points[1].Y = 0; + Points[2] = new PointF(); + Points[2].X = width; + Points[2].Y = height; + Points[3] = new PointF(); + Points[3].X = 0; + Points[3].Y = aP.Y; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (i == bNum - 1) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = i * width; + Points[0].Y = height; + Points[1] = new PointF(); + Points[1].X = i * width; + Points[1].Y = 0; + Points[2] = new PointF(); + Points[2].X = i * width + width; + Points[2].Y = aP.Y; + Points[3] = new PointF(); + Points[3].X = i * width; + Points[3].Y = height; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(true); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + + sP.X = aP.X + width / 2; + sP.Y = aP.Y + height / 2; + if (i < bNum - 1) { + //FontMetrics metrics = g.getFontMetrics(lFont); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(this.getForeColor()); + g.setFont(lFont); + g.drawString(caption, sP.X - aSF.width / 2, sP.Y + aSF.height); + } + } + } + } + + private void drawHorizontalBarLegend_Ex(Graphics2D g, float zoom) { + LegendScheme aLS = _legendLayer.getLegendScheme(); + PointF aP = new PointF(0, 0); + PointF sP = new PointF(0, 0); + float width, height; + boolean DrawShape = true, DrawFill = true, DrawOutline = false; + Color FillColor = Color.red, OutlineColor = this.getForeColor(); + String caption = ""; + Dimension aSF; + + int bNum = aLS.getBreakNum(); + if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + + int tickGap = this.getTickGap(g); + List labelIdxs = new ArrayList<>(); + int sIdx = (bNum % tickGap) / 2; + int labNum = bNum - 1; + if (aLS.getLegendType() == LegendType.UniqueValue) { + labNum += 1; + } + while (sIdx < labNum) { + labelIdxs.add(sIdx); + sIdx += tickGap; + } + + Font lFont = new Font(this.getFont().getFontName(), this.getFont().getStyle(), (int) (this.getFont().getSize() * zoom)); + FontMetrics metrics = g.getFontMetrics(lFont); + _vBarWidth = this.getHeight() - metrics.getHeight() - 5; + //width = (this.getWidth() - 5) * zoom / bNum; + width = this.getWidth() / bNum; + //height = _vBarWidth * zoom; + height = _vBarWidth; + int idx; + for (int i = 0; i < bNum; i++) { + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPB.isDrawShape(); + DrawFill = aPB.isDrawFill(); + FillColor = aPB.getColor(); + break; + case Polyline: + case PolylineZ: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPLB.getDrawPolyline(); + FillColor = aPLB.getColor(); + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); + DrawShape = aPGB.isDrawShape(); + DrawFill = aPGB.isDrawFill(); + FillColor = aPGB.getColor(); + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(i); + DrawShape = true; + DrawFill = true; + FillColor = aCB.getColor(); + break; + } + + aP.X = i * width + width / 2; + aP.Y = height / 2; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (DrawShape) { + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + } else if (DrawShape) { + if (i == 0) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = 0; + Points[0].Y = aP.Y; + Points[1] = new PointF(); + Points[1].X = width; + Points[1].Y = 0; + Points[2] = new PointF(); + Points[2].X = width; + Points[2].Y = height; + Points[3] = new PointF(); + Points[3].X = 0; + Points[3].Y = aP.Y; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (i == bNum - 1) { + PointF[] Points = new PointF[4]; + Points[0] = new PointF(); + Points[0].X = i * width; + Points[0].Y = height; + Points[1] = new PointF(); + Points[1].X = i * width; + Points[1].Y = 0; + Points[2] = new PointF(); + Points[2].X = i * width + width; + Points[2].Y = aP.Y; + Points[3] = new PointF(); + Points[3].X = i * width; + Points[3].Y = height; + if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygon(Points, aPGB, g); + } else { + Draw.drawPolygon(Points, FillColor, OutlineColor, DrawFill, DrawOutline, g); + } + } else if (aLS.getShapeType() == ShapeTypes.Polygon) { + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i).clone(); + aPGB.setDrawOutline(DrawOutline); + aPGB.setOutlineColor(Color.black); + Draw.drawPolygonSymbol((PointF) aP.clone(), width, height, aPGB, g); + } else { + Draw.drawPolygonSymbol((PointF) aP.clone(), FillColor, OutlineColor, width, + height, DrawFill, DrawOutline, g); + } + } + } + + //Draw neatline + g.setColor(Color.black); + if (aLS.getLegendType() == LegendType.UniqueValue) { + g.draw(new Rectangle.Float(0, 0, width * bNum, height)); + } else { + float extendw = width; +// if (this.autoExtendFrac) +// extendw = _hBarHeight; + Polygon p = new Polygon(); + p.addPoint((int) (width - extendw), (int) (height / 2)); + p.addPoint((int) width, 0); + p.addPoint((int) (width * (bNum - 1)), 0); + p.addPoint((int) (width * (bNum - 1) + extendw), (int) (height / 2)); + p.addPoint((int) (width * (bNum - 1)), (int) height); + p.addPoint((int) width, (int) height); + g.drawPolygon(p); + } + //Draw tick and label + aP.X = -_vBarWidth / 2; + int labLen = (int) (this._hBarHeight / 3); + if (labLen < 5) { + labLen = 5; + if (this._hBarHeight < 5) { + labLen = (int) this._hBarHeight; + } + } + for (int i = 0; i < bNum; i++) { + idx = i; + ColorBreak cb = aLS.getLegendBreaks().get(idx); + if (aLS.getLegendType() == LegendType.UniqueValue) { + caption = cb.getCaption(); + } else { + caption = DataConvert.removeTailingZeros(cb.getEndValue().toString()); + } + + aP.X += width; + aP.Y = height / 2; + + if (aLS.getLegendType() == LegendType.UniqueValue) { + if (labelIdxs.contains(idx)) { + sP.X = aP.X; + sP.Y = aP.Y + height / 2 + 5; + metrics = g.getFontMetrics(this._font); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setColor(Color.black); + g.setFont(this._font); + //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); + Draw.drawString(g, caption, sP.X - aSF.width / 2, sP.Y + aSF.height * 3 / 4); + } + } else if (labelIdxs.contains(idx)) { + //g.setColor(Color.black); + sP.X = aP.X + _vBarWidth / 2; + sP.Y = aP.Y + height / 2; + g.draw(new Line2D.Float(sP.X, sP.Y, sP.X, sP.Y - labLen)); + sP.Y = sP.Y + 5; + if (i < bNum - 1) { + metrics = g.getFontMetrics(this._font); + aSF = new Dimension(metrics.stringWidth(caption), metrics.getHeight()); + g.setFont(this._font); + //g.drawString(caption, sP.X, sP.Y + aSF.height / 4); + Draw.drawString(g, caption, sP.X - aSF.width / 2, sP.Y + aSF.height * 3 / 4); + } + } + } + } + + private int getLabelWidth(Graphics2D g) { + LegendScheme aLS = _legendLayer.getLegendScheme(); + float width = 0; + String caption = ""; + Dimension aSF; + int bNum = aLS.getBreakNum(); + FontMetrics metrics = g.getFontMetrics(_font); + if (_legendStyle == LegendStyles.Normal) { + aSF = new Dimension(metrics.stringWidth(_title), metrics.getHeight()); + width = aSF.width; + } else if (aLS.getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + for (int i = 0; i < bNum; i++) { + switch (aLS.getShapeType()) { + case Point: + PointBreak aPB = (PointBreak) aLS.getLegendBreaks().get(i); + if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { + caption = DataConvert.removeTailingZeros(aPB.getEndValue().toString()); + } else { + caption = aPB.getCaption(); + } + break; + case Polyline: + PolylineBreak aPLB = (PolylineBreak) aLS.getLegendBreaks().get(i); + if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { + caption = DataConvert.removeTailingZeros(aPLB.getEndValue().toString()); + } else { + caption = aPLB.getCaption(); + } + break; + case Polygon: + PolygonBreak aPGB = (PolygonBreak) aLS.getLegendBreaks().get(i); + if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { + caption = DataConvert.removeTailingZeros(aPGB.getEndValue().toString()); + } else { + caption = aPGB.getCaption(); + } + break; + case Image: + ColorBreak aCB = aLS.getLegendBreaks().get(i); + if (aLS.getLegendType() == LegendType.GraduatedColor && _legendStyle != LegendStyles.Normal) { + caption = DataConvert.removeTailingZeros(aCB.getEndValue().toString()); + } else { + caption = aCB.getCaption(); + } + break; + } + + boolean isValid = true; + switch (aLS.getLegendType()) { + case GraduatedColor: + if (_legendStyle != LegendStyles.Normal) { + if (i == bNum - 1) { + isValid = false; + } + } + break; + } + if (isValid) { + float labwidth = metrics.stringWidth(caption); + if (width < labwidth) { + width = labwidth; + } + } + } + + if (_legendStyle == LegendStyles.Normal) { + if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { + if (((VectorLayer) _legendLayer).getChartSet().isDrawCharts()) { + ChartBreak aCB = ((ChartBreak) ((VectorLayer) _legendLayer).getChartPoints().get(0).getLegend()).getSampleChartBreak(); + if (aCB.getChartType() == ChartTypes.BarChart) { + LegendScheme ls = aCB.getLegendScheme(); + for (ColorBreak cb : ls.getLegendBreaks()) { + float labwidth = metrics.stringWidth(cb.getCaption()); + if (width < labwidth) { + width = metrics.stringWidth(cb.getCaption()); + } + } + } + } + } + } + + return (int) width; + } + + private int getBreakHeight(Graphics2D g) { + String title = _title; + if ("".equals(title.trim())) { + title = "Temp"; + } + + FontMetrics metrics = g.getFontMetrics(_font); + Dimension aSF = new Dimension(metrics.stringWidth(title), metrics.getHeight()); + return aSF.height; + } + + private int getTitleHeight(Graphics2D g) { + FontMetrics metrics = g.getFontMetrics(_titleFont); + Dimension aSF = new Dimension(metrics.stringWidth(_title), metrics.getHeight()); + return aSF.height; + } + + /** + * Update legend control size + */ + public void updateLegendSize() { + if (this._legendStyle != LegendStyles.Normal) { + return; + } + + if (_legendLayer != null) { + if (_legendLayer.getLegendScheme() == null) { + return; + } + + //Graphics2D g = (Graphics2D) _mapLayout.getGraphics(); + BufferedImage image = new BufferedImage(_mapLayout.getPageBounds().width, _mapLayout.getPageBounds().height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + int bNum = _legendLayer.getLegendScheme().getBreakNum(); + if (_legendLayer.getLegendScheme().getLegendBreaks().get(bNum - 1).isNoData()) { + bNum -= 1; + } + + int w = this.getWidth(); + int h = this.getHeight(); + int nw, nh; + switch (_legendStyle) { + case Bar_Vertical: + nw = 10 + getLabelWidth(g) + 5; + nh = bNum * 20; + if (nw > w) { + this.setWidth(nw); + } + if (nh > h) { + this.setHeight(bNum * 20); + } + break; + case Bar_Horizontal: + nw = bNum * 30; + nh = 30; + if (nw > w) { + this.setWidth(nw); + } + if (nh > h) { + this.setHeight(bNum * 20); + } + break; + case Normal: + int aHeight = getBreakHeight(g); + int colWidth = aHeight * 2 + getLabelWidth(g) + 15; + this.setWidth(colWidth * _columnNum); + + //Set columns + int[] rowNums = new int[_columnNum]; + int ave = _legendLayer.getLegendScheme().getVisibleBreakNum() / _columnNum; + int num = 0; + int i; + for (i = 1; i < _columnNum; i++) { + rowNums[i] = ave; + num += ave; + } + rowNums[0] = _legendLayer.getLegendScheme().getVisibleBreakNum() - num; + + this.setHeight((int) (rowNums[0] * (aHeight + _breakSpace) + + getTitleHeight(g) + _breakSpace * 2 + aHeight / 2 + 5)); + if (_legendLayer.getLayerType() == LayerTypes.VectorLayer) { + VectorLayer aLayer = (VectorLayer) _legendLayer; + if (aLayer.getChartSet().isDrawCharts()) { + ChartBreak aCB = ((ChartBreak) aLayer.getChartPoints().get(0).getLegend()).getSampleChartBreak(); + this.setHeight(this.getHeight() + (int) (_breakSpace * 2 + aCB.getHeight() + + aCB.getLegendScheme().getBreakNum() * (aHeight + _breakSpace) + aHeight / 2 + 5)); + } + } + break; + } + } + } + + @Override + public void paint(Graphics2D g) { + //throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (this.isVisible()) { + paintGraphics(g, pageLocation, zoom); + } + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + + /** + * Get layer names + * + * @return Layer names + */ + public static List getLayerNames() { + List layerNames = new ArrayList<>(); + for (MapLayer aLayer : _layoutMap.getMapFrame().getMapView().getLayers()) { + if (aLayer.getLayerType() == LayerTypes.VectorLayer || aLayer.getLayerType() == LayerTypes.RasterLayer) { + layerNames.add(aLayer.getLayerName()); + } + } + + return layerNames; + } + // + + // + public class LayoutLegendBean { + + LayoutLegendBean() { + } + + // + /** + * Get layout map + * + * @return The layout map + */ + public LayoutMap getLayoutMap() { + return _layoutMap; + } + + /** + * Get legend layer + * + * @return The legend alyer + */ + public MapLayer getLegendLayer() { + return _legendLayer; + } + + /** + * Set legend layer + * + * @param layer The legend layer + */ + public void setLegendLayer(MapLayer layer) { + _legendLayer = layer; + String aStr = _legendLayer.getLayerName(); + if (aStr.contains("_")) { + aStr = aStr.split("_")[1]; + } + _title = aStr; + updateLegendSize(); + } + + /** + * Get legend layer name + * + * @return Legend layer name + */ + public String getLayerName() { + if (_legendLayer != null) { + return _legendLayer.getLayerName(); + } else { + return null; + } + } + + /** + * Set legend layer name + * + * @param name Layer name + */ + public void setLayerName(String name) { + MapLayer aLayer = _layoutMap.getMapFrame().getMapView().getLayer(name); + if (aLayer != null) { + this.setLegendLayer(aLayer); + } + } + + /** + * Get if force to draw polygon outline - for normal legend + * + * @return Boolean + */ + public boolean isForceDrawOutline() { + return forceDrawOutline; + } + + /** + * Set if force to draw polygon outline - for normal legend + * + * @param value Boolean + */ + public void setForceDrawOutline(boolean value) { + forceDrawOutline = value; + } + + /** + * Get layer update type string + * + * @return Layer update type string + */ + public String getLayerUpdateType() { + return _layerUpdateType.toString(); + } + + /** + * Set layer update type + * + * @param typeStr Layer update type string + */ + public void setLayerUpdateType(String typeStr) { + _layerUpdateType = LayerUpdateTypes.valueOf(typeStr); + } + + /** + * Get legend style string + * + * @return Legend style string + */ + public String getLegendStyle() { + return _legendStyle.toString(); + } + + /** + * Set legend style + * + * @param style Legend style string + */ + public void setLegendStyle(String style) { + _legendStyle = LegendStyles.valueOf(style); + if (isVisible()) { + updateLegendSize(); + } + } + + /** + * Get title + * + * @return The title + */ + public String getTitle() { + return _title; + } + + /** + * Set title + * + * @param title The title + */ + public void setTitle(String title) { + _title = title; + updateLegendSize(); + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get font + * + * @return The font + */ + public Font getFont() { + return _font; + } + + /** + * Set font + * + * @param font The font + */ + public void setFont(Font font) { + _font = font; + _titleFont = new Font(_font.getFontName(), Font.PLAIN, _font.getSize() + 2); + updateLegendSize(); + } + + /** + * Get column number + * + * @return Column number + */ + public int getColumnNumber() { + return _columnNum; + } + + /** + * Set column number + * + * @param value Column number + */ + public void setColumnNumber(int value) { + _columnNum = value; + if (isVisible()) { + updateLegendSize(); + } + } + + /** + * Get is draw chart breaks + * + * @return Boolean + */ + public boolean isDrawChartBreaks() { + return drawChartBreaks; + } + + /** + * Set if draw chart breaks + * + * @param value Boolean + */ + public void setDrawChartBreaks(boolean value) { + drawChartBreaks = value; + } + + /** + * Get is draw backcolor + * + * @return Boolean + */ + public boolean isDrawBackColor() { + return LayoutLegend.this.isDrawBackColor(); + } + + /** + * Set is draw backcolor + * + * @param value Boolean + */ + public void setDrawBackColor(boolean value) { + LayoutLegend.this.setDrawBackColor(value); + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackColor() { + return LayoutLegend.this.getBackColor(); + } + + /** + * Set background color + * + * @param c Background color + */ + public void setBackColor(Color c) { + LayoutLegend.this.setBackColor(c); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeColor() { + return LayoutLegend.this.getForeColor(); + } + + /** + * Set foreground color + * + * @param c Foreground color + */ + public void setForeColor(Color c) { + LayoutLegend.this.setForeColor(c); + } + + /** + * Get left + * + * @return Left + */ + public int getLeft() { + return LayoutLegend.this.getLeft(); + } + + /** + * Set left + * + * @param left Left + */ + public void setLeft(int left) { + LayoutLegend.this.setLeft(left); + } + + /** + * Get top + * + * @return Top + */ + public int getTop() { + return LayoutLegend.this.getTop(); + } + + /** + * Set top + * + * @param top Top + */ + public void setTop(int top) { + LayoutLegend.this.setTop(top); + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return LayoutLegend.this.getWidth(); + } + + /** + * Set width + * + * @param value Width + */ + public void setWidth(int value) { + LayoutLegend.this.setWidth(value); + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return LayoutLegend.this.getHeight(); + } + + /** + * Set height + * + * @param value Height + */ + public void setHeight(int value) { + LayoutLegend.this.setHeight(value); + } + + /** + * Get bar width + * + * @return Bar width + */ + public float getBarWidth() { + return LayoutLegend.this._vBarWidth; + } + + /** + * Set bar width + * + * @param value Bar width + */ + public void setBarWidth(float value) { + LayoutLegend.this._vBarWidth = value; + } + // + } + + public static class LayoutLegendBeanBeanInfo extends BaseBeanInfo { + + public LayoutLegendBeanBeanInfo() { + super(LayoutLegendBean.class); + ExtendedPropertyDescriptor e = addProperty("layerName"); + e.setCategory("General").setPropertyEditorClass(LayerNameEditor.class); + e.setDisplayName("Layer Name"); + e.setShortDescription("The name of the layer of this legend"); + e = addProperty("layerUpdateType"); + e.setCategory("General").setDisplayName("Layer Update Type"); + e.setPropertyEditorClass(LayerUpdateTypeEditor.class); + e = addProperty("legendStyle"); + e.setCategory("General").setDisplayName("Legend Style"); + e.setPropertyEditorClass(LegendStyleEditor.class); + addProperty("title").setCategory("General").setDisplayName("Title"); + addProperty("font").setCategory("General").setDisplayName("Font"); + addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); + addProperty("backColor").setCategory("General").setDisplayName("Background"); + addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); + addProperty("columnNumber").setCategory("General").setDisplayName("Column Number"); + addProperty("forceDrawOutline").setCategory("General").setDisplayName("Force Draw Outline"); + addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); + addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); + addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); + addProperty("drawChartBreaks").setCategory("Chart").setDisplayName("Draw Chart Breaks"); + //addProperty("drawPieLabel").setCategory("Chart").setDisplayName("Draw Pie label"); + addProperty("left").setCategory("Location").setDisplayName("Left"); + addProperty("top").setCategory("Location").setDisplayName("Top"); + addProperty("width").setCategory("Location").setDisplayName("Width"); + addProperty("height").setCategory("Location").setDisplayName("Height"); + //addProperty("barWidth").setCategory("ColorBar").setDisplayName("Bar Width"); + } + } + + public static class LayerNameEditor extends ComboBoxPropertyEditor { + + public LayerNameEditor() { + super(); + String[] names = (String[]) getLayerNames().toArray(new String[0]); + setAvailableValues(names); +// Icon[] icons = new Icon[4]; +// Arrays.fill(icons, UIManager.getIcon("Tree.openIcon")); +// setAvailableIcons(icons); + } + } + + public static class LayerUpdateTypeEditor extends ComboBoxPropertyEditor { + + public LayerUpdateTypeEditor() { + super(); + LayerUpdateTypes[] lutypes = LayerUpdateTypes.values(); + String[] types = new String[lutypes.length]; + int i = 0; + for (LayerUpdateTypes type : lutypes) { + types[i] = type.toString(); + i += 1; + } + setAvailableValues(types); + } + } + + public static class LegendStyleEditor extends ComboBoxPropertyEditor { + + public LegendStyleEditor() { + super(); + LegendStyles[] styles = LegendStyles.values(); + String[] values = new String[styles.length]; + int i = 0; + for (LegendStyles s : styles) { + values[i] = s.toString(); + i += 1; + } + setAvailableValues(values); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutMap.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutMap.java index d933b3ee..d6816b72 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutMap.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutMap.java @@ -1,1548 +1,1548 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import org.meteoinfo.global.event.ILayersUpdatedListener; -import org.meteoinfo.global.event.IMapViewUpdatedListener; -import org.meteoinfo.global.event.LayersUpdatedEvent; -import org.meteoinfo.global.event.MapViewUpdatedEvent; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointF; -import org.meteoinfo.legend.GridLabelPosition; -import org.meteoinfo.legend.LineStyles; -import org.meteoinfo.legend.MapFrame; -import org.meteoinfo.map.GridLabel; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.Line2D; -import java.util.ArrayList; -import java.util.List; -import javax.swing.event.EventListenerList; -import org.meteoinfo.data.mapdata.webmap.TileLoadListener; - -/** - * - * @author yaqiang - */ -public class LayoutMap extends LayoutElement { - // - - public void addMapViewUpdatedListener(IMapViewUpdatedListener listener) { - this._listeners.add(IMapViewUpdatedListener.class, listener); - } - - public void removeMapViewUpdatedListener(IMapViewUpdatedListener listener) { - this._listeners.remove(IMapViewUpdatedListener.class, listener); - } - - public void fireMapViewUpdatedEvent() { - fireMapViewUpdatedEvent(new MapViewUpdatedEvent(this)); - } - - private void fireMapViewUpdatedEvent(MapViewUpdatedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == IMapViewUpdatedListener.class) { - ((IMapViewUpdatedListener) listeners[i + 1]).mapViewUpdatedEvent(event); - } - } - } - // - // - private EventListenerList _listeners = new EventListenerList(); - private MapFrame _mapFrame = null; - private boolean _drawDegreeSymbol = false; - private final TileLoadListener tileLoadListener; - // - // - - /** - * Constructor - * - * @param mapFrame MapFrame - * @param tll TileLoadListener - */ - public LayoutMap(MapFrame mapFrame, TileLoadListener tll) { - super(); - this.setElementType(ElementType.LayoutMap); - this.setResizeAbility(ResizeAbility.ResizeAll); - this.setMapFrame(mapFrame); - this.tileLoadListener = tll; - } - // - // - - public MapFrame getMapFrame() { - return _mapFrame; - } - - public void setMapFrame(MapFrame mf) { - _mapFrame = mf; - _mapFrame.addMapViewUpdatedListener(new IMapViewUpdatedListener() { - @Override - public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { - fireMapViewUpdatedEvent(); - } - }); - - _mapFrame.addLayersUpdatedListener(new ILayersUpdatedListener() { - @Override - public void layersUpdatedEvent(LayersUpdatedEvent event) { - fireMapViewUpdatedEvent(); - } - }); - } - - /** - * Get left - * - * @return Left - */ - @Override - public int getLeft() { - return _mapFrame.getLayoutBounds().x; - } - - /** - * Set left - * - * @param left Left - */ - @Override - public void setLeft(int left) { - _mapFrame.setLayoutBounds(new Rectangle(left, _mapFrame.getLayoutBounds().y, _mapFrame.getLayoutBounds().width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get top - * - * @return Top - */ - @Override - public int getTop() { - return _mapFrame.getLayoutBounds().y; - } - - /** - * Set top - * - * @param top Top - */ - @Override - public void setTop(int top) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, top, _mapFrame.getLayoutBounds().width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get width - * - * @return Width - */ - @Override - public int getWidth() { - return _mapFrame.getLayoutBounds().width; - } - - /** - * Set width - * - * @param width Width - */ - @Override - public void setWidth(int width) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get height - * - * @return Height - */ - @Override - public int getHeight() { - return _mapFrame.getLayoutBounds().height; - } - - /** - * Set height - * - * @param height Height - */ - @Override - public void setHeight(int height) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, - _mapFrame.getLayoutBounds().width, height)); - } - - /** - * Get bounds rectangle - * - * @return The bounds rectangle - */ - @Override - public Rectangle getBounds() { - return _mapFrame.getLayoutBounds(); - } - - /** - * Set bounds rectangle - * - * @param rect Bounds rectangle - */ - public void setBounds(Rectangle rect) { - _mapFrame.setLayoutBounds(rect); - } - - /** - * Get background color - * - * @return Background color - */ - @Override - public Color getBackColor() { - return _mapFrame.getBackColor(); - } - - /** - * Set background color - * - * @param color Background color - */ - @Override - public void setBackColor(Color color) { - _mapFrame.setBackColor(color); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - @Override - public Color getForeColor() { - return _mapFrame.getForeColor(); - } - - /** - * Set foreground color - * - * @param color - */ - @Override - public void setForeColor(Color color) { - _mapFrame.setForeColor(color); - } - - /** - * Get if draw map view neat line - * - * @return Boolean - */ - public boolean isDrawNeatLine() { - return _mapFrame.isDrawNeatLine(); - } - - /** - * Set if draw map view neat line - * - * @param istrue Boolean - */ - public void setDrawNeatLine(boolean istrue) { - _mapFrame.setDrawNeatLine(istrue); - } - - /** - * Get map view neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _mapFrame.getNeatLineColor(); - } - - /** - * Set map view neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _mapFrame.setNeatLineColor(color); - } - - /** - * Get map view neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _mapFrame.getNeatLineSize(); - } - - /** - * Set map view neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _mapFrame.setNeatLineSize(size); - } - - /** - * Get grid line color - * - * @return Grid line color - */ - public Color getGridLineColor() { - return _mapFrame.getGridLineColor(); - } - - /** - * Set grid line color - * - * @param color Grid line color - */ - public void setGridLineColor(Color color) { - _mapFrame.setGridLineColor(color); - } - - /** - * Get grid line size - * - * @return Grid line size - */ - public float getGridLineSize() { - return _mapFrame.getGridLineSize(); - } - - /** - * Set grid line size - * - * @param size Grid line size - */ - public void setGridLineSize(float size) { - _mapFrame.setGridLineSize(size); - } - - /** - * Get grid line style - * - * @return Grid line style - */ - public LineStyles getGridLineStyle() { - return _mapFrame.getGridLineStyle(); - } - - /** - * Set grid line style - * - * @param style Grid line style - */ - public void setGridLineStyle(LineStyles style) { - _mapFrame.setGridLineStyle(style); - } - - /** - * Get if draw grid labels - * - * @return If draw grid labels - */ - public boolean isDrawGridLabel() { - return _mapFrame.isDrawGridLabel(); - } - - /** - * Set if draw grid labels - * - * @param istrue Boolean - */ - public void setDrawGridLabel(boolean istrue) { - _mapFrame.setDrawGridLabel(istrue); - } - - /** - * Get if draw grid tick line inside - * - * @return Booelan - */ - public boolean isInsideTickLine() { - return _mapFrame.isInsideTickLine(); - } - - /** - * Set if draw grid tick line inside - * - * @param istrue Boolean - */ - public void setInsideTickLine(boolean istrue) { - _mapFrame.setInsideTickLine(istrue); - } - - /** - * Get grid tick line length - * - * @return Grid tick line length - */ - public int getTickLineLength() { - return _mapFrame.getTickLineLength(); - } - - /** - * Set grid tick line length - * - * @param value Tick line length value - */ - public void setTickLineLength(int value) { - _mapFrame.setTickLineLength(value); - } - - /** - * Get grid label shift - * - * @return Grid label shift - */ - public int getGridLabelShift() { - return _mapFrame.getGridLabelShift(); - } - - /** - * Set grid label shift - * - * @param value Grid label shift - */ - public void setGridLabelShift(int value) { - _mapFrame.setGridLabelShift(value); - } - - ///

- /// Get or set grid label position - /** - * Get grid label position - * - * @return Grid label position - */ - public GridLabelPosition getGridLabelPosition() { - return _mapFrame.getGridLabelPosition(); - } - - /** - * Set grid label positiont - * - * @param value Grid label position - */ - public void setGridLabelPosition(GridLabelPosition value) { - _mapFrame.setGridLabelPosition(value); - } - - /** - * Get if draw grid line - * - * @return If draw grid line - */ - public boolean isDrawGridLine() { - return _mapFrame.isDrawGridLine(); - } - - /** - * Set if draw grid line - * - * @param istrue If draw grid line - */ - public void setDrawGridLine(boolean istrue) { - _mapFrame.setDrawGridLine(istrue); - } - - /** - * Get if draw grid tick line - * - * @return Boolean - */ - public boolean isDrawGridTickLine() { - return _mapFrame.isDrawGridTickLine(); - } - - /** - * Set if draw grid tick line - * - * @param istrue Boolean - */ - public void setDrawGridTickLine(boolean istrue) { - _mapFrame.setDrawGridTickLine(istrue); - } - - /** - * Get if draw degree symbol - * - * @return Boolean - */ - public boolean isDrawDegreeSymbol() { - return _drawDegreeSymbol; - } - - /** - * Set if draw degree symbol - * - * @param value Boolean - */ - public void setDrawDegreeSymbol(boolean value) { - _drawDegreeSymbol = value; - } - - /** - * Get grid label font - * - * @return Grid label font - */ - public Font getGridFont() { - return _mapFrame.getGridFont(); - } - - /** - * Set grid label font - * - * @param font Grid label font - */ - public void setGridFont(Font font) { - _mapFrame.setGridFont(font); - } - - /** - * Get grid x delt - * - * @return Grid x delt - */ - public double getGridXDelt() { - return _mapFrame.getGridXDelt(); - } - - /** - * Set grid x delt - * - * @param value The value - */ - public void setGridXDelt(double value) { - _mapFrame.setGridXDelt(value); - } - - /** - * Get grid y delt - * - * @return Grid y delt - */ - public double getGridYDelt() { - return _mapFrame.getGridYDelt(); - } - - /** - * Set grid y delt - * - * @param value Grid y delt - */ - public void setGridYDelt(double value) { - _mapFrame.setGridYDelt(value); - } - - /** - * Get grid x origin - * - * @return Grid x origin - */ - public float getGridXOrigin() { - return _mapFrame.getGridXOrigin(); - } - - /** - * Set grid x origin - * - * @param value Grid x origin - */ - public void setGridXOrigin(float value) { - _mapFrame.setGridXOrigin(value); - } - - /** - * Get grid y origin - * - * @return Grid y origin - */ - public float getGridYOrigin() { - return _mapFrame.getGridYOrigin(); - } - - /** - * Set grid y origin - * - * @param value Grid y origin - */ - public void setGridYOrigin(float value) { - _mapFrame.setGridYOrigin(value); - } - - // - // - /** - * Zoom to exactly lon/lat extent - * - * @param aExtent The lon/lat extent - */ - public void zoomToExtentLonLatEx(Extent aExtent) { - if (!_mapFrame.getMapView().getProjection().isLonLatMap()) { - aExtent = _mapFrame.getMapView().getProjection().getProjectedExtentFromLonLat(aExtent); - } - - setSizeByExtent(aExtent); - _mapFrame.getMapView().setViewExtent(aExtent); - } - - private void setSizeByExtent(Extent aExtent) { - double scaleFactor; - - double scaleX = this.getWidth() / (aExtent.maxX - aExtent.minX); - double scaleY = this.getHeight() / (aExtent.maxY - aExtent.minY); - if (_mapFrame.getMapView().getProjection().isLonLatMap()) { - scaleFactor = _mapFrame.getMapView().getXYScaleFactor(); - } else { - scaleFactor = 1; - } - - if (scaleX > scaleY) { - scaleX = scaleY / scaleFactor; - this.setWidth((int) ((aExtent.maxX - aExtent.minX) * scaleX)); - } else { - scaleY = scaleX * scaleFactor; - this.setHeight((int) ((aExtent.maxY - aExtent.minY) * scaleY)); - } - } - - /** - * Paint method - * - * @param g Graphics2D - */ - @Override - public void paint(Graphics2D g) { - if (_mapFrame != null) { - g.setColor(_mapFrame.getMapView().getBackground()); - g.fill(_mapFrame.getLayoutBounds()); - - _mapFrame.getMapView().paintGraphics(g, _mapFrame.getLayoutBounds(), this.tileLoadListener); - -// //Draw lon/lat grid labels -// if (_mapFrame.getDrawGridLabel()) -// { -// List extentList = new ArrayList(); -// Extent maxExtent = new Extent(); -// Extent aExtent = new Extent(); -// SizeF aSF = new SizeF(); -// SolidBrush aBrush = new SolidBrush(this.ForeColor); -// Pen aPen = new Pen(_mapFrame.GridLineColor); -// aPen.Width = _mapFrame.GridLineSize; -// String drawStr; -// PointF sP = new PointF(0, 0); -// PointF eP = new PointF(0, 0); -// Font font = new Font(_mapFrame.getGridFont().Name, _mapFrame.getGridFont().Size, _mapFrame.getGridFont().Style); -// float labX, labY; -// int len = 5; -// int space = len + 2; -// for (int i = 0; i < _mapFrame.getMapView().getGridLabels().Count; i++) -// { -// GridLabel aGL = _mapFrame.getMapView().getGridLabels()[i]; -// switch (_mapFrame.getGridLabelPosition()) -// { -// case GridLabelPosition.LeftBottom: -// switch (aGL.LabDirection) -// { -// case Direction.East: -// case Direction.North: -// continue; -// } -// break; -// case GridLabelPosition.LeftUp: -// switch (aGL.LabDirection) -// { -// case Direction.East: -// case Direction.South: -// continue; -// } -// break; -// case GridLabelPosition.RightBottom: -// switch (aGL.LabDirection) -// { -// case Direction.Weast: -// case Direction.North: -// continue; -// } -// break; -// case GridLabelPosition.RightUp: -// switch (aGL.LabDirection) -// { -// case Direction.Weast: -// case Direction.South: -// continue; -// } -// break; -// } -// -// labX = (float)aGL.LabPoint.X; -// labY = (float)aGL.LabPoint.Y; -// labX = labX + this.Left; -// labY = labY + this.Top; -// sP.X = labX; -// sP.Y = labY; -// -// drawStr = aGL.LabString; -// aSF = g.MeasureString(drawStr, font); -// switch (aGL.LabDirection) -// { -// case Direction.South: -// labX = labX - aSF.Width / 2; -// labY = labY + space; -// eP.X = sP.X; -// eP.Y = sP.Y + len; -// break; -// case Direction.Weast: -// labX = labX - aSF.Width - space; -// labY = labY - aSF.Height / 2; -// eP.X = sP.X - len; -// eP.Y = sP.Y; -// break; -// case Direction.North: -// labX = labX - aSF.Width / 2; -// labY = labY - aSF.Height - space; -// eP.X = sP.X; -// eP.Y = sP.Y - len; -// break; -// case Direction.East: -// labX = labX + space; -// labY = labY - aSF.Height / 2; -// eP.X = sP.X + len; -// eP.Y = sP.Y; -// break; -// } -// -// bool ifDraw = true; -// float aSize = aSF.Width / 2; -// float bSize = aSF.Height / 2; -// aExtent.minX = labX; -// aExtent.maxX = labX + aSF.Width; -// aExtent.minY = labY - aSF.Height; -// aExtent.maxY = labY; -// -// //Judge extent -// if (extentList.Count == 0) -// { -// maxExtent = aExtent; -// extentList.Add(aExtent); -// } -// else -// { -// if (!MIMath.IsExtentCross(aExtent, maxExtent)) -// { -// extentList.Add(aExtent); -// maxExtent = MIMath.GetLagerExtent(maxExtent, aExtent); -// } -// else -// { -// for (int j = 0; j < extentList.Count; j++) -// { -// if (MIMath.IsExtentCross(aExtent, extentList[j])) -// { -// ifDraw = false; -// break; -// } -// } -// if (ifDraw) -// { -// extentList.Add(aExtent); -// maxExtent = MIMath.GetLagerExtent(maxExtent, aExtent); -// } -// } -// } -// -// if (ifDraw) -// { -// g.DrawLine(aPen, sP, eP); -// g.DrawString(drawStr, font, aBrush, labX, labY); -// } -// } -// } - if (_mapFrame.isDrawNeatLine()) { - g.setColor(_mapFrame.getNeatLineColor()); - g.setStroke(new BasicStroke(_mapFrame.getNeatLineSize())); - g.draw(_mapFrame.getLayoutBounds()); - } - } - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (_mapFrame != null) { - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - Rectangle rect = new Rectangle((int) aP.X, (int) aP.Y, (int) (this.getWidth() * zoom), (int) (this.getHeight() * zoom)); - //g.setColor(_mapFrame.getMapView().getBackground()); - //g.fill(rect); - - _mapFrame.getMapView().paintGraphics(g, rect, this.tileLoadListener); - - //Draw lon/lat grid labels - if (_mapFrame.isDrawGridLabel()) { - List extentList = new ArrayList<>(); - Extent maxExtent = new Extent(); - Extent aExtent; - Dimension aSF; - g.setColor(_mapFrame.getGridLineColor()); - g.setStroke(new BasicStroke(_mapFrame.getGridLineSize())); - String drawStr; - PointF sP = new PointF(0, 0); - PointF eP = new PointF(0, 0); - Font font = new Font(_mapFrame.getGridFont().getFontName(), _mapFrame.getGridFont().getStyle(), (int) (_mapFrame.getGridFont().getSize() * zoom)); - g.setFont(font); - float labX, labY; - int len = _mapFrame.getTickLineLength(); - int space = len + _mapFrame.getGridLabelShift(); - if (_mapFrame.isInsideTickLine()) { - space = _mapFrame.getGridLabelShift(); - } - - for (int i = 0; i < _mapFrame.getMapView().getGridLabels().size(); i++) { - GridLabel aGL = _mapFrame.getMapView().getGridLabels().get(i); - switch (_mapFrame.getGridLabelPosition()) { - case LEFT_BOTTOM: - switch (aGL.getLabDirection()) { - case East: - case North: - continue; - } - break; - case LEFT_UP: - switch (aGL.getLabDirection()) { - case East: - case South: - continue; - } - break; - case RIGHT_BOTTOM: - switch (aGL.getLabDirection()) { - case Weast: - case North: - continue; - } - break; - case RIGHT_UP: - switch (aGL.getLabDirection()) { - case Weast: - case South: - continue; - } - break; - } - - labX = (float) aGL.getLabPoint().X; - labY = (float) aGL.getLabPoint().Y; - labX = labX + this.getLeft() * zoom + pageLocation.X; - labY = labY + this.getTop() * zoom + pageLocation.Y; - sP.X = labX; - sP.Y = labY; - - drawStr = aGL.getLabString(); - if (_drawDegreeSymbol) { - if (drawStr.endsWith("E") || drawStr.endsWith("W") || drawStr.endsWith("N") || drawStr.endsWith("S")) { - drawStr = drawStr.substring(0, drawStr.length() - 1) + String.valueOf((char) 186) + drawStr.substring(drawStr.length() - 1); - } else { - drawStr = drawStr + String.valueOf((char) 186); - } - } - FontMetrics metrics = g.getFontMetrics(font); - aSF = new Dimension(metrics.stringWidth(drawStr), metrics.getHeight()); - switch (aGL.getLabDirection()) { - case South: - labX = labX - aSF.width / 2; - labY = labY + aSF.height * 3 / 4 + space; - eP.X = sP.X; - if (_mapFrame.isInsideTickLine()) { - eP.Y = sP.Y - len; - } else { - eP.Y = sP.Y + len; - } - break; - case Weast: - labX = labX - aSF.width - space; - labY = labY + aSF.height / 3; - eP.Y = sP.Y; - if (_mapFrame.isInsideTickLine()) { - eP.X = sP.X + len; - } else { - eP.X = sP.X - len; - } - break; - case North: - labX = labX - aSF.width / 2; - //labY = labY - aSF.height / 3 - space; - labY = labY - space; - eP.X = sP.X; - if (_mapFrame.isInsideTickLine()) { - eP.Y = sP.Y + len; - } else { - eP.Y = sP.Y - len; - } - break; - case East: - labX = labX + space; - labY = labY + aSF.height / 3; - eP.Y = sP.Y; - if (_mapFrame.isInsideTickLine()) { - eP.X = sP.X - len; - } else { - eP.X = sP.X + len; - } - break; - } - - boolean ifDraw = true; - float aSize = aSF.width / 2; - float bSize = aSF.height / 2; - aExtent = new Extent(); - aExtent.minX = labX; - aExtent.maxX = labX + aSF.width; - aExtent.minY = labY - aSF.height; - aExtent.maxY = labY; - - //Judge extent - if (extentList.isEmpty()) { - maxExtent = (Extent) aExtent.clone(); - extentList.add((Extent) aExtent.clone()); - } else { - if (!MIMath.isExtentCross(aExtent, maxExtent)) { - extentList.add((Extent) aExtent.clone()); - maxExtent = MIMath.getLagerExtent(maxExtent, aExtent); - } else { - for (int j = 0; j < extentList.size(); j++) { - if (MIMath.isExtentCross(aExtent, extentList.get(j))) { - ifDraw = false; - break; - } - } - if (ifDraw) { - extentList.add(aExtent); - maxExtent = MIMath.getLagerExtent(maxExtent, aExtent); - } - } - } - - if (ifDraw) { - g.setColor(_mapFrame.getGridLineColor()); - g.draw(new Line2D.Float(sP.X, sP.Y, eP.X, eP.Y)); - g.setColor(this.getForeColor()); - g.drawString(drawStr, labX, labY); - } - } - } - - //Draw neat line - if (_mapFrame.isDrawNeatLine()) { - g.setColor(_mapFrame.getNeatLineColor()); - g.setStroke(new BasicStroke(_mapFrame.getNeatLineSize())); - g.draw(rect); - } - } - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // - // - - public class LayoutMapBean { - - LayoutMapBean() { - } - // - - /** - * Get left - * - * @return Left - */ - public int getLeft() { - return _mapFrame.getLayoutBounds().x; - } - - /** - * Set left - * - * @param left Left - */ - public void setLeft(int left) { - _mapFrame.setLayoutBounds(new Rectangle(left, _mapFrame.getLayoutBounds().y, _mapFrame.getLayoutBounds().width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get top - * - * @return Top - */ - public int getTop() { - return _mapFrame.getLayoutBounds().y; - } - - /** - * Set top - * - * @param top Top - */ - public void setTop(int top) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, top, _mapFrame.getLayoutBounds().width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return _mapFrame.getLayoutBounds().width; - } - - /** - * Set width - * - * @param width Width - */ - public void setWidth(int width) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, width, - _mapFrame.getLayoutBounds().height)); - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return _mapFrame.getLayoutBounds().height; - } - - /** - * Set height - * - * @param height Height - */ - public void setHeight(int height) { - _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, - _mapFrame.getLayoutBounds().width, height)); - } - - /** - * Get bounds rectangle - * - * @return The bounds rectangle - */ - public Rectangle getBounds() { - return _mapFrame.getLayoutBounds(); - } - - /** - * Set bounds rectangle - * - * @param rect Bounds rectangle - */ - public void setBounds(Rectangle rect) { - _mapFrame.setLayoutBounds(rect); - } - - /** - * Get is draw backcolor - * - * @return Boolean - */ - public boolean isDrawBackColor() { - return LayoutMap.this.isDrawBackColor(); - } - - /** - * Set is draw backcolor - * - * @param value Boolean - */ - public void setDrawBackColor(boolean value) { - LayoutMap.this.setDrawBackColor(value); - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackColor() { - return _mapFrame.getBackColor(); - } - - /** - * Set background color - * - * @param color Background color - */ - public void setBackColor(Color color) { - _mapFrame.setBackColor(color); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeColor() { - return _mapFrame.getForeColor(); - } - - /** - * Set foreground color - * - * @param color - */ - public void setForeColor(Color color) { - _mapFrame.setForeColor(color); - } - - /** - * Get if draw map view neat line - * - * @return Boolean - */ - public boolean isDrawNeatLine() { - return _mapFrame.isDrawNeatLine(); - } - - /** - * Set if draw map view neat line - * - * @param istrue Boolean - */ - public void setDrawNeatLine(boolean istrue) { - _mapFrame.setDrawNeatLine(istrue); - } - - /** - * Get map view neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _mapFrame.getNeatLineColor(); - } - - /** - * Set map view neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _mapFrame.setNeatLineColor(color); - } - - /** - * Get map view neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _mapFrame.getNeatLineSize(); - } - - /** - * Set map view neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _mapFrame.setNeatLineSize(size); - } - - /** - * Get grid line color - * - * @return Grid line color - */ - public Color getGridLineColor() { - return _mapFrame.getGridLineColor(); - } - - /** - * Set grid line color - * - * @param color Grid line color - */ - public void setGridLineColor(Color color) { - _mapFrame.setGridLineColor(color); - } - - /** - * Get grid line size - * - * @return Grid line size - */ - public float getGridLineSize() { - return _mapFrame.getGridLineSize(); - } - - /** - * Set grid line size - * - * @param size Grid line size - */ - public void setGridLineSize(float size) { - _mapFrame.setGridLineSize(size); - } - - /** - * Get grid line style - * - * @return Grid line style - */ - public String getGridLineStyle() { - return _mapFrame.getGridLineStyle().toString(); - } - - /** - * Set grid line style - * - * @param style Grid line style - */ - public void setGridLineStyle(String style) { - _mapFrame.setGridLineStyle(LineStyles.valueOf(style)); - } - - /** - * Get if draw grid labels - * - * @return If draw grid labels - */ - public boolean isDrawGridLabel() { - return _mapFrame.isDrawGridLabel(); - } - - /** - * Set if draw grid labels - * - * @param istrue Boolean - */ - public void setDrawGridLabel(boolean istrue) { - _mapFrame.setDrawGridLabel(istrue); - } - - /** - * Get if draw grid tick line inside - * - * @return Booelan - */ - public boolean isInsideTickLine() { - return _mapFrame.isInsideTickLine(); - } - - /** - * Set if draw grid tick line inside - * - * @param istrue Boolean - */ - public void setInsideTickLine(boolean istrue) { - _mapFrame.setInsideTickLine(istrue); - } - - /** - * Get grid tick line length - * - * @return Grid tick line length - */ - public int getTickLineLength() { - return _mapFrame.getTickLineLength(); - } - - /** - * Set grid tick line length - * - * @param value tick line length - */ - public void setTickLineLength(int value) { - _mapFrame.setTickLineLength(value); - } - - /** - * Get grid label shift - * - * @return Grid label shift - */ - public int getGridLabelShift() { - return _mapFrame.getGridLabelShift(); - } - - /** - * Set grid label shift - * - * @param value Grid label shift - */ - public void setGridLabelShift(int value) { - _mapFrame.setGridLabelShift(value); - } - - /// - /// Get or set grid label position - /** - * Get grid label position - * - * @return Grid label position - */ - public String getGridLabelPosition() { - return _mapFrame.getGridLabelPosition().toString(); - } - - /** - * Set grid label positiont - * - * @param value Grid label position - */ - public void setGridLabelPosition(String value) { - _mapFrame.setGridLabelPosition(GridLabelPosition.valueOf(value)); - } - - /** - * Get if draw grid line - * - * @return If draw grid line - */ - public boolean isDrawGridLine() { - return _mapFrame.isDrawGridLine(); - } - - /** - * Set if draw grid line - * - * @param istrue If draw grid line - */ - public void setDrawGridLine(boolean istrue) { - _mapFrame.setDrawGridLine(istrue); - } - - /** - * Get if draw grid tick line - * - * @return Boolean - */ - public boolean isDrawGridTickLine() { - return _mapFrame.isDrawGridTickLine(); - } - - /** - * Set if draw grid tick line - * - * @param istrue Boolean - */ - public void setDrawGridTickLine(boolean istrue) { - _mapFrame.setDrawGridTickLine(istrue); - } - - /** - * Get if draw degree symbol - * - * @return Boolean - */ - public boolean isDrawDegreeSymbol() { - return _drawDegreeSymbol; - } - - /** - * Set if draw degree symbol - * - * @param value Boolean - */ - public void setDrawDegreeSymbol(boolean value) { - _drawDegreeSymbol = value; - } - - /** - * Get grid label font - * - * @return Grid label font - */ - public Font getGridFont() { - return _mapFrame.getGridFont(); - } - - /** - * Set grid label font - * - * @param font Grid label font - */ - public void setGridFont(Font font) { - _mapFrame.setGridFont(font); - } - - /** - * Get grid x delt - * - * @return Grid x delt - */ - public double getGridXDelt() { - return _mapFrame.getGridXDelt(); - } - - /** - * Set grid x delt - * - * @param value The value - */ - public void setGridXDelt(double value) { - _mapFrame.setGridXDelt(value); - } - - /** - * Get grid y delt - * - * @return Grid y delt - */ - public double getGridYDelt() { - return _mapFrame.getGridYDelt(); - } - - /** - * Set grid y delt - * - * @param value Grid y delt - */ - public void setGridYDelt(double value) { - _mapFrame.setGridYDelt(value); - } - - /** - * Get grid x origin - * - * @return Grid x origin - */ - public float getGridXOrigin() { - return _mapFrame.getGridXOrigin(); - } - - /** - * Set grid x origin - * - * @param value Grid x origin - */ - public void setGridXOrigin(float value) { - _mapFrame.setGridXOrigin(value); - } - - /** - * Get grid y origin - * - * @return Grid y origin - */ - public float getGridYOrigin() { - return _mapFrame.getGridYOrigin(); - } - - /** - * Set grid y origin - * - * @param value Grid y origin - */ - public void setGridYOrigin(float value) { - _mapFrame.setGridYOrigin(value); - } - // - } - - public static class LayoutMapBeanBeanInfo extends BaseBeanInfo { - - public LayoutMapBeanBeanInfo() { - super(LayoutMapBean.class); - addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); - addProperty("backColor").setCategory("General").setDisplayName("Background"); - addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); - addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); - addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); - addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); - addProperty("drawGridLine").setCategory("Grid Line").setDisplayName("Draw Grid Line"); - addProperty("drawGridLabel").setCategory("Grid Line").setDisplayName("Draw Grid Label"); - addProperty("gridXDelt").setCategory("Grid Line").setDisplayName("Grid X Interval"); - addProperty("gridYDelt").setCategory("Grid Line").setDisplayName("Grid Y Interval"); - addProperty("gridXOrigin").setCategory("Grid Line").setDisplayName("Grid X Origin"); - addProperty("gridYOrigin").setCategory("Grid Line").setDisplayName("Grid Y Origin"); - addProperty("gridFont").setCategory("Grid Line").setDisplayName("Grid Label Font"); - addProperty("gridLabelShift").setCategory("Grid Line").setDisplayName("Grid Label Shift"); - ExtendedPropertyDescriptor e = addProperty("gridLabelPosition"); - e.setCategory("Grid Line").setDisplayName("Grid Label Position"); - e.setPropertyEditorClass(GridLabelPositionEditor.class); - addProperty("drawDegreeSymbol").setCategory("Grid Line").setDisplayName("Draw Degree Symbol"); - addProperty("gridLineColor").setCategory("Grid Line").setDisplayName("Grid Line Color"); - addProperty("gridLineSize").setCategory("Grid Line").setDisplayName("Grid Line Size"); - e = addProperty("gridLineStyle"); - e.setCategory("Grid Line").setDisplayName("Grid Line Style"); - e.setPropertyEditorClass(LineStyleEditor.class); - addProperty("insideTickLine").setCategory("Grid Line").setDisplayName("Inside Tick Line"); - addProperty("tickLineLength").setCategory("Grid Line").setDisplayName("Tick Line Length"); - addProperty("left").setCategory("Location").setDisplayName("Left"); - addProperty("top").setCategory("Location").setDisplayName("Top"); - addProperty("width").setCategory("Location").setDisplayName("Width"); - addProperty("height").setCategory("Location").setDisplayName("Height"); - } - } - - public static class GridLabelPositionEditor extends ComboBoxPropertyEditor { - - public GridLabelPositionEditor() { - super(); - GridLabelPosition[] lutypes = GridLabelPosition.values(); - String[] types = new String[lutypes.length]; - int i = 0; - for (GridLabelPosition type : lutypes) { - types[i] = type.toString(); - i += 1; - } - setAvailableValues(types); - } - } - - public static class LineStyleEditor extends ComboBoxPropertyEditor { - - public LineStyleEditor() { - super(); - LineStyles[] lutypes = LineStyles.values(); - String[] types = new String[lutypes.length]; - int i = 0; - for (LineStyles type : lutypes) { - types[i] = type.toString(); - i += 1; - } - setAvailableValues(types); - } - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointF; +import org.meteoinfo.global.event.ILayersUpdatedListener; +import org.meteoinfo.global.event.IMapViewUpdatedListener; +import org.meteoinfo.global.event.LayersUpdatedEvent; +import org.meteoinfo.global.event.MapViewUpdatedEvent; +import org.meteoinfo.legend.GridLabelPosition; +import org.meteoinfo.legend.LineStyles; +import org.meteoinfo.legend.MapFrame; +import org.meteoinfo.map.GridLabel; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.List; +import javax.swing.event.EventListenerList; +import org.meteoinfo.data.mapdata.webmap.TileLoadListener; + +/** + * + * @author yaqiang + */ +public class LayoutMap extends LayoutElement { + // + + public void addMapViewUpdatedListener(IMapViewUpdatedListener listener) { + this._listeners.add(IMapViewUpdatedListener.class, listener); + } + + public void removeMapViewUpdatedListener(IMapViewUpdatedListener listener) { + this._listeners.remove(IMapViewUpdatedListener.class, listener); + } + + public void fireMapViewUpdatedEvent() { + fireMapViewUpdatedEvent(new MapViewUpdatedEvent(this)); + } + + private void fireMapViewUpdatedEvent(MapViewUpdatedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == IMapViewUpdatedListener.class) { + ((IMapViewUpdatedListener) listeners[i + 1]).mapViewUpdatedEvent(event); + } + } + } + // + // + private EventListenerList _listeners = new EventListenerList(); + private MapFrame _mapFrame = null; + private boolean _drawDegreeSymbol = false; + private final TileLoadListener tileLoadListener; + // + // + + /** + * Constructor + * + * @param mapFrame MapFrame + * @param tll TileLoadListener + */ + public LayoutMap(MapFrame mapFrame, TileLoadListener tll) { + super(); + this.setElementType(ElementType.LayoutMap); + this.setResizeAbility(ResizeAbility.ResizeAll); + this.setMapFrame(mapFrame); + this.tileLoadListener = tll; + } + // + // + + public MapFrame getMapFrame() { + return _mapFrame; + } + + public void setMapFrame(MapFrame mf) { + _mapFrame = mf; + _mapFrame.addMapViewUpdatedListener(new IMapViewUpdatedListener() { + @Override + public void mapViewUpdatedEvent(MapViewUpdatedEvent event) { + fireMapViewUpdatedEvent(); + } + }); + + _mapFrame.addLayersUpdatedListener(new ILayersUpdatedListener() { + @Override + public void layersUpdatedEvent(LayersUpdatedEvent event) { + fireMapViewUpdatedEvent(); + } + }); + } + + /** + * Get left + * + * @return Left + */ + @Override + public int getLeft() { + return _mapFrame.getLayoutBounds().x; + } + + /** + * Set left + * + * @param left Left + */ + @Override + public void setLeft(int left) { + _mapFrame.setLayoutBounds(new Rectangle(left, _mapFrame.getLayoutBounds().y, _mapFrame.getLayoutBounds().width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get top + * + * @return Top + */ + @Override + public int getTop() { + return _mapFrame.getLayoutBounds().y; + } + + /** + * Set top + * + * @param top Top + */ + @Override + public void setTop(int top) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, top, _mapFrame.getLayoutBounds().width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get width + * + * @return Width + */ + @Override + public int getWidth() { + return _mapFrame.getLayoutBounds().width; + } + + /** + * Set width + * + * @param width Width + */ + @Override + public void setWidth(int width) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get height + * + * @return Height + */ + @Override + public int getHeight() { + return _mapFrame.getLayoutBounds().height; + } + + /** + * Set height + * + * @param height Height + */ + @Override + public void setHeight(int height) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, + _mapFrame.getLayoutBounds().width, height)); + } + + /** + * Get bounds rectangle + * + * @return The bounds rectangle + */ + @Override + public Rectangle getBounds() { + return _mapFrame.getLayoutBounds(); + } + + /** + * Set bounds rectangle + * + * @param rect Bounds rectangle + */ + public void setBounds(Rectangle rect) { + _mapFrame.setLayoutBounds(rect); + } + + /** + * Get background color + * + * @return Background color + */ + @Override + public Color getBackColor() { + return _mapFrame.getBackColor(); + } + + /** + * Set background color + * + * @param color Background color + */ + @Override + public void setBackColor(Color color) { + _mapFrame.setBackColor(color); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + @Override + public Color getForeColor() { + return _mapFrame.getForeColor(); + } + + /** + * Set foreground color + * + * @param color + */ + @Override + public void setForeColor(Color color) { + _mapFrame.setForeColor(color); + } + + /** + * Get if draw map view neat line + * + * @return Boolean + */ + public boolean isDrawNeatLine() { + return _mapFrame.isDrawNeatLine(); + } + + /** + * Set if draw map view neat line + * + * @param istrue Boolean + */ + public void setDrawNeatLine(boolean istrue) { + _mapFrame.setDrawNeatLine(istrue); + } + + /** + * Get map view neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _mapFrame.getNeatLineColor(); + } + + /** + * Set map view neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _mapFrame.setNeatLineColor(color); + } + + /** + * Get map view neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _mapFrame.getNeatLineSize(); + } + + /** + * Set map view neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _mapFrame.setNeatLineSize(size); + } + + /** + * Get grid line color + * + * @return Grid line color + */ + public Color getGridLineColor() { + return _mapFrame.getGridLineColor(); + } + + /** + * Set grid line color + * + * @param color Grid line color + */ + public void setGridLineColor(Color color) { + _mapFrame.setGridLineColor(color); + } + + /** + * Get grid line size + * + * @return Grid line size + */ + public float getGridLineSize() { + return _mapFrame.getGridLineSize(); + } + + /** + * Set grid line size + * + * @param size Grid line size + */ + public void setGridLineSize(float size) { + _mapFrame.setGridLineSize(size); + } + + /** + * Get grid line style + * + * @return Grid line style + */ + public LineStyles getGridLineStyle() { + return _mapFrame.getGridLineStyle(); + } + + /** + * Set grid line style + * + * @param style Grid line style + */ + public void setGridLineStyle(LineStyles style) { + _mapFrame.setGridLineStyle(style); + } + + /** + * Get if draw grid labels + * + * @return If draw grid labels + */ + public boolean isDrawGridLabel() { + return _mapFrame.isDrawGridLabel(); + } + + /** + * Set if draw grid labels + * + * @param istrue Boolean + */ + public void setDrawGridLabel(boolean istrue) { + _mapFrame.setDrawGridLabel(istrue); + } + + /** + * Get if draw grid tick line inside + * + * @return Booelan + */ + public boolean isInsideTickLine() { + return _mapFrame.isInsideTickLine(); + } + + /** + * Set if draw grid tick line inside + * + * @param istrue Boolean + */ + public void setInsideTickLine(boolean istrue) { + _mapFrame.setInsideTickLine(istrue); + } + + /** + * Get grid tick line length + * + * @return Grid tick line length + */ + public int getTickLineLength() { + return _mapFrame.getTickLineLength(); + } + + /** + * Set grid tick line length + * + * @param value Tick line length value + */ + public void setTickLineLength(int value) { + _mapFrame.setTickLineLength(value); + } + + /** + * Get grid label shift + * + * @return Grid label shift + */ + public int getGridLabelShift() { + return _mapFrame.getGridLabelShift(); + } + + /** + * Set grid label shift + * + * @param value Grid label shift + */ + public void setGridLabelShift(int value) { + _mapFrame.setGridLabelShift(value); + } + + /// + /// Get or set grid label position + /** + * Get grid label position + * + * @return Grid label position + */ + public GridLabelPosition getGridLabelPosition() { + return _mapFrame.getGridLabelPosition(); + } + + /** + * Set grid label positiont + * + * @param value Grid label position + */ + public void setGridLabelPosition(GridLabelPosition value) { + _mapFrame.setGridLabelPosition(value); + } + + /** + * Get if draw grid line + * + * @return If draw grid line + */ + public boolean isDrawGridLine() { + return _mapFrame.isDrawGridLine(); + } + + /** + * Set if draw grid line + * + * @param istrue If draw grid line + */ + public void setDrawGridLine(boolean istrue) { + _mapFrame.setDrawGridLine(istrue); + } + + /** + * Get if draw grid tick line + * + * @return Boolean + */ + public boolean isDrawGridTickLine() { + return _mapFrame.isDrawGridTickLine(); + } + + /** + * Set if draw grid tick line + * + * @param istrue Boolean + */ + public void setDrawGridTickLine(boolean istrue) { + _mapFrame.setDrawGridTickLine(istrue); + } + + /** + * Get if draw degree symbol + * + * @return Boolean + */ + public boolean isDrawDegreeSymbol() { + return _drawDegreeSymbol; + } + + /** + * Set if draw degree symbol + * + * @param value Boolean + */ + public void setDrawDegreeSymbol(boolean value) { + _drawDegreeSymbol = value; + } + + /** + * Get grid label font + * + * @return Grid label font + */ + public Font getGridFont() { + return _mapFrame.getGridFont(); + } + + /** + * Set grid label font + * + * @param font Grid label font + */ + public void setGridFont(Font font) { + _mapFrame.setGridFont(font); + } + + /** + * Get grid x delt + * + * @return Grid x delt + */ + public double getGridXDelt() { + return _mapFrame.getGridXDelt(); + } + + /** + * Set grid x delt + * + * @param value The value + */ + public void setGridXDelt(double value) { + _mapFrame.setGridXDelt(value); + } + + /** + * Get grid y delt + * + * @return Grid y delt + */ + public double getGridYDelt() { + return _mapFrame.getGridYDelt(); + } + + /** + * Set grid y delt + * + * @param value Grid y delt + */ + public void setGridYDelt(double value) { + _mapFrame.setGridYDelt(value); + } + + /** + * Get grid x origin + * + * @return Grid x origin + */ + public float getGridXOrigin() { + return _mapFrame.getGridXOrigin(); + } + + /** + * Set grid x origin + * + * @param value Grid x origin + */ + public void setGridXOrigin(float value) { + _mapFrame.setGridXOrigin(value); + } + + /** + * Get grid y origin + * + * @return Grid y origin + */ + public float getGridYOrigin() { + return _mapFrame.getGridYOrigin(); + } + + /** + * Set grid y origin + * + * @param value Grid y origin + */ + public void setGridYOrigin(float value) { + _mapFrame.setGridYOrigin(value); + } + + // + // + /** + * Zoom to exactly lon/lat extent + * + * @param aExtent The lon/lat extent + */ + public void zoomToExtentLonLatEx(Extent aExtent) { + if (!_mapFrame.getMapView().getProjection().isLonLatMap()) { + aExtent = _mapFrame.getMapView().getProjection().getProjectedExtentFromLonLat(aExtent); + } + + setSizeByExtent(aExtent); + _mapFrame.getMapView().setViewExtent(aExtent); + } + + private void setSizeByExtent(Extent aExtent) { + double scaleFactor; + + double scaleX = this.getWidth() / (aExtent.maxX - aExtent.minX); + double scaleY = this.getHeight() / (aExtent.maxY - aExtent.minY); + if (_mapFrame.getMapView().getProjection().isLonLatMap()) { + scaleFactor = _mapFrame.getMapView().getXYScaleFactor(); + } else { + scaleFactor = 1; + } + + if (scaleX > scaleY) { + scaleX = scaleY / scaleFactor; + this.setWidth((int) ((aExtent.maxX - aExtent.minX) * scaleX)); + } else { + scaleY = scaleX * scaleFactor; + this.setHeight((int) ((aExtent.maxY - aExtent.minY) * scaleY)); + } + } + + /** + * Paint method + * + * @param g Graphics2D + */ + @Override + public void paint(Graphics2D g) { + if (_mapFrame != null) { + g.setColor(_mapFrame.getMapView().getBackground()); + g.fill(_mapFrame.getLayoutBounds()); + + _mapFrame.getMapView().paintGraphics(g, _mapFrame.getLayoutBounds(), this.tileLoadListener); + +// //Draw lon/lat grid labels +// if (_mapFrame.getDrawGridLabel()) +// { +// List extentList = new ArrayList(); +// Extent maxExtent = new Extent(); +// Extent aExtent = new Extent(); +// SizeF aSF = new SizeF(); +// SolidBrush aBrush = new SolidBrush(this.ForeColor); +// Pen aPen = new Pen(_mapFrame.GridLineColor); +// aPen.Width = _mapFrame.GridLineSize; +// String drawStr; +// PointF sP = new PointF(0, 0); +// PointF eP = new PointF(0, 0); +// Font font = new Font(_mapFrame.getGridFont().Name, _mapFrame.getGridFont().Size, _mapFrame.getGridFont().Style); +// float labX, labY; +// int len = 5; +// int space = len + 2; +// for (int i = 0; i < _mapFrame.getMapView().getGridLabels().Count; i++) +// { +// GridLabel aGL = _mapFrame.getMapView().getGridLabels()[i]; +// switch (_mapFrame.getGridLabelPosition()) +// { +// case GridLabelPosition.LeftBottom: +// switch (aGL.LabDirection) +// { +// case Direction.East: +// case Direction.North: +// continue; +// } +// break; +// case GridLabelPosition.LeftUp: +// switch (aGL.LabDirection) +// { +// case Direction.East: +// case Direction.South: +// continue; +// } +// break; +// case GridLabelPosition.RightBottom: +// switch (aGL.LabDirection) +// { +// case Direction.Weast: +// case Direction.North: +// continue; +// } +// break; +// case GridLabelPosition.RightUp: +// switch (aGL.LabDirection) +// { +// case Direction.Weast: +// case Direction.South: +// continue; +// } +// break; +// } +// +// labX = (float)aGL.LabPoint.X; +// labY = (float)aGL.LabPoint.Y; +// labX = labX + this.Left; +// labY = labY + this.Top; +// sP.X = labX; +// sP.Y = labY; +// +// drawStr = aGL.LabString; +// aSF = g.MeasureString(drawStr, font); +// switch (aGL.LabDirection) +// { +// case Direction.South: +// labX = labX - aSF.Width / 2; +// labY = labY + space; +// eP.X = sP.X; +// eP.Y = sP.Y + len; +// break; +// case Direction.Weast: +// labX = labX - aSF.Width - space; +// labY = labY - aSF.Height / 2; +// eP.X = sP.X - len; +// eP.Y = sP.Y; +// break; +// case Direction.North: +// labX = labX - aSF.Width / 2; +// labY = labY - aSF.Height - space; +// eP.X = sP.X; +// eP.Y = sP.Y - len; +// break; +// case Direction.East: +// labX = labX + space; +// labY = labY - aSF.Height / 2; +// eP.X = sP.X + len; +// eP.Y = sP.Y; +// break; +// } +// +// bool ifDraw = true; +// float aSize = aSF.Width / 2; +// float bSize = aSF.Height / 2; +// aExtent.minX = labX; +// aExtent.maxX = labX + aSF.Width; +// aExtent.minY = labY - aSF.Height; +// aExtent.maxY = labY; +// +// //Judge extent +// if (extentList.Count == 0) +// { +// maxExtent = aExtent; +// extentList.Add(aExtent); +// } +// else +// { +// if (!MIMath.IsExtentCross(aExtent, maxExtent)) +// { +// extentList.Add(aExtent); +// maxExtent = MIMath.GetLagerExtent(maxExtent, aExtent); +// } +// else +// { +// for (int j = 0; j < extentList.Count; j++) +// { +// if (MIMath.IsExtentCross(aExtent, extentList[j])) +// { +// ifDraw = false; +// break; +// } +// } +// if (ifDraw) +// { +// extentList.Add(aExtent); +// maxExtent = MIMath.GetLagerExtent(maxExtent, aExtent); +// } +// } +// } +// +// if (ifDraw) +// { +// g.DrawLine(aPen, sP, eP); +// g.DrawString(drawStr, font, aBrush, labX, labY); +// } +// } +// } + if (_mapFrame.isDrawNeatLine()) { + g.setColor(_mapFrame.getNeatLineColor()); + g.setStroke(new BasicStroke(_mapFrame.getNeatLineSize())); + g.draw(_mapFrame.getLayoutBounds()); + } + } + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (_mapFrame != null) { + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + Rectangle rect = new Rectangle((int) aP.X, (int) aP.Y, (int) (this.getWidth() * zoom), (int) (this.getHeight() * zoom)); + //g.setColor(_mapFrame.getMapView().getBackground()); + //g.fill(rect); + + _mapFrame.getMapView().paintGraphics(g, rect, this.tileLoadListener); + + //Draw lon/lat grid labels + if (_mapFrame.isDrawGridLabel()) { + List extentList = new ArrayList<>(); + Extent maxExtent = new Extent(); + Extent aExtent; + Dimension aSF; + g.setColor(_mapFrame.getGridLineColor()); + g.setStroke(new BasicStroke(_mapFrame.getGridLineSize())); + String drawStr; + PointF sP = new PointF(0, 0); + PointF eP = new PointF(0, 0); + Font font = new Font(_mapFrame.getGridFont().getFontName(), _mapFrame.getGridFont().getStyle(), (int) (_mapFrame.getGridFont().getSize() * zoom)); + g.setFont(font); + float labX, labY; + int len = _mapFrame.getTickLineLength(); + int space = len + _mapFrame.getGridLabelShift(); + if (_mapFrame.isInsideTickLine()) { + space = _mapFrame.getGridLabelShift(); + } + + for (int i = 0; i < _mapFrame.getMapView().getGridLabels().size(); i++) { + GridLabel aGL = _mapFrame.getMapView().getGridLabels().get(i); + switch (_mapFrame.getGridLabelPosition()) { + case LEFT_BOTTOM: + switch (aGL.getLabDirection()) { + case East: + case North: + continue; + } + break; + case LEFT_UP: + switch (aGL.getLabDirection()) { + case East: + case South: + continue; + } + break; + case RIGHT_BOTTOM: + switch (aGL.getLabDirection()) { + case Weast: + case North: + continue; + } + break; + case RIGHT_UP: + switch (aGL.getLabDirection()) { + case Weast: + case South: + continue; + } + break; + } + + labX = (float) aGL.getLabPoint().X; + labY = (float) aGL.getLabPoint().Y; + labX = labX + this.getLeft() * zoom + pageLocation.X; + labY = labY + this.getTop() * zoom + pageLocation.Y; + sP.X = labX; + sP.Y = labY; + + drawStr = aGL.getLabString(); + if (_drawDegreeSymbol) { + if (drawStr.endsWith("E") || drawStr.endsWith("W") || drawStr.endsWith("N") || drawStr.endsWith("S")) { + drawStr = drawStr.substring(0, drawStr.length() - 1) + String.valueOf((char) 186) + drawStr.substring(drawStr.length() - 1); + } else { + drawStr = drawStr + String.valueOf((char) 186); + } + } + FontMetrics metrics = g.getFontMetrics(font); + aSF = new Dimension(metrics.stringWidth(drawStr), metrics.getHeight()); + switch (aGL.getLabDirection()) { + case South: + labX = labX - aSF.width / 2; + labY = labY + aSF.height * 3 / 4 + space; + eP.X = sP.X; + if (_mapFrame.isInsideTickLine()) { + eP.Y = sP.Y - len; + } else { + eP.Y = sP.Y + len; + } + break; + case Weast: + labX = labX - aSF.width - space; + labY = labY + aSF.height / 3; + eP.Y = sP.Y; + if (_mapFrame.isInsideTickLine()) { + eP.X = sP.X + len; + } else { + eP.X = sP.X - len; + } + break; + case North: + labX = labX - aSF.width / 2; + //labY = labY - aSF.height / 3 - space; + labY = labY - space; + eP.X = sP.X; + if (_mapFrame.isInsideTickLine()) { + eP.Y = sP.Y + len; + } else { + eP.Y = sP.Y - len; + } + break; + case East: + labX = labX + space; + labY = labY + aSF.height / 3; + eP.Y = sP.Y; + if (_mapFrame.isInsideTickLine()) { + eP.X = sP.X - len; + } else { + eP.X = sP.X + len; + } + break; + } + + boolean ifDraw = true; + float aSize = aSF.width / 2; + float bSize = aSF.height / 2; + aExtent = new Extent(); + aExtent.minX = labX; + aExtent.maxX = labX + aSF.width; + aExtent.minY = labY - aSF.height; + aExtent.maxY = labY; + + //Judge extent + if (extentList.isEmpty()) { + maxExtent = (Extent) aExtent.clone(); + extentList.add((Extent) aExtent.clone()); + } else { + if (!MIMath.isExtentCross(aExtent, maxExtent)) { + extentList.add((Extent) aExtent.clone()); + maxExtent = MIMath.getLagerExtent(maxExtent, aExtent); + } else { + for (int j = 0; j < extentList.size(); j++) { + if (MIMath.isExtentCross(aExtent, extentList.get(j))) { + ifDraw = false; + break; + } + } + if (ifDraw) { + extentList.add(aExtent); + maxExtent = MIMath.getLagerExtent(maxExtent, aExtent); + } + } + } + + if (ifDraw) { + g.setColor(_mapFrame.getGridLineColor()); + g.draw(new Line2D.Float(sP.X, sP.Y, eP.X, eP.Y)); + g.setColor(this.getForeColor()); + g.drawString(drawStr, labX, labY); + } + } + } + + //Draw neat line + if (_mapFrame.isDrawNeatLine()) { + g.setColor(_mapFrame.getNeatLineColor()); + g.setStroke(new BasicStroke(_mapFrame.getNeatLineSize())); + g.draw(rect); + } + } + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // + // + + public class LayoutMapBean { + + LayoutMapBean() { + } + // + + /** + * Get left + * + * @return Left + */ + public int getLeft() { + return _mapFrame.getLayoutBounds().x; + } + + /** + * Set left + * + * @param left Left + */ + public void setLeft(int left) { + _mapFrame.setLayoutBounds(new Rectangle(left, _mapFrame.getLayoutBounds().y, _mapFrame.getLayoutBounds().width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get top + * + * @return Top + */ + public int getTop() { + return _mapFrame.getLayoutBounds().y; + } + + /** + * Set top + * + * @param top Top + */ + public void setTop(int top) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, top, _mapFrame.getLayoutBounds().width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return _mapFrame.getLayoutBounds().width; + } + + /** + * Set width + * + * @param width Width + */ + public void setWidth(int width) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, width, + _mapFrame.getLayoutBounds().height)); + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return _mapFrame.getLayoutBounds().height; + } + + /** + * Set height + * + * @param height Height + */ + public void setHeight(int height) { + _mapFrame.setLayoutBounds(new Rectangle(_mapFrame.getLayoutBounds().x, _mapFrame.getLayoutBounds().y, + _mapFrame.getLayoutBounds().width, height)); + } + + /** + * Get bounds rectangle + * + * @return The bounds rectangle + */ + public Rectangle getBounds() { + return _mapFrame.getLayoutBounds(); + } + + /** + * Set bounds rectangle + * + * @param rect Bounds rectangle + */ + public void setBounds(Rectangle rect) { + _mapFrame.setLayoutBounds(rect); + } + + /** + * Get is draw backcolor + * + * @return Boolean + */ + public boolean isDrawBackColor() { + return LayoutMap.this.isDrawBackColor(); + } + + /** + * Set is draw backcolor + * + * @param value Boolean + */ + public void setDrawBackColor(boolean value) { + LayoutMap.this.setDrawBackColor(value); + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackColor() { + return _mapFrame.getBackColor(); + } + + /** + * Set background color + * + * @param color Background color + */ + public void setBackColor(Color color) { + _mapFrame.setBackColor(color); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeColor() { + return _mapFrame.getForeColor(); + } + + /** + * Set foreground color + * + * @param color + */ + public void setForeColor(Color color) { + _mapFrame.setForeColor(color); + } + + /** + * Get if draw map view neat line + * + * @return Boolean + */ + public boolean isDrawNeatLine() { + return _mapFrame.isDrawNeatLine(); + } + + /** + * Set if draw map view neat line + * + * @param istrue Boolean + */ + public void setDrawNeatLine(boolean istrue) { + _mapFrame.setDrawNeatLine(istrue); + } + + /** + * Get map view neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _mapFrame.getNeatLineColor(); + } + + /** + * Set map view neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _mapFrame.setNeatLineColor(color); + } + + /** + * Get map view neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _mapFrame.getNeatLineSize(); + } + + /** + * Set map view neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _mapFrame.setNeatLineSize(size); + } + + /** + * Get grid line color + * + * @return Grid line color + */ + public Color getGridLineColor() { + return _mapFrame.getGridLineColor(); + } + + /** + * Set grid line color + * + * @param color Grid line color + */ + public void setGridLineColor(Color color) { + _mapFrame.setGridLineColor(color); + } + + /** + * Get grid line size + * + * @return Grid line size + */ + public float getGridLineSize() { + return _mapFrame.getGridLineSize(); + } + + /** + * Set grid line size + * + * @param size Grid line size + */ + public void setGridLineSize(float size) { + _mapFrame.setGridLineSize(size); + } + + /** + * Get grid line style + * + * @return Grid line style + */ + public String getGridLineStyle() { + return _mapFrame.getGridLineStyle().toString(); + } + + /** + * Set grid line style + * + * @param style Grid line style + */ + public void setGridLineStyle(String style) { + _mapFrame.setGridLineStyle(LineStyles.valueOf(style)); + } + + /** + * Get if draw grid labels + * + * @return If draw grid labels + */ + public boolean isDrawGridLabel() { + return _mapFrame.isDrawGridLabel(); + } + + /** + * Set if draw grid labels + * + * @param istrue Boolean + */ + public void setDrawGridLabel(boolean istrue) { + _mapFrame.setDrawGridLabel(istrue); + } + + /** + * Get if draw grid tick line inside + * + * @return Booelan + */ + public boolean isInsideTickLine() { + return _mapFrame.isInsideTickLine(); + } + + /** + * Set if draw grid tick line inside + * + * @param istrue Boolean + */ + public void setInsideTickLine(boolean istrue) { + _mapFrame.setInsideTickLine(istrue); + } + + /** + * Get grid tick line length + * + * @return Grid tick line length + */ + public int getTickLineLength() { + return _mapFrame.getTickLineLength(); + } + + /** + * Set grid tick line length + * + * @param value tick line length + */ + public void setTickLineLength(int value) { + _mapFrame.setTickLineLength(value); + } + + /** + * Get grid label shift + * + * @return Grid label shift + */ + public int getGridLabelShift() { + return _mapFrame.getGridLabelShift(); + } + + /** + * Set grid label shift + * + * @param value Grid label shift + */ + public void setGridLabelShift(int value) { + _mapFrame.setGridLabelShift(value); + } + + /// + /// Get or set grid label position + /** + * Get grid label position + * + * @return Grid label position + */ + public String getGridLabelPosition() { + return _mapFrame.getGridLabelPosition().toString(); + } + + /** + * Set grid label positiont + * + * @param value Grid label position + */ + public void setGridLabelPosition(String value) { + _mapFrame.setGridLabelPosition(GridLabelPosition.valueOf(value)); + } + + /** + * Get if draw grid line + * + * @return If draw grid line + */ + public boolean isDrawGridLine() { + return _mapFrame.isDrawGridLine(); + } + + /** + * Set if draw grid line + * + * @param istrue If draw grid line + */ + public void setDrawGridLine(boolean istrue) { + _mapFrame.setDrawGridLine(istrue); + } + + /** + * Get if draw grid tick line + * + * @return Boolean + */ + public boolean isDrawGridTickLine() { + return _mapFrame.isDrawGridTickLine(); + } + + /** + * Set if draw grid tick line + * + * @param istrue Boolean + */ + public void setDrawGridTickLine(boolean istrue) { + _mapFrame.setDrawGridTickLine(istrue); + } + + /** + * Get if draw degree symbol + * + * @return Boolean + */ + public boolean isDrawDegreeSymbol() { + return _drawDegreeSymbol; + } + + /** + * Set if draw degree symbol + * + * @param value Boolean + */ + public void setDrawDegreeSymbol(boolean value) { + _drawDegreeSymbol = value; + } + + /** + * Get grid label font + * + * @return Grid label font + */ + public Font getGridFont() { + return _mapFrame.getGridFont(); + } + + /** + * Set grid label font + * + * @param font Grid label font + */ + public void setGridFont(Font font) { + _mapFrame.setGridFont(font); + } + + /** + * Get grid x delt + * + * @return Grid x delt + */ + public double getGridXDelt() { + return _mapFrame.getGridXDelt(); + } + + /** + * Set grid x delt + * + * @param value The value + */ + public void setGridXDelt(double value) { + _mapFrame.setGridXDelt(value); + } + + /** + * Get grid y delt + * + * @return Grid y delt + */ + public double getGridYDelt() { + return _mapFrame.getGridYDelt(); + } + + /** + * Set grid y delt + * + * @param value Grid y delt + */ + public void setGridYDelt(double value) { + _mapFrame.setGridYDelt(value); + } + + /** + * Get grid x origin + * + * @return Grid x origin + */ + public float getGridXOrigin() { + return _mapFrame.getGridXOrigin(); + } + + /** + * Set grid x origin + * + * @param value Grid x origin + */ + public void setGridXOrigin(float value) { + _mapFrame.setGridXOrigin(value); + } + + /** + * Get grid y origin + * + * @return Grid y origin + */ + public float getGridYOrigin() { + return _mapFrame.getGridYOrigin(); + } + + /** + * Set grid y origin + * + * @param value Grid y origin + */ + public void setGridYOrigin(float value) { + _mapFrame.setGridYOrigin(value); + } + // + } + + public static class LayoutMapBeanBeanInfo extends BaseBeanInfo { + + public LayoutMapBeanBeanInfo() { + super(LayoutMapBean.class); + addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); + addProperty("backColor").setCategory("General").setDisplayName("Background"); + addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); + addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); + addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); + addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); + addProperty("drawGridLine").setCategory("Grid Line").setDisplayName("Draw Grid Line"); + addProperty("drawGridLabel").setCategory("Grid Line").setDisplayName("Draw Grid Label"); + addProperty("gridXDelt").setCategory("Grid Line").setDisplayName("Grid X Interval"); + addProperty("gridYDelt").setCategory("Grid Line").setDisplayName("Grid Y Interval"); + addProperty("gridXOrigin").setCategory("Grid Line").setDisplayName("Grid X Origin"); + addProperty("gridYOrigin").setCategory("Grid Line").setDisplayName("Grid Y Origin"); + addProperty("gridFont").setCategory("Grid Line").setDisplayName("Grid Label Font"); + addProperty("gridLabelShift").setCategory("Grid Line").setDisplayName("Grid Label Shift"); + ExtendedPropertyDescriptor e = addProperty("gridLabelPosition"); + e.setCategory("Grid Line").setDisplayName("Grid Label Position"); + e.setPropertyEditorClass(GridLabelPositionEditor.class); + addProperty("drawDegreeSymbol").setCategory("Grid Line").setDisplayName("Draw Degree Symbol"); + addProperty("gridLineColor").setCategory("Grid Line").setDisplayName("Grid Line Color"); + addProperty("gridLineSize").setCategory("Grid Line").setDisplayName("Grid Line Size"); + e = addProperty("gridLineStyle"); + e.setCategory("Grid Line").setDisplayName("Grid Line Style"); + e.setPropertyEditorClass(LineStyleEditor.class); + addProperty("insideTickLine").setCategory("Grid Line").setDisplayName("Inside Tick Line"); + addProperty("tickLineLength").setCategory("Grid Line").setDisplayName("Tick Line Length"); + addProperty("left").setCategory("Location").setDisplayName("Left"); + addProperty("top").setCategory("Location").setDisplayName("Top"); + addProperty("width").setCategory("Location").setDisplayName("Width"); + addProperty("height").setCategory("Location").setDisplayName("Height"); + } + } + + public static class GridLabelPositionEditor extends ComboBoxPropertyEditor { + + public GridLabelPositionEditor() { + super(); + GridLabelPosition[] lutypes = GridLabelPosition.values(); + String[] types = new String[lutypes.length]; + int i = 0; + for (GridLabelPosition type : lutypes) { + types[i] = type.toString(); + i += 1; + } + setAvailableValues(types); + } + } + + public static class LineStyleEditor extends ComboBoxPropertyEditor { + + public LineStyleEditor() { + super(); + LineStyles[] lutypes = LineStyles.values(); + String[] types = new String[lutypes.length]; + int i = 0; + for (LineStyles type : lutypes) { + types[i] = type.toString(); + i += 1; + } + setAvailableValues(types); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutNorthArrow.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutNorthArrow.java index 2a0aee9e..958ebf06 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutNorthArrow.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutNorthArrow.java @@ -1,476 +1,477 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import com.l2fprod.common.beans.BaseBeanInfo; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.PointF; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; - -/** - * - * @author Yaqiang Wang - */ -public class LayoutNorthArrow extends LayoutElement { -// - - private LayoutMap _layoutMap; - private boolean _antiAlias; - private boolean _drawNeatLine; - private Color _neatLineColor; - private float _neatLineSize; - private NorthArrowType _northArrowType; - private float _angle; - // - // - - /** - * Constructor - * - * @param layoutMap The layout map - */ - public LayoutNorthArrow(LayoutMap layoutMap) { - super(); - this.setElementType(ElementType.LayoutNorthArraw); - this.setResizeAbility(ResizeAbility.ResizeAll); - - this.setWidth(50); - this.setHeight(50); - - _layoutMap = layoutMap; - _antiAlias = true; - _drawNeatLine = false; - _neatLineColor = Color.black; - _neatLineSize = 1; - _northArrowType = NorthArrowType.NORTHARROW_1; - _angle = 0; - } - // - // - - /** - * Get layout map - * - * @return The layout map - */ - public LayoutMap getLayoutMap() { - return _layoutMap; - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get angle - * - * @return Angle - */ - public float getAngle() { - return _angle; - } - - /** - * Set angle - * - * @param angle The angle - */ - public void setAngle(float angle) { - _angle = angle; - } - - // - // - @Override - public void paint(Graphics2D g) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (this.isVisible()) { - paintGraphics(g, pageLocation, zoom); - } - } - - /** - * Paint graphics - * - * @param g Graphics - * @param pageLocation Page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { - AffineTransform oldMatrix = g.getTransform(); - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - g.translate(aP.X, aP.Y); - g.scale(zoom, zoom); - if (_angle != 0) { - g.rotate(_angle); - } - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackColor()); - g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); - } - - drawNorthArrow(g, zoom); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawNorthArrow(Graphics2D g, float zoom) { - switch (_northArrowType) { - case NORTHARROW_1: - drawNorthArrow1(g, zoom); - break; - } - } - - private void drawNorthArrow1(Graphics2D g, float zoom) { - g.setColor(this.getForeColor()); - g.setStroke(new BasicStroke(zoom)); - - //Draw N symbol - PointF[] points = new PointF[4]; - int x = this.getWidth() / 2; - int y = this.getHeight() / 6; - int w = this.getWidth() / 6; - int h = this.getHeight() / 4; - points[0] = new PointF(x - w / 2, y + h / 2); - points[1] = new PointF(x - w / 2, y - h / 2); - points[2] = new PointF(x + w / 2, y + h / 2); - points[3] = new PointF(x + w / 2, y - h / 2); - Draw.drawPolyline(points, g); - - //Draw arrow - w = this.getWidth() / 2; - h = this.getHeight() * 2 / 3; - points = new PointF[3]; - points[0] = new PointF(x - w / 2, this.getHeight()); - points[1] = new PointF(x, this.getHeight() - h / 2); - points[2] = new PointF(x, this.getHeight() - h); - Draw.fillPolygon(points, g, null); - - points = new PointF[4]; - points[0] = new PointF(x + w / 2, this.getHeight()); - points[1] = new PointF(x, this.getHeight() - h / 2); - points[2] = new PointF(x, this.getHeight() - h); - points[3] = points[0]; - Draw.drawPolyline(points, g); - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // - // - - public class LayoutNorthArrowBean { - - LayoutNorthArrowBean() { - } - // - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get angle - * - * @return Angle - */ - public float getAngle() { - return _angle; - } - - /** - * Set angle - * - * @param angle The angle - */ - public void setAngle(float angle) { - _angle = angle; - } - - /** - * Get is draw backcolor - * @return Boolean - */ - public boolean isDrawBackColor(){ - return LayoutNorthArrow.this.isDrawBackColor(); - } - - /** - * Set is draw backcolor - * @param value Boolean - */ - public void setDrawBackColor(boolean value){ - LayoutNorthArrow.this.setDrawBackColor(value); - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackColor() { - return LayoutNorthArrow.this.getBackColor(); - } - - /** - * Set background color - * - * @param c Background color - */ - public void setBackColor(Color c) { - LayoutNorthArrow.this.setBackColor(c); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeColor() { - return LayoutNorthArrow.this.getForeColor(); - } - - /** - * Set foreground color - * - * @param c Foreground color - */ - public void setForeColor(Color c) { - LayoutNorthArrow.this.setForeColor(c); - } - - /** - * Get left - * - * @return Left - */ - public int getLeft() { - return LayoutNorthArrow.this.getLeft(); - } - - /** - * Set left - * - * @param left Left - */ - public void setLeft(int left) { - LayoutNorthArrow.this.setLeft(left); - } - - /** - * Get top - * - * @return Top - */ - public int getTop() { - return LayoutNorthArrow.this.getTop(); - } - - /** - * Set top - * - * @param top Top - */ - public void setTop(int top) { - LayoutNorthArrow.this.setTop(top); - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return LayoutNorthArrow.this.getWidth(); - } - - /** - * Set width - * - * @param width Width - */ - public void setWidth(int width) { - LayoutNorthArrow.this.setWidth(width); - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return LayoutNorthArrow.this.getHeight(); - } - - /** - * Set height - * - * @param height Height - */ - public void setHeight(int height) { - LayoutNorthArrow.this.setHeight(height); - } - // - } - - public static class LayoutNorthArrowBeanBeanInfo extends BaseBeanInfo { - - public LayoutNorthArrowBeanBeanInfo() { - super(LayoutNorthArrowBean.class); - addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); - addProperty("backColor").setCategory("General").setDisplayName("Background"); - addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); - addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); - addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); - addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); - addProperty("angle").setCategory("Location").setDisplayName("Angle"); - addProperty("left").setCategory("Location").setDisplayName("Left"); - addProperty("top").setCategory("Location").setDisplayName("Top"); - addProperty("width").setCategory("Location").setDisplayName("Width"); - addProperty("height").setCategory("Location").setDisplayName("Height"); - } - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import com.l2fprod.common.beans.BaseBeanInfo; +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; + +/** + * + * @author Yaqiang Wang + */ +public class LayoutNorthArrow extends LayoutElement { +// + + private LayoutMap _layoutMap; + private boolean _antiAlias; + private boolean _drawNeatLine; + private Color _neatLineColor; + private float _neatLineSize; + private NorthArrowType _northArrowType; + private float _angle; + // + // + + /** + * Constructor + * + * @param layoutMap The layout map + */ + public LayoutNorthArrow(LayoutMap layoutMap) { + super(); + this.setElementType(ElementType.LayoutNorthArraw); + this.setResizeAbility(ResizeAbility.ResizeAll); + + this.setWidth(50); + this.setHeight(50); + + _layoutMap = layoutMap; + _antiAlias = true; + _drawNeatLine = false; + _neatLineColor = Color.black; + _neatLineSize = 1; + _northArrowType = NorthArrowType.NORTHARROW_1; + _angle = 0; + } + // + // + + /** + * Get layout map + * + * @return The layout map + */ + public LayoutMap getLayoutMap() { + return _layoutMap; + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get angle + * + * @return Angle + */ + public float getAngle() { + return _angle; + } + + /** + * Set angle + * + * @param angle The angle + */ + public void setAngle(float angle) { + _angle = angle; + } + + // + // + @Override + public void paint(Graphics2D g) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (this.isVisible()) { + paintGraphics(g, pageLocation, zoom); + } + } + + /** + * Paint graphics + * + * @param g Graphics + * @param pageLocation Page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { + AffineTransform oldMatrix = g.getTransform(); + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + g.translate(aP.X, aP.Y); + g.scale(zoom, zoom); + if (_angle != 0) { + g.rotate(_angle); + } + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackColor()); + g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); + } + + drawNorthArrow(g, zoom); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawNorthArrow(Graphics2D g, float zoom) { + switch (_northArrowType) { + case NORTHARROW_1: + drawNorthArrow1(g, zoom); + break; + } + } + + private void drawNorthArrow1(Graphics2D g, float zoom) { + g.setColor(this.getForeColor()); + g.setStroke(new BasicStroke(zoom)); + + //Draw N symbol + PointF[] points = new PointF[4]; + int x = this.getWidth() / 2; + int y = this.getHeight() / 6; + int w = this.getWidth() / 6; + int h = this.getHeight() / 4; + points[0] = new PointF(x - w / 2, y + h / 2); + points[1] = new PointF(x - w / 2, y - h / 2); + points[2] = new PointF(x + w / 2, y + h / 2); + points[3] = new PointF(x + w / 2, y - h / 2); + Draw.drawPolyline(points, g); + + //Draw arrow + w = this.getWidth() / 2; + h = this.getHeight() * 2 / 3; + points = new PointF[3]; + points[0] = new PointF(x - w / 2, this.getHeight()); + points[1] = new PointF(x, this.getHeight() - h / 2); + points[2] = new PointF(x, this.getHeight() - h); + Draw.fillPolygon(points, g, null); + + points = new PointF[4]; + points[0] = new PointF(x + w / 2, this.getHeight()); + points[1] = new PointF(x, this.getHeight() - h / 2); + points[2] = new PointF(x, this.getHeight() - h); + points[3] = points[0]; + Draw.drawPolyline(points, g); + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // + // + + public class LayoutNorthArrowBean { + + LayoutNorthArrowBean() { + } + // + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get angle + * + * @return Angle + */ + public float getAngle() { + return _angle; + } + + /** + * Set angle + * + * @param angle The angle + */ + public void setAngle(float angle) { + _angle = angle; + } + + /** + * Get is draw backcolor + * @return Boolean + */ + public boolean isDrawBackColor(){ + return LayoutNorthArrow.this.isDrawBackColor(); + } + + /** + * Set is draw backcolor + * @param value Boolean + */ + public void setDrawBackColor(boolean value){ + LayoutNorthArrow.this.setDrawBackColor(value); + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackColor() { + return LayoutNorthArrow.this.getBackColor(); + } + + /** + * Set background color + * + * @param c Background color + */ + public void setBackColor(Color c) { + LayoutNorthArrow.this.setBackColor(c); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeColor() { + return LayoutNorthArrow.this.getForeColor(); + } + + /** + * Set foreground color + * + * @param c Foreground color + */ + public void setForeColor(Color c) { + LayoutNorthArrow.this.setForeColor(c); + } + + /** + * Get left + * + * @return Left + */ + public int getLeft() { + return LayoutNorthArrow.this.getLeft(); + } + + /** + * Set left + * + * @param left Left + */ + public void setLeft(int left) { + LayoutNorthArrow.this.setLeft(left); + } + + /** + * Get top + * + * @return Top + */ + public int getTop() { + return LayoutNorthArrow.this.getTop(); + } + + /** + * Set top + * + * @param top Top + */ + public void setTop(int top) { + LayoutNorthArrow.this.setTop(top); + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return LayoutNorthArrow.this.getWidth(); + } + + /** + * Set width + * + * @param width Width + */ + public void setWidth(int width) { + LayoutNorthArrow.this.setWidth(width); + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return LayoutNorthArrow.this.getHeight(); + } + + /** + * Set height + * + * @param height Height + */ + public void setHeight(int height) { + LayoutNorthArrow.this.setHeight(height); + } + // + } + + public static class LayoutNorthArrowBeanBeanInfo extends BaseBeanInfo { + + public LayoutNorthArrowBeanBeanInfo() { + super(LayoutNorthArrowBean.class); + addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); + addProperty("backColor").setCategory("General").setDisplayName("Background"); + addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); + addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); + addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); + addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); + addProperty("angle").setCategory("Location").setDisplayName("Angle"); + addProperty("left").setCategory("Location").setDisplayName("Left"); + addProperty("top").setCategory("Location").setDisplayName("Top"); + addProperty("width").setCategory("Location").setDisplayName("Width"); + addProperty("height").setCategory("Location").setDisplayName("Height"); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutScaleBar.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutScaleBar.java index 2cd93cba..fc64637e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutScaleBar.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/LayoutScaleBar.java @@ -1,729 +1,730 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.layout; - -import com.l2fprod.common.beans.BaseBeanInfo; -import com.l2fprod.common.beans.ExtendedPropertyDescriptor; -import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; -import org.meteoinfo.global.PointF; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; - -/** - * - * @author Yaqiang Wang - */ -public class LayoutScaleBar extends LayoutElement { -// - - private LayoutMap _layoutMap; - private boolean _antiAlias; - private Font _font; - private ScaleBarType _scaleBarType; - private ScaleBarUnits _unit; - private String _unitText; - private int _numBreaks; - private boolean _drawNeatLine; - private Color _neatLineColor; - private float _neatLineSize; - private boolean _drawScaleText; - private float _yShiftScale = 2.0f; - // - // - - /** - * Constructor - * - * @param layoutMap The layout map - */ - public LayoutScaleBar(LayoutMap layoutMap) { - super(); - this.setElementType(ElementType.LayoutScaleBar); - this.setResizeAbility(ResizeAbility.ResizeAll); - - this.setWidth(200); - this.setHeight(50); - _layoutMap = layoutMap; - _antiAlias = true; - _scaleBarType = ScaleBarType.SCALELINE_1; - _drawNeatLine = false; - _neatLineColor = Color.black; - _neatLineSize = 1; - _font = new Font("Arial", Font.PLAIN, 12); - _unit = ScaleBarUnits.KILOMETERS; - _unitText = "km"; - _numBreaks = 4; - _drawScaleText = false; - } - // - // - - /** - * Get layout map - * - * @return The layout map - */ - public LayoutMap getLayoutMap() { - return _layoutMap; - } - - /** - * Get scale bar type - * - * @return Scale bar type - */ - public ScaleBarType getScaleBarType() { - return _scaleBarType; - } - - /** - * Set scale bar type - * - * @param type Scale bar type - */ - public void setScaleBarType(ScaleBarType type) { - _scaleBarType = type; - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get font - * - * @return The font - */ - public Font getFont() { - return _font; - } - - /** - * Set font - * - * @param font The font - */ - public void setFont(Font font) { - _font = font; - } - - /** - * Get break number - * - * @return The break number - */ - public int getBreakNumber() { - return _numBreaks; - } - - /** - * Set break number - * - * @param num Break number - */ - public void setBreakNumber(int num) { - _numBreaks = num; - } - - /** - * Get if draw scale text - * - * @return If draw scale text - */ - public boolean isDrawScaleText() { - return _drawScaleText; - } - - /** - * Set if draw scale text - * - * @param istrue If draw scale text - */ - public void setDrawScaleText(boolean istrue) { - _drawScaleText = istrue; - } - // - // - - @Override - public void paint(Graphics2D g) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { - if (this.isVisible()) { - paintGraphics(g, pageLocation, zoom); - } - } - - /** - * Paint graphics - * - * @param g Graphics - * @param pageLocation Page location - * @param zoom Zoom - */ - public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { - AffineTransform oldMatrix = g.getTransform(); - PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); - g.translate(aP.X, aP.Y); - g.scale(zoom, zoom); - if (_antiAlias) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } else { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - } - - //Draw background color - if (this.isDrawBackColor()){ - g.setColor(this.getBackColor()); - g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); - } - - drawScaleBar(g, zoom); - - //Draw neatline - if (_drawNeatLine) { - Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, - (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); - g.setColor(_neatLineColor); - g.setStroke(new BasicStroke(_neatLineSize)); - g.draw(mapRect); - } - - g.setTransform(oldMatrix); - } - - private void drawScaleBar(Graphics2D g, float zoom) { - Font aFont = new Font(_font.getFontName(), _font.getStyle(), (int) (_font.getSize() * zoom)); - //Calculates the width of one break in greographic units - FontMetrics metrics = g.getFontMetrics(aFont); - float unitLegnth = metrics.stringWidth(_unitText) * 2; - float widthNoUnit = (this.getWidth() * zoom - unitLegnth); - long geoBreakWidth = (long) (getGeoWidth(widthNoUnit / _numBreaks)); - - //If the geobreakWidth is less than 1 we return and don't draw anything - if (geoBreakWidth < 1) { - return; - } - - double n = Math.pow(10, String.valueOf(geoBreakWidth).length() - 1); - geoBreakWidth = (long) (Math.floor(geoBreakWidth / n) * n); - - long breakWidth = (long) (getWidth(geoBreakWidth)); - FontMetrics metrics1 = g.getFontMetrics(_font); - float fontHeight = metrics1.getHeight() * zoom; - float leftStart = metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - - //Draw scale text - double scale = geoBreakWidth * getConversionFactor(_unit) * 100 / (breakWidth / 96 * 2.539999918) * zoom; - if (_drawScaleText) { - g.setFont(aFont); - g.setColor(this.getForeColor()); - g.drawString("1 : " + String.format("{0:0,0}", scale), - leftStart - (metrics.stringWidth(String.valueOf(Math.abs(0))) / 2), fontHeight * 2.5F); - } - - //Draw scale bar - switch (_scaleBarType) { - case SCALELINE_1: - drawScaleLine1(g, zoom, aFont, breakWidth, geoBreakWidth); - break; - case SCALELINE_2: - drawScaleLine2(g, zoom, aFont, breakWidth, geoBreakWidth); - break; - case ALTERNATING_BAR: - drawAlternatingBar(g, zoom, aFont, breakWidth, geoBreakWidth); - break; - } - } - - private double getConversionFactor(ScaleBarUnits unit) { - switch (unit) { - case KILOMETERS: - return 1000; - default: - return 1; - } - } - - private double getGeoWidth(double width) { - double geoWidth = width / _layoutMap.getMapFrame().getMapView().getXScale() / getConversionFactor(_unit); - if (_layoutMap.getMapFrame().getMapView().getProjection().isLonLatMap()) { - geoWidth = geoWidth * getLonDistScale(); - } - - return geoWidth; - } - - private double getWidth(double geoWidth) { - double width = geoWidth * _layoutMap.getMapFrame().getMapView().getXScale() * getConversionFactor(_unit); - if (_layoutMap.getMapFrame().getMapView().getProjection().isLonLatMap()) { - width = width / getLonDistScale(); - } - - return width; - } - - private double getLonDistScale() { - //Get meters of one longitude degree - double pY = (_layoutMap.getMapFrame().getMapView().getViewExtent().maxY + _layoutMap.getMapFrame().getMapView().getViewExtent().minY) / 2; - double ProjX = 0, ProjY = pY, pProjX = 1, pProjY = pY; - double dx = Math.abs(ProjX - pProjX); - double dy = Math.abs(ProjY - pProjY); - double dist; - double y = (ProjY + pProjY) / 2; - double factor = Math.cos(y * Math.PI / 180); - dx *= factor; - dist = Math.sqrt(dx * dx + dy * dy); - dist = dist * 111319.5; - - return dist; - } - - private void drawScaleLine1(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight() * zoom; - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 10; - - g.setColor(this.getForeColor()); - g.setStroke(new BasicStroke(zoom)); - g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); - FontMetrics metrics1 = g.getFontMetrics(aFont); - g.setFont(aFont); - for (int i = 0; i <= _numBreaks; i++) { - g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight * 1.6f + yShift)); - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - } - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - private void drawScaleLine2(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight() * zoom; - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 5; - - g.setColor(this.getForeColor()); - g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); - FontMetrics metrics1 = g.getFontMetrics(aFont); - g.setFont(aFont); - for (int i = 0; i <= _numBreaks; i++) { - g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight + (fontHeight * 1.1f) + yShift)); - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - } - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - private void drawAlternatingBar(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { - FontMetrics metrics = g.getFontMetrics(_font); - float fontHeight = metrics.getHeight() * zoom; - float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; - int yShift = 5; - float rHeight = fontHeight / 2; - FontMetrics metrics1 = g.getFontMetrics(aFont); - - boolean isFill = false; - for (int i = 0; i <= _numBreaks; i++) { - if (i < _numBreaks) { - if (isFill) { - g.setColor(this.getForeColor()); - g.fill(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); - } else { - g.setColor(this.getForeColor()); - g.draw(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); - } - } - - g.setColor(this.getForeColor()); - g.setFont(aFont); - g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), - leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); - leftStart = leftStart + breakWidth; - isFill = !isFill; - } - g.setColor(this.getForeColor()); - g.setFont(aFont); - g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); - } - - @Override - public void moveUpdate() { - } - - @Override - public void resizeUpdate() { - } - // - // - - public class LayoutScaleBarBean { - - LayoutScaleBarBean() { - } - // - - /** - * Get scale bar type - * - * @return Scale bar type - */ - public String getScaleBarType() { - return _scaleBarType.toString(); - } - - /** - * Set scale bar type - * - * @param type Scale bar type - */ - public void setScaleBarType(String type) { - _scaleBarType = ScaleBarType.valueOf(type); - } - - /** - * Get if draw neat line - * - * @return If draw neat line - */ - public boolean isDrawNeatLine() { - return _drawNeatLine; - } - - /** - * Set if draw neat line - * - * @param istrue If draw neat line - */ - public void setDrawNeatLine(boolean istrue) { - _drawNeatLine = istrue; - } - - /** - * Get neat line color - * - * @return Neat line color - */ - public Color getNeatLineColor() { - return _neatLineColor; - } - - /** - * Set neat line color - * - * @param color Neat line color - */ - public void setNeatLineColor(Color color) { - _neatLineColor = color; - } - - /** - * Get neat line size - * - * @return Neat line size - */ - public float getNeatLineSize() { - return _neatLineSize; - } - - /** - * Set neat line size - * - * @param size Neat line size - */ - public void setNeatLineSize(float size) { - _neatLineSize = size; - } - - /** - * Get font - * - * @return The font - */ - public Font getFont() { - return _font; - } - - /** - * Set font - * - * @param font The font - */ - public void setFont(Font font) { - _font = font; - } - - /** - * Get break number - * - * @return The break number - */ - public int getBreakNumber() { - return _numBreaks; - } - - /** - * Set break number - * - * @param num Break number - */ - public void setBreakNumber(int num) { - _numBreaks = num; - } - - /** - * Get if draw scale text - * - * @return If draw scale text - */ - public boolean isDrawScaleText() { - return _drawScaleText; - } - - /** - * Set if draw scale text - * - * @param istrue If draw scale text - */ - public void setDrawScaleText(boolean istrue) { - _drawScaleText = istrue; - } - - /** - * Get is draw backcolor - * @return Boolean - */ - public boolean isDrawBackColor(){ - return LayoutScaleBar.this.isDrawBackColor(); - } - - /** - * Set is draw backcolor - * @param value Boolean - */ - public void setDrawBackColor(boolean value){ - LayoutScaleBar.this.setDrawBackColor(value); - } - - /** - * Get background color - * - * @return Background color - */ - public Color getBackColor() { - return LayoutScaleBar.this.getBackColor(); - } - - /** - * Set background color - * - * @param c Background color - */ - public void setBackColor(Color c) { - LayoutScaleBar.this.setBackColor(c); - } - - /** - * Get foreground color - * - * @return Foreground color - */ - public Color getForeColor() { - return LayoutScaleBar.this.getForeColor(); - } - - /** - * Set foreground color - * - * @param c Foreground color - */ - public void setForeColor(Color c) { - LayoutScaleBar.this.setForeColor(c); - } - - /** - * Get left - * - * @return Left - */ - public int getLeft() { - return LayoutScaleBar.this.getLeft(); - } - - /** - * Set left - * - * @param left Left - */ - public void setLeft(int left) { - LayoutScaleBar.this.setLeft(left); - } - - /** - * Get top - * - * @return Top - */ - public int getTop() { - return LayoutScaleBar.this.getTop(); - } - - /** - * Set top - * - * @param top Top - */ - public void setTop(int top) { - LayoutScaleBar.this.setTop(top); - } - - /** - * Get width - * - * @return Width - */ - public int getWidth() { - return LayoutScaleBar.this.getWidth(); - } - - /** - * Set width - * - * @param width Width - */ - public void setWidth(int width) { - LayoutScaleBar.this.setWidth(width); - } - - /** - * Get height - * - * @return Height - */ - public int getHeight() { - return LayoutScaleBar.this.getHeight(); - } - - /** - * Set height - * - * @param height Height - */ - public void setHeight(int height) { - LayoutScaleBar.this.setHeight(height); - } - // - } - - public static class LayoutScaleBarBeanBeanInfo extends BaseBeanInfo { - - public LayoutScaleBarBeanBeanInfo() { - super(LayoutScaleBarBean.class); - ExtendedPropertyDescriptor e = addProperty("scaleBarType"); - e.setCategory("General").setDisplayName("Scale Bar Type"); - e.setPropertyEditorClass(ScaleBarTypeEditor.class); - addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); - addProperty("backColor").setCategory("General").setDisplayName("Background"); - addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); - addProperty("font").setCategory("General").setDisplayName("Font"); - addProperty("drawScaleText").setCategory("General").setDisplayName("Draw Scale Text"); - addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); - addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); - addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); - addProperty("left").setCategory("Location").setDisplayName("Left"); - addProperty("top").setCategory("Location").setDisplayName("Top"); - addProperty("width").setCategory("Location").setDisplayName("Width"); - addProperty("height").setCategory("Location").setDisplayName("Height"); - } - } - - public static class ScaleBarTypeEditor extends ComboBoxPropertyEditor { - - public ScaleBarTypeEditor() { - super(); - ScaleBarType[] lutypes = ScaleBarType.values(); - String[] types = new String[lutypes.length]; - int i = 0; - for (ScaleBarType type : lutypes) { - types[i] = type.toString(); - i += 1; - } - setAvailableValues(types); - } - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.layout; + +import com.l2fprod.common.beans.BaseBeanInfo; +import com.l2fprod.common.beans.ExtendedPropertyDescriptor; +import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor; +import org.meteoinfo.common.PointF; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; + +/** + * + * @author Yaqiang Wang + */ +public class LayoutScaleBar extends LayoutElement { +// + + private LayoutMap _layoutMap; + private boolean _antiAlias; + private Font _font; + private ScaleBarType _scaleBarType; + private ScaleBarUnits _unit; + private String _unitText; + private int _numBreaks; + private boolean _drawNeatLine; + private Color _neatLineColor; + private float _neatLineSize; + private boolean _drawScaleText; + private float _yShiftScale = 2.0f; + // + // + + /** + * Constructor + * + * @param layoutMap The layout map + */ + public LayoutScaleBar(LayoutMap layoutMap) { + super(); + this.setElementType(ElementType.LayoutScaleBar); + this.setResizeAbility(ResizeAbility.ResizeAll); + + this.setWidth(200); + this.setHeight(50); + _layoutMap = layoutMap; + _antiAlias = true; + _scaleBarType = ScaleBarType.SCALELINE_1; + _drawNeatLine = false; + _neatLineColor = Color.black; + _neatLineSize = 1; + _font = new Font("Arial", Font.PLAIN, 12); + _unit = ScaleBarUnits.KILOMETERS; + _unitText = "km"; + _numBreaks = 4; + _drawScaleText = false; + } + // + // + + /** + * Get layout map + * + * @return The layout map + */ + public LayoutMap getLayoutMap() { + return _layoutMap; + } + + /** + * Get scale bar type + * + * @return Scale bar type + */ + public ScaleBarType getScaleBarType() { + return _scaleBarType; + } + + /** + * Set scale bar type + * + * @param type Scale bar type + */ + public void setScaleBarType(ScaleBarType type) { + _scaleBarType = type; + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get font + * + * @return The font + */ + public Font getFont() { + return _font; + } + + /** + * Set font + * + * @param font The font + */ + public void setFont(Font font) { + _font = font; + } + + /** + * Get break number + * + * @return The break number + */ + public int getBreakNumber() { + return _numBreaks; + } + + /** + * Set break number + * + * @param num Break number + */ + public void setBreakNumber(int num) { + _numBreaks = num; + } + + /** + * Get if draw scale text + * + * @return If draw scale text + */ + public boolean isDrawScaleText() { + return _drawScaleText; + } + + /** + * Set if draw scale text + * + * @param istrue If draw scale text + */ + public void setDrawScaleText(boolean istrue) { + _drawScaleText = istrue; + } + // + // + + @Override + public void paint(Graphics2D g) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void paintOnLayout(Graphics2D g, PointF pageLocation, float zoom) { + if (this.isVisible()) { + paintGraphics(g, pageLocation, zoom); + } + } + + /** + * Paint graphics + * + * @param g Graphics + * @param pageLocation Page location + * @param zoom Zoom + */ + public void paintGraphics(Graphics2D g, PointF pageLocation, float zoom) { + AffineTransform oldMatrix = g.getTransform(); + PointF aP = pageToScreen(this.getLeft(), this.getTop(), pageLocation, zoom); + g.translate(aP.X, aP.Y); + g.scale(zoom, zoom); + if (_antiAlias) { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } else { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + //Draw background color + if (this.isDrawBackColor()){ + g.setColor(this.getBackColor()); + g.fill(new Rectangle.Float(0, 0, this.getWidth() * zoom, this.getHeight() * zoom)); + } + + drawScaleBar(g, zoom); + + //Draw neatline + if (_drawNeatLine) { + Rectangle.Float mapRect = new Rectangle.Float(_neatLineSize - 1, _neatLineSize - 1, + (this.getWidth() - _neatLineSize) * zoom, (this.getHeight() - _neatLineSize) * zoom); + g.setColor(_neatLineColor); + g.setStroke(new BasicStroke(_neatLineSize)); + g.draw(mapRect); + } + + g.setTransform(oldMatrix); + } + + private void drawScaleBar(Graphics2D g, float zoom) { + Font aFont = new Font(_font.getFontName(), _font.getStyle(), (int) (_font.getSize() * zoom)); + //Calculates the width of one break in greographic units + FontMetrics metrics = g.getFontMetrics(aFont); + float unitLegnth = metrics.stringWidth(_unitText) * 2; + float widthNoUnit = (this.getWidth() * zoom - unitLegnth); + long geoBreakWidth = (long) (getGeoWidth(widthNoUnit / _numBreaks)); + + //If the geobreakWidth is less than 1 we return and don't draw anything + if (geoBreakWidth < 1) { + return; + } + + double n = Math.pow(10, String.valueOf(geoBreakWidth).length() - 1); + geoBreakWidth = (long) (Math.floor(geoBreakWidth / n) * n); + + long breakWidth = (long) (getWidth(geoBreakWidth)); + FontMetrics metrics1 = g.getFontMetrics(_font); + float fontHeight = metrics1.getHeight() * zoom; + float leftStart = metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + + //Draw scale text + double scale = geoBreakWidth * getConversionFactor(_unit) * 100 / (breakWidth / 96 * 2.539999918) * zoom; + if (_drawScaleText) { + g.setFont(aFont); + g.setColor(this.getForeColor()); + g.drawString("1 : " + String.format("{0:0,0}", scale), + leftStart - (metrics.stringWidth(String.valueOf(Math.abs(0))) / 2), fontHeight * 2.5F); + } + + //Draw scale bar + switch (_scaleBarType) { + case SCALELINE_1: + drawScaleLine1(g, zoom, aFont, breakWidth, geoBreakWidth); + break; + case SCALELINE_2: + drawScaleLine2(g, zoom, aFont, breakWidth, geoBreakWidth); + break; + case ALTERNATING_BAR: + drawAlternatingBar(g, zoom, aFont, breakWidth, geoBreakWidth); + break; + } + } + + private double getConversionFactor(ScaleBarUnits unit) { + switch (unit) { + case KILOMETERS: + return 1000; + default: + return 1; + } + } + + private double getGeoWidth(double width) { + double geoWidth = width / _layoutMap.getMapFrame().getMapView().getXScale() / getConversionFactor(_unit); + if (_layoutMap.getMapFrame().getMapView().getProjection().isLonLatMap()) { + geoWidth = geoWidth * getLonDistScale(); + } + + return geoWidth; + } + + private double getWidth(double geoWidth) { + double width = geoWidth * _layoutMap.getMapFrame().getMapView().getXScale() * getConversionFactor(_unit); + if (_layoutMap.getMapFrame().getMapView().getProjection().isLonLatMap()) { + width = width / getLonDistScale(); + } + + return width; + } + + private double getLonDistScale() { + //Get meters of one longitude degree + double pY = (_layoutMap.getMapFrame().getMapView().getViewExtent().maxY + _layoutMap.getMapFrame().getMapView().getViewExtent().minY) / 2; + double ProjX = 0, ProjY = pY, pProjX = 1, pProjY = pY; + double dx = Math.abs(ProjX - pProjX); + double dy = Math.abs(ProjY - pProjY); + double dist; + double y = (ProjY + pProjY) / 2; + double factor = Math.cos(y * Math.PI / 180); + dx *= factor; + dist = Math.sqrt(dx * dx + dy * dy); + dist = dist * 111319.5; + + return dist; + } + + private void drawScaleLine1(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight() * zoom; + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 10; + + g.setColor(this.getForeColor()); + g.setStroke(new BasicStroke(zoom)); + g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); + FontMetrics metrics1 = g.getFontMetrics(aFont); + g.setFont(aFont); + for (int i = 0; i <= _numBreaks; i++) { + g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight * 1.6f + yShift)); + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + } + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + private void drawScaleLine2(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight() * zoom; + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 5; + + g.setColor(this.getForeColor()); + g.draw(new Line2D.Float(leftStart, fontHeight * 1.6f + yShift, leftStart + (breakWidth * _numBreaks), fontHeight * 1.6f + yShift)); + FontMetrics metrics1 = g.getFontMetrics(aFont); + g.setFont(aFont); + for (int i = 0; i <= _numBreaks; i++) { + g.draw(new Line2D.Float(leftStart, fontHeight * 1.1f + yShift, leftStart, fontHeight + (fontHeight * 1.1f) + yShift)); + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + } + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + private void drawAlternatingBar(Graphics2D g, float zoom, Font aFont, long breakWidth, long geoBreakWidth) { + FontMetrics metrics = g.getFontMetrics(_font); + float fontHeight = metrics.getHeight() * zoom; + float leftStart = metrics.stringWidth(String.valueOf(Math.abs(geoBreakWidth))) / 2F; + int yShift = 5; + float rHeight = fontHeight / 2; + FontMetrics metrics1 = g.getFontMetrics(aFont); + + boolean isFill = false; + for (int i = 0; i <= _numBreaks; i++) { + if (i < _numBreaks) { + if (isFill) { + g.setColor(this.getForeColor()); + g.fill(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); + } else { + g.setColor(this.getForeColor()); + g.draw(new Rectangle.Float(leftStart, fontHeight * 1.1f + yShift, breakWidth, rHeight)); + } + } + + g.setColor(this.getForeColor()); + g.setFont(aFont); + g.drawString(String.valueOf(Math.abs(geoBreakWidth * i)), + leftStart - (metrics1.stringWidth(String.valueOf(Math.abs(geoBreakWidth * i))) / 2), yShift * _yShiftScale); + leftStart = leftStart + breakWidth; + isFill = !isFill; + } + g.setColor(this.getForeColor()); + g.setFont(aFont); + g.drawString(_unitText, leftStart - breakWidth + (fontHeight / 2), fontHeight * 1.1f + yShift * _yShiftScale); + } + + @Override + public void moveUpdate() { + } + + @Override + public void resizeUpdate() { + } + // + // + + public class LayoutScaleBarBean { + + LayoutScaleBarBean() { + } + // + + /** + * Get scale bar type + * + * @return Scale bar type + */ + public String getScaleBarType() { + return _scaleBarType.toString(); + } + + /** + * Set scale bar type + * + * @param type Scale bar type + */ + public void setScaleBarType(String type) { + _scaleBarType = ScaleBarType.valueOf(type); + } + + /** + * Get if draw neat line + * + * @return If draw neat line + */ + public boolean isDrawNeatLine() { + return _drawNeatLine; + } + + /** + * Set if draw neat line + * + * @param istrue If draw neat line + */ + public void setDrawNeatLine(boolean istrue) { + _drawNeatLine = istrue; + } + + /** + * Get neat line color + * + * @return Neat line color + */ + public Color getNeatLineColor() { + return _neatLineColor; + } + + /** + * Set neat line color + * + * @param color Neat line color + */ + public void setNeatLineColor(Color color) { + _neatLineColor = color; + } + + /** + * Get neat line size + * + * @return Neat line size + */ + public float getNeatLineSize() { + return _neatLineSize; + } + + /** + * Set neat line size + * + * @param size Neat line size + */ + public void setNeatLineSize(float size) { + _neatLineSize = size; + } + + /** + * Get font + * + * @return The font + */ + public Font getFont() { + return _font; + } + + /** + * Set font + * + * @param font The font + */ + public void setFont(Font font) { + _font = font; + } + + /** + * Get break number + * + * @return The break number + */ + public int getBreakNumber() { + return _numBreaks; + } + + /** + * Set break number + * + * @param num Break number + */ + public void setBreakNumber(int num) { + _numBreaks = num; + } + + /** + * Get if draw scale text + * + * @return If draw scale text + */ + public boolean isDrawScaleText() { + return _drawScaleText; + } + + /** + * Set if draw scale text + * + * @param istrue If draw scale text + */ + public void setDrawScaleText(boolean istrue) { + _drawScaleText = istrue; + } + + /** + * Get is draw backcolor + * @return Boolean + */ + public boolean isDrawBackColor(){ + return LayoutScaleBar.this.isDrawBackColor(); + } + + /** + * Set is draw backcolor + * @param value Boolean + */ + public void setDrawBackColor(boolean value){ + LayoutScaleBar.this.setDrawBackColor(value); + } + + /** + * Get background color + * + * @return Background color + */ + public Color getBackColor() { + return LayoutScaleBar.this.getBackColor(); + } + + /** + * Set background color + * + * @param c Background color + */ + public void setBackColor(Color c) { + LayoutScaleBar.this.setBackColor(c); + } + + /** + * Get foreground color + * + * @return Foreground color + */ + public Color getForeColor() { + return LayoutScaleBar.this.getForeColor(); + } + + /** + * Set foreground color + * + * @param c Foreground color + */ + public void setForeColor(Color c) { + LayoutScaleBar.this.setForeColor(c); + } + + /** + * Get left + * + * @return Left + */ + public int getLeft() { + return LayoutScaleBar.this.getLeft(); + } + + /** + * Set left + * + * @param left Left + */ + public void setLeft(int left) { + LayoutScaleBar.this.setLeft(left); + } + + /** + * Get top + * + * @return Top + */ + public int getTop() { + return LayoutScaleBar.this.getTop(); + } + + /** + * Set top + * + * @param top Top + */ + public void setTop(int top) { + LayoutScaleBar.this.setTop(top); + } + + /** + * Get width + * + * @return Width + */ + public int getWidth() { + return LayoutScaleBar.this.getWidth(); + } + + /** + * Set width + * + * @param width Width + */ + public void setWidth(int width) { + LayoutScaleBar.this.setWidth(width); + } + + /** + * Get height + * + * @return Height + */ + public int getHeight() { + return LayoutScaleBar.this.getHeight(); + } + + /** + * Set height + * + * @param height Height + */ + public void setHeight(int height) { + LayoutScaleBar.this.setHeight(height); + } + // + } + + public static class LayoutScaleBarBeanBeanInfo extends BaseBeanInfo { + + public LayoutScaleBarBeanBeanInfo() { + super(LayoutScaleBarBean.class); + ExtendedPropertyDescriptor e = addProperty("scaleBarType"); + e.setCategory("General").setDisplayName("Scale Bar Type"); + e.setPropertyEditorClass(ScaleBarTypeEditor.class); + addProperty("drawBackColor").setCategory("General").setDisplayName("Draw Background"); + addProperty("backColor").setCategory("General").setDisplayName("Background"); + addProperty("foreColor").setCategory("General").setDisplayName("Foreground"); + addProperty("font").setCategory("General").setDisplayName("Font"); + addProperty("drawScaleText").setCategory("General").setDisplayName("Draw Scale Text"); + addProperty("drawNeatLine").setCategory("Neat Line").setDisplayName("Draw Neat Line"); + addProperty("neatLineColor").setCategory("Neat Line").setDisplayName("Neat Line Color"); + addProperty("neatLineSize").setCategory("Neat Line").setDisplayName("Neat Line Size"); + addProperty("left").setCategory("Location").setDisplayName("Left"); + addProperty("top").setCategory("Location").setDisplayName("Top"); + addProperty("width").setCategory("Location").setDisplayName("Width"); + addProperty("height").setCategory("Location").setDisplayName("Height"); + } + } + + public static class ScaleBarTypeEditor extends ComboBoxPropertyEditor { + + public ScaleBarTypeEditor() { + super(); + ScaleBarType[] lutypes = ScaleBarType.values(); + String[] types = new String[lutypes.length]; + int i = 0; + for (ScaleBarType type : lutypes) { + types[i] = type.toString(); + i += 1; + } + setAvailableValues(types); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayout.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayout.java index f5fb9a82..73ff4a3b 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayout.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayout.java @@ -18,6 +18,10 @@ import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfTemplate; import com.itextpdf.text.pdf.PdfWriter; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.drawing.Draw; import org.meteoinfo.geoprocess.GeoComputation; import org.meteoinfo.global.colors.ColorUtil; @@ -34,9 +38,6 @@ import org.meteoinfo.global.event.ZoomChangedEvent; import org.meteoinfo.global.FrmMeasurement; import org.meteoinfo.global.FrmMeasurement.MeasureTypes; import org.meteoinfo.global.FrmProperty; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; import org.meteoinfo.layer.VectorLayer; @@ -134,7 +135,6 @@ import org.meteoinfo.data.mapdata.webmap.IWebMapPanel; import org.meteoinfo.data.mapdata.webmap.TileLoadListener; import org.meteoinfo.global.event.IUndoEditListener; import org.meteoinfo.global.event.UndoEditEvent; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.image.ImageUtil; import org.meteoinfo.layer.RasterLayer; import org.meteoinfo.layer.WebMapLayer; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayoutUndoRedo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayoutUndoRedo.java index 8f3b15d5..1b10d64c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayoutUndoRedo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/layout/MapLayoutUndoRedo.java @@ -1,283 +1,282 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.layout; - -import org.meteoinfo.map.*; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; -import javax.swing.undo.AbstractUndoableEdit; -import org.meteoinfo.global.PointF; -import org.meteoinfo.shape.Graphic; - -/** - * - * @author yaqiang - */ -public class MapLayoutUndoRedo { - - // - public class AddElementEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - LayoutElement element; - - public AddElementEdit(MapLayout mapLayout, LayoutElement element) { - this.mapLayout = mapLayout; - this.element = element; - } - - @Override - public String getPresentationName() { - return "Add a Layout Element"; - } - - @Override - public void undo() { - super.undo(); - mapLayout.removeElement(element); - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - mapLayout.addElement(element); - mapLayout.paintGraphics(); - } - } - - public class RemoveElementEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - LayoutElement element; - - public RemoveElementEdit(MapLayout mapLayout, LayoutElement element) { - this.mapLayout = mapLayout; - this.element = element; - } - - @Override - public String getPresentationName() { - return "Remove a Layout Element"; - } - - @Override - public void undo() { - super.undo(); - mapLayout.addElement(element); - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - mapLayout.removeElement(element); - mapLayout.paintGraphics(); - } - } - - public class RemoveElementsEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - List elements; - - public RemoveElementsEdit(MapLayout mapLayout, List elements) { - this.mapLayout = mapLayout; - this.elements = new ArrayList(elements); - } - - @Override - public String getPresentationName() { - return "Remove Layout Elements"; - } - - @Override - public void undo() { - super.undo(); - for (LayoutElement element : elements) { - mapLayout.addElement(element); - } - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - for (LayoutElement element : elements) { - mapLayout.removeElement(element); - } - mapLayout.paintGraphics(); - } - } - - class MoveElementEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - LayoutElement element; - int deltaX; - int deltaY; - - public MoveElementEdit(MapLayout mapLayout, LayoutElement element, int deltaX, int deltaY) { - this.mapLayout = mapLayout; - this.element = element; - this.deltaX = deltaX; - this.deltaY = deltaY; - } - - @Override - public String getPresentationName() { - return "Move a Layout Element"; - } - - @Override - public void undo() { - super.undo(); - element.setLeft(element.getLeft() - deltaX); - element.setTop(element.getTop() - deltaY); - element.moveUpdate(); - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - element.setLeft(element.getLeft() + deltaX); - element.setTop(element.getTop() + deltaY); - element.moveUpdate(); - mapLayout.paintGraphics(); - } - } - - class MoveElementsEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - List elements; - int deltaX; - int deltaY; - - public MoveElementsEdit(MapLayout mapLayout, List elements, int deltaX, int deltaY) { - this.mapLayout = mapLayout; - this.elements = new ArrayList(elements); - this.deltaX = deltaX; - this.deltaY = deltaY; - } - - @Override - public String getPresentationName() { - return "Move a Layout Element"; - } - - @Override - public void undo() { - super.undo(); - for (LayoutElement element : elements) { - element.setLeft(element.getLeft() - deltaX); - element.setTop(element.getTop() - deltaY); - element.moveUpdate(); - } - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - for (LayoutElement element : elements) { - element.setLeft(element.getLeft() + deltaX); - element.setTop(element.getTop() + deltaY); - element.moveUpdate(); - } - mapLayout.paintGraphics(); - } - } - - class MoveGraphicVerticeEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - LayoutGraphic lg; - int verticeIdx; - double newX; - double newY; - double oldX; - double oldY; - - public MoveGraphicVerticeEdit(MapLayout mapLayout, LayoutGraphic lg, int vIdx, double newX, double newY) { - this.mapLayout = mapLayout; - this.lg = lg; - this.verticeIdx = vIdx; - this.newX = newX; - this.newY = newY; - this.oldX = lg.getGraphic().getShape().getPoints().get(vIdx).X; - this.oldY = lg.getGraphic().getShape().getPoints().get(vIdx).Y; - } - - @Override - public String getPresentationName() { - return "Move Grahic vertice"; - } - - @Override - public void undo() { - super.undo(); - lg.verticeEditUpdate(verticeIdx, oldX, oldY); - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - lg.verticeEditUpdate(verticeIdx, newX, newY); - mapLayout.paintGraphics(); - } - } - - class ResizeElementEdit extends AbstractUndoableEdit { - - MapLayout mapLayout; - LayoutElement element; - Rectangle oldRect; - Rectangle newRect; - - public ResizeElementEdit(MapLayout mapLayout, LayoutElement element, Rectangle newRect) { - this.mapLayout = mapLayout; - this.element = element; - this.newRect = (Rectangle)newRect.clone(); - this.oldRect = (Rectangle)element.getBounds().clone(); - } - - @Override - public String getPresentationName() { - return "Resize a Layout Element"; - } - - @Override - public void undo() { - super.undo(); - PointF minP = mapLayout.screenToPage((float) oldRect.x, (float) oldRect.y); - PointF maxP = mapLayout.screenToPage((float) oldRect.x + oldRect.width, oldRect.y + oldRect.height); - element.setLeft((int) minP.X); - element.setTop((int) minP.Y); - element.setWidth((int) (maxP.X - minP.X)); - element.setHeight((int) (maxP.Y - minP.Y)); - element.resizeUpdate(); - mapLayout.paintGraphics(); - } - - @Override - public void redo() { - super.redo(); - PointF minP = mapLayout.screenToPage((float) newRect.x, (float) newRect.y); - PointF maxP = mapLayout.screenToPage((float) newRect.x + newRect.width, newRect.y + newRect.height); - element.setLeft((int) minP.X); - element.setTop((int) minP.Y); - element.setWidth((int) (maxP.X - minP.X)); - element.setHeight((int) (maxP.Y - minP.Y)); - element.resizeUpdate(); - mapLayout.paintGraphics(); - } - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.layout; + +import org.meteoinfo.common.PointF; + +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import javax.swing.undo.AbstractUndoableEdit; + +/** + * + * @author yaqiang + */ +public class MapLayoutUndoRedo { + + // + public class AddElementEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + LayoutElement element; + + public AddElementEdit(MapLayout mapLayout, LayoutElement element) { + this.mapLayout = mapLayout; + this.element = element; + } + + @Override + public String getPresentationName() { + return "Add a Layout Element"; + } + + @Override + public void undo() { + super.undo(); + mapLayout.removeElement(element); + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + mapLayout.addElement(element); + mapLayout.paintGraphics(); + } + } + + public class RemoveElementEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + LayoutElement element; + + public RemoveElementEdit(MapLayout mapLayout, LayoutElement element) { + this.mapLayout = mapLayout; + this.element = element; + } + + @Override + public String getPresentationName() { + return "Remove a Layout Element"; + } + + @Override + public void undo() { + super.undo(); + mapLayout.addElement(element); + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + mapLayout.removeElement(element); + mapLayout.paintGraphics(); + } + } + + public class RemoveElementsEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + List elements; + + public RemoveElementsEdit(MapLayout mapLayout, List elements) { + this.mapLayout = mapLayout; + this.elements = new ArrayList(elements); + } + + @Override + public String getPresentationName() { + return "Remove Layout Elements"; + } + + @Override + public void undo() { + super.undo(); + for (LayoutElement element : elements) { + mapLayout.addElement(element); + } + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + for (LayoutElement element : elements) { + mapLayout.removeElement(element); + } + mapLayout.paintGraphics(); + } + } + + class MoveElementEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + LayoutElement element; + int deltaX; + int deltaY; + + public MoveElementEdit(MapLayout mapLayout, LayoutElement element, int deltaX, int deltaY) { + this.mapLayout = mapLayout; + this.element = element; + this.deltaX = deltaX; + this.deltaY = deltaY; + } + + @Override + public String getPresentationName() { + return "Move a Layout Element"; + } + + @Override + public void undo() { + super.undo(); + element.setLeft(element.getLeft() - deltaX); + element.setTop(element.getTop() - deltaY); + element.moveUpdate(); + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + element.setLeft(element.getLeft() + deltaX); + element.setTop(element.getTop() + deltaY); + element.moveUpdate(); + mapLayout.paintGraphics(); + } + } + + class MoveElementsEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + List elements; + int deltaX; + int deltaY; + + public MoveElementsEdit(MapLayout mapLayout, List elements, int deltaX, int deltaY) { + this.mapLayout = mapLayout; + this.elements = new ArrayList(elements); + this.deltaX = deltaX; + this.deltaY = deltaY; + } + + @Override + public String getPresentationName() { + return "Move a Layout Element"; + } + + @Override + public void undo() { + super.undo(); + for (LayoutElement element : elements) { + element.setLeft(element.getLeft() - deltaX); + element.setTop(element.getTop() - deltaY); + element.moveUpdate(); + } + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + for (LayoutElement element : elements) { + element.setLeft(element.getLeft() + deltaX); + element.setTop(element.getTop() + deltaY); + element.moveUpdate(); + } + mapLayout.paintGraphics(); + } + } + + class MoveGraphicVerticeEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + LayoutGraphic lg; + int verticeIdx; + double newX; + double newY; + double oldX; + double oldY; + + public MoveGraphicVerticeEdit(MapLayout mapLayout, LayoutGraphic lg, int vIdx, double newX, double newY) { + this.mapLayout = mapLayout; + this.lg = lg; + this.verticeIdx = vIdx; + this.newX = newX; + this.newY = newY; + this.oldX = lg.getGraphic().getShape().getPoints().get(vIdx).X; + this.oldY = lg.getGraphic().getShape().getPoints().get(vIdx).Y; + } + + @Override + public String getPresentationName() { + return "Move Grahic vertice"; + } + + @Override + public void undo() { + super.undo(); + lg.verticeEditUpdate(verticeIdx, oldX, oldY); + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + lg.verticeEditUpdate(verticeIdx, newX, newY); + mapLayout.paintGraphics(); + } + } + + class ResizeElementEdit extends AbstractUndoableEdit { + + MapLayout mapLayout; + LayoutElement element; + Rectangle oldRect; + Rectangle newRect; + + public ResizeElementEdit(MapLayout mapLayout, LayoutElement element, Rectangle newRect) { + this.mapLayout = mapLayout; + this.element = element; + this.newRect = (Rectangle)newRect.clone(); + this.oldRect = (Rectangle)element.getBounds().clone(); + } + + @Override + public String getPresentationName() { + return "Resize a Layout Element"; + } + + @Override + public void undo() { + super.undo(); + PointF minP = mapLayout.screenToPage((float) oldRect.x, (float) oldRect.y); + PointF maxP = mapLayout.screenToPage((float) oldRect.x + oldRect.width, oldRect.y + oldRect.height); + element.setLeft((int) minP.X); + element.setTop((int) minP.Y); + element.setWidth((int) (maxP.X - minP.X)); + element.setHeight((int) (maxP.Y - minP.Y)); + element.resizeUpdate(); + mapLayout.paintGraphics(); + } + + @Override + public void redo() { + super.redo(); + PointF minP = mapLayout.screenToPage((float) newRect.x, (float) newRect.y); + PointF maxP = mapLayout.screenToPage((float) newRect.x + newRect.width, newRect.y + newRect.height); + element.setLeft((int) minP.X); + element.setTop((int) minP.Y); + element.setWidth((int) (maxP.X - minP.X)); + element.setHeight((int) (maxP.Y - minP.Y)); + element.resizeUpdate(); + mapLayout.paintGraphics(); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ChartBreak.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ChartBreak.java index cbd3c3c8..0fc0097e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ChartBreak.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ChartBreak.java @@ -1,644 +1,645 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.legend; - -import java.awt.Color; -import java.awt.Font; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointF; -import org.meteoinfo.shape.ShapeTypes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Chart break class - * - * @author Yaqiang Wang - */ -public class ChartBreak extends ColorBreak { - // - - private ChartTypes _chartType; - private List _chartData; - private int _xShift; - private int _yShift; - private LegendScheme _legendScheme; - private int _maxSize; - private int _minSize; - private float _maxValue; - private float _minValue; - private int _barWidth; - private AlignType _alignType; - private boolean _view3D; - private int _thickness; - private int _shpIdx; - private boolean drawLabel; - private Font labelFont; - private Color labelColor; - private int decimalDigits; - // - // - - /** - * Constructor - * - * @param chartType Chart type - */ - public ChartBreak(ChartTypes chartType) { - super(); - this.setBreakType(BreakTypes.ChartBreak); - _chartType = chartType; - _chartData = new ArrayList<>(); - _xShift = 0; - _yShift = 0; - _legendScheme = new LegendScheme(ShapeTypes.Polygon); - _maxSize = 50; - _minSize = 10; - _barWidth = 10; - _alignType = AlignType.Center; - _view3D = false; - _thickness = 5; - _shpIdx = 0; - drawLabel = false; - labelFont = new Font("Arial", Font.PLAIN, 12); - labelColor = Color.black; - this.decimalDigits = 0; - } - // - // - - /** - * Get chart type - * - * @return Chart type - */ - public ChartTypes getChartType() { - return _chartType; - } - - /** - * Set chart type - * - * @param cType Chart type - */ - public void setChartType(ChartTypes cType) { - _chartType = cType; - } - - /** - * Get chart data - * - * @return Chart data list - */ - public List getChartData() { - return _chartData; - } - - /** - * Set chart data - * - * @param cData Chart data list - */ - public void setChartData(List cData) { - _chartData = cData; - } - - /** - * Get chart item number - * - * @return Chart item number - */ - public int getItemNum() { - return _chartData.size(); - } - - /** - * Get chart data sum - * - * @return Chart data sum - */ - public float getDataSum() { - float sum = 0; - for (float d : _chartData) { - sum += d; - } - return sum; - } - - /** - * Get x shift - * - * @return X shift - */ - public int getXShift() { - return _xShift; - } - - /** - * Set x shift - * - * @param xshift X shift - */ - public void setXShift(int xshift) { - _xShift = xshift; - } - - /** - * Get y shift - * - * @return Y shift - */ - public int getYShift() { - return _yShift; - } - - /** - * Set y shift - * - * @param yshift Y shift - */ - public void setYShift(int yshift) { - _yShift = yshift; - } - - /** - * Get legend scheme - * - * @return Legend Scheme - */ - public LegendScheme getLegendScheme() { - return _legendScheme; - } - - /** - * Set legend scheme - * - * @param ls Legend scheme - */ - public void setLegendScheme(LegendScheme ls) { - _legendScheme = ls; - } - - /** - * Get maximum size - * - * @return Maximum size - */ - public int getMaxSize() { - return _maxSize; - } - - /** - * Set maximum size - * - * @param maxSize Maximum size - */ - public void setMaxSize(int maxSize) { - _maxSize = maxSize; - } - - /** - * Get minimum size - * - * @return Minimum size - */ - public int getMinSize() { - return _minSize; - } - - /** - * Set minimum size - * - * @param minSize Minimum size - */ - public void setMinSize(int minSize) { - _minSize = minSize; - } - - /** - * Get maximum value - * - * @return Maximum value - */ - public float getMaxValue() { - return _maxValue; - } - - /** - * Set maximum value - * - * @param maxValue Maximum value - */ - public void setMaxValue(float maxValue) { - _maxValue = maxValue; - } - - /** - * Get minimum value - * - * @return Minimum value - */ - public float getMinValue() { - return _minValue; - } - - /** - * Set minimum value - * - * @param minValue Minimum value - */ - public void setMinValue(float minValue) { - _minValue = minValue; - } - - /** - * Get bar width - * - * @return Bar width - */ - public int getBarWidth() { - return _barWidth; - } - - /** - * Set bar width - * - * @param width Bar width - */ - public void setBarWidth(int width) { - _barWidth = width; - } - - /** - * Get align type - * - * @return Align type - */ - public AlignType getAlignType() { - return _alignType; - } - - /** - * Set align type - * - * @param atype Align type - */ - public void setAlignType(AlignType atype) { - _alignType = atype; - } - - /** - * Get if view 3D - * - * @return Boolean - */ - public boolean isView3D() { - return _view3D; - } - - /** - * Set if view 3D - * - * @param v3d - */ - public void setView3D(boolean v3d) { - _view3D = v3d; - } - - /** - * Get 3D thickness - * - * @return 3D thickness - */ - public int getThickness() { - return _thickness; - } - - /** - * Set 3D thickness - * - * @param thickness 3D thickness - */ - public void setThickness(int thickness) { - _thickness = thickness; - } - - /** - * Get shape index - * - * @return Shape index - */ - public int getShapeIndex() { - return _shpIdx; - } - - /** - * Set shape index - * - * @param sIdx Shape index - */ - public void setShapeIndex(int sIdx) { - _shpIdx = sIdx; - } - - /** - * Get if draw label - * @return Boolean - */ - public boolean isDrawLabel(){ - return this.drawLabel; - } - - /** - * Set if draw label - * @param value Boolean - */ - public void setDrawLabel(boolean value){ - this.drawLabel = value; - } - - /** - * Get label font - * @return Label font - */ - public Font getLabelFont(){ - return this.labelFont; - } - - /** - * Set label font - * @param value Label font - */ - public void setLabelFont(Font value){ - this.labelFont = value; - } - - /** - * Get label color - * @return Label color - */ - public Color getLabelColor(){ - return this.labelColor; - } - - /** - * Set label color - * @param value Label color - */ - public void setLabelColor(Color value){ - this.labelColor = value; - } - - /** - * Get decimal digits - * @return Decimal digits - */ - public int getDecimalDigits(){ - return this.decimalDigits; - } - - /** - * Set decimal digits - * @param value Decimal digits - */ - public void setDecimalDigits(int value){ - this.decimalDigits = value; - } - // - // - - /** - * Get bar heights - * - * @return Bar heights - */ - public List getBarHeights() { - List heights = new ArrayList<>(); - int i, h; - for (i = 0; i < _chartData.size(); i++) { - if (_minSize == 0) { - h = (int) (_chartData.get(i) / _maxValue * _maxSize); - } else { - h = (int) ((_chartData.get(i) - _minValue) / (_maxValue - _minValue) - * (_maxSize - _minSize) + _minSize); - } - heights.add(h); - } - - return heights; - } - - /** - * Get chart width - * - * @return Chart width - */ - public int getWidth() { - int width = 0; - switch (_chartType) { - case BarChart: - width = _barWidth * _chartData.size(); - if (_view3D) { - width += _thickness; - } - break; - case PieChart: - if (_minSize == _maxSize) { - width = _maxSize; - } else if (_minSize == 0) { - width = (int) (this.getDataSum() / _maxValue * _maxSize); - } else { - width = (int) ((this.getDataSum() - _minValue) / (_maxValue - _minValue) - * (_maxSize - _minSize) + _minSize); - } - break; - } - - return width; - } - - /** - * Get chart height - * - * @return Chart height - */ - public int getHeight() { - int height = 0; - switch (_chartType) { - case BarChart: - height = Collections.max(getBarHeights()); - break; - case PieChart: - if (_minSize == _maxSize) { - height = _maxSize; - } else if (_minSize == 0) { - height = (int) (this.getDataSum() / _maxValue * _maxSize); - } else { - height = (int) ((this.getDataSum() - _minValue) / (_maxValue - _minValue) - * (_maxSize - _minSize) + _minSize); - } - - if (_view3D) { - height = height * 2 / 3; - } - break; - } - - if (_view3D) { - height += _thickness; - } - - return height; - } - - /** - * Get pie angles - * - * @return Pie angle list - */ - public List> getPieAngles() { - List> angles = new ArrayList<>(); - float sum = this.getDataSum(); - float startAngle = 0; - float sweepAngle; - for (Float value : _chartData) { - sweepAngle = value / sum * 360; - List ssa = new ArrayList<>(); - ssa.add(startAngle); - ssa.add(sweepAngle); - angles.add(ssa); - startAngle += sweepAngle; - if (startAngle > 360) { - startAngle = startAngle - 360; - } - } - - return angles; - } - - /** - * Get pie ratios - * - * @return Pie ratio list - */ - public List getPieRatios() { - List ratios = new ArrayList<>(); - float sum = this.getDataSum(); - float ratio; - for (Float value : _chartData) { - ratio = value / sum; - ratios.add(ratio); - } - - return ratios; - } - - /** - * Clone - * - * @return ChartBreak object - */ - @Override - public Object clone() { - ChartBreak aCB = new ChartBreak(_chartType); - aCB.setCaption(this.getCaption()); - aCB.setAlignType(_alignType); - aCB.setBarWidth(_barWidth); - aCB.setChartData(new ArrayList<>(_chartData)); - aCB.setColor(this.getColor()); - aCB.setDrawShape(this.isDrawShape()); - aCB.setLegendScheme(_legendScheme); - aCB.setMaxSize(_maxSize); - aCB.setMaxValue(_maxValue); - aCB.setMinSize(_minSize); - aCB.setMinValue(_minValue); - aCB.setThickness(_thickness); - aCB.setView3D(_view3D); - aCB.setXShift(_xShift); - aCB.setYShift(_yShift); - aCB.setDrawLabel(this.drawLabel); - aCB.setLabelColor(this.labelColor); - aCB.setLabelFont(labelFont); - aCB.setDecimalDigits(this.decimalDigits); - - return aCB; - } - - /** - * Get sample chart break - * - * @return Sample chart break - */ - public ChartBreak getSampleChartBreak() { - ChartBreak aCB = (ChartBreak) clone(); - int i; - switch (aCB.getChartType()) { - case BarChart: - float min = aCB.getMaxValue() / aCB.getItemNum(); - float dv = (aCB.getMaxValue() - min) / aCB.getItemNum(); - for (i = 0; i < aCB.getItemNum(); i++) { - aCB.getChartData().set(i, min + dv * i); - } - break; - case PieChart: - //float sum = (aCB.getMaxValue() - aCB.getMinValue()) * 2 / 3; - float sum = aCB.getMaxValue(); - float data = sum / aCB.getItemNum(); - for (i = 0; i < aCB.getItemNum(); i++) { - aCB.getChartData().set(i, data); - } - aCB.setMinSize(aCB._maxSize); - //aCB.setMaxSize(20); - break; - } - - return aCB; - } - - /** - * Get draw extent - * - * @param aPoint start point - * @return draw extent - */ - public Extent getDrawExtent(PointF aPoint) { - int width = this.getWidth(); - int height = this.getHeight(); - switch (_alignType) { - case Center: - aPoint.X -= width / 2; - aPoint.Y += height / 2; - break; - case Left: - aPoint.X -= width; - aPoint.Y += height / 2; - break; - case Right: - aPoint.Y += height / 2; - break; - } - aPoint.X += _xShift; - aPoint.Y -= _yShift; - - Extent aExtent = new Extent(); - aExtent.minX = aPoint.X; - aExtent.maxX = aPoint.X + width; - aExtent.minY = aPoint.Y - height; - aExtent.maxY = aPoint.Y; - - return aExtent; - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.legend; + +import java.awt.Color; +import java.awt.Font; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointF; +import org.meteoinfo.shape.ShapeTypes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Chart break class + * + * @author Yaqiang Wang + */ +public class ChartBreak extends ColorBreak { + // + + private ChartTypes _chartType; + private List _chartData; + private int _xShift; + private int _yShift; + private LegendScheme _legendScheme; + private int _maxSize; + private int _minSize; + private float _maxValue; + private float _minValue; + private int _barWidth; + private AlignType _alignType; + private boolean _view3D; + private int _thickness; + private int _shpIdx; + private boolean drawLabel; + private Font labelFont; + private Color labelColor; + private int decimalDigits; + // + // + + /** + * Constructor + * + * @param chartType Chart type + */ + public ChartBreak(ChartTypes chartType) { + super(); + this.setBreakType(BreakTypes.ChartBreak); + _chartType = chartType; + _chartData = new ArrayList<>(); + _xShift = 0; + _yShift = 0; + _legendScheme = new LegendScheme(ShapeTypes.Polygon); + _maxSize = 50; + _minSize = 10; + _barWidth = 10; + _alignType = AlignType.Center; + _view3D = false; + _thickness = 5; + _shpIdx = 0; + drawLabel = false; + labelFont = new Font("Arial", Font.PLAIN, 12); + labelColor = Color.black; + this.decimalDigits = 0; + } + // + // + + /** + * Get chart type + * + * @return Chart type + */ + public ChartTypes getChartType() { + return _chartType; + } + + /** + * Set chart type + * + * @param cType Chart type + */ + public void setChartType(ChartTypes cType) { + _chartType = cType; + } + + /** + * Get chart data + * + * @return Chart data list + */ + public List getChartData() { + return _chartData; + } + + /** + * Set chart data + * + * @param cData Chart data list + */ + public void setChartData(List cData) { + _chartData = cData; + } + + /** + * Get chart item number + * + * @return Chart item number + */ + public int getItemNum() { + return _chartData.size(); + } + + /** + * Get chart data sum + * + * @return Chart data sum + */ + public float getDataSum() { + float sum = 0; + for (float d : _chartData) { + sum += d; + } + return sum; + } + + /** + * Get x shift + * + * @return X shift + */ + public int getXShift() { + return _xShift; + } + + /** + * Set x shift + * + * @param xshift X shift + */ + public void setXShift(int xshift) { + _xShift = xshift; + } + + /** + * Get y shift + * + * @return Y shift + */ + public int getYShift() { + return _yShift; + } + + /** + * Set y shift + * + * @param yshift Y shift + */ + public void setYShift(int yshift) { + _yShift = yshift; + } + + /** + * Get legend scheme + * + * @return Legend Scheme + */ + public LegendScheme getLegendScheme() { + return _legendScheme; + } + + /** + * Set legend scheme + * + * @param ls Legend scheme + */ + public void setLegendScheme(LegendScheme ls) { + _legendScheme = ls; + } + + /** + * Get maximum size + * + * @return Maximum size + */ + public int getMaxSize() { + return _maxSize; + } + + /** + * Set maximum size + * + * @param maxSize Maximum size + */ + public void setMaxSize(int maxSize) { + _maxSize = maxSize; + } + + /** + * Get minimum size + * + * @return Minimum size + */ + public int getMinSize() { + return _minSize; + } + + /** + * Set minimum size + * + * @param minSize Minimum size + */ + public void setMinSize(int minSize) { + _minSize = minSize; + } + + /** + * Get maximum value + * + * @return Maximum value + */ + public float getMaxValue() { + return _maxValue; + } + + /** + * Set maximum value + * + * @param maxValue Maximum value + */ + public void setMaxValue(float maxValue) { + _maxValue = maxValue; + } + + /** + * Get minimum value + * + * @return Minimum value + */ + public float getMinValue() { + return _minValue; + } + + /** + * Set minimum value + * + * @param minValue Minimum value + */ + public void setMinValue(float minValue) { + _minValue = minValue; + } + + /** + * Get bar width + * + * @return Bar width + */ + public int getBarWidth() { + return _barWidth; + } + + /** + * Set bar width + * + * @param width Bar width + */ + public void setBarWidth(int width) { + _barWidth = width; + } + + /** + * Get align type + * + * @return Align type + */ + public AlignType getAlignType() { + return _alignType; + } + + /** + * Set align type + * + * @param atype Align type + */ + public void setAlignType(AlignType atype) { + _alignType = atype; + } + + /** + * Get if view 3D + * + * @return Boolean + */ + public boolean isView3D() { + return _view3D; + } + + /** + * Set if view 3D + * + * @param v3d + */ + public void setView3D(boolean v3d) { + _view3D = v3d; + } + + /** + * Get 3D thickness + * + * @return 3D thickness + */ + public int getThickness() { + return _thickness; + } + + /** + * Set 3D thickness + * + * @param thickness 3D thickness + */ + public void setThickness(int thickness) { + _thickness = thickness; + } + + /** + * Get shape index + * + * @return Shape index + */ + public int getShapeIndex() { + return _shpIdx; + } + + /** + * Set shape index + * + * @param sIdx Shape index + */ + public void setShapeIndex(int sIdx) { + _shpIdx = sIdx; + } + + /** + * Get if draw label + * @return Boolean + */ + public boolean isDrawLabel(){ + return this.drawLabel; + } + + /** + * Set if draw label + * @param value Boolean + */ + public void setDrawLabel(boolean value){ + this.drawLabel = value; + } + + /** + * Get label font + * @return Label font + */ + public Font getLabelFont(){ + return this.labelFont; + } + + /** + * Set label font + * @param value Label font + */ + public void setLabelFont(Font value){ + this.labelFont = value; + } + + /** + * Get label color + * @return Label color + */ + public Color getLabelColor(){ + return this.labelColor; + } + + /** + * Set label color + * @param value Label color + */ + public void setLabelColor(Color value){ + this.labelColor = value; + } + + /** + * Get decimal digits + * @return Decimal digits + */ + public int getDecimalDigits(){ + return this.decimalDigits; + } + + /** + * Set decimal digits + * @param value Decimal digits + */ + public void setDecimalDigits(int value){ + this.decimalDigits = value; + } + // + // + + /** + * Get bar heights + * + * @return Bar heights + */ + public List getBarHeights() { + List heights = new ArrayList<>(); + int i, h; + for (i = 0; i < _chartData.size(); i++) { + if (_minSize == 0) { + h = (int) (_chartData.get(i) / _maxValue * _maxSize); + } else { + h = (int) ((_chartData.get(i) - _minValue) / (_maxValue - _minValue) + * (_maxSize - _minSize) + _minSize); + } + heights.add(h); + } + + return heights; + } + + /** + * Get chart width + * + * @return Chart width + */ + public int getWidth() { + int width = 0; + switch (_chartType) { + case BarChart: + width = _barWidth * _chartData.size(); + if (_view3D) { + width += _thickness; + } + break; + case PieChart: + if (_minSize == _maxSize) { + width = _maxSize; + } else if (_minSize == 0) { + width = (int) (this.getDataSum() / _maxValue * _maxSize); + } else { + width = (int) ((this.getDataSum() - _minValue) / (_maxValue - _minValue) + * (_maxSize - _minSize) + _minSize); + } + break; + } + + return width; + } + + /** + * Get chart height + * + * @return Chart height + */ + public int getHeight() { + int height = 0; + switch (_chartType) { + case BarChart: + height = Collections.max(getBarHeights()); + break; + case PieChart: + if (_minSize == _maxSize) { + height = _maxSize; + } else if (_minSize == 0) { + height = (int) (this.getDataSum() / _maxValue * _maxSize); + } else { + height = (int) ((this.getDataSum() - _minValue) / (_maxValue - _minValue) + * (_maxSize - _minSize) + _minSize); + } + + if (_view3D) { + height = height * 2 / 3; + } + break; + } + + if (_view3D) { + height += _thickness; + } + + return height; + } + + /** + * Get pie angles + * + * @return Pie angle list + */ + public List> getPieAngles() { + List> angles = new ArrayList<>(); + float sum = this.getDataSum(); + float startAngle = 0; + float sweepAngle; + for (Float value : _chartData) { + sweepAngle = value / sum * 360; + List ssa = new ArrayList<>(); + ssa.add(startAngle); + ssa.add(sweepAngle); + angles.add(ssa); + startAngle += sweepAngle; + if (startAngle > 360) { + startAngle = startAngle - 360; + } + } + + return angles; + } + + /** + * Get pie ratios + * + * @return Pie ratio list + */ + public List getPieRatios() { + List ratios = new ArrayList<>(); + float sum = this.getDataSum(); + float ratio; + for (Float value : _chartData) { + ratio = value / sum; + ratios.add(ratio); + } + + return ratios; + } + + /** + * Clone + * + * @return ChartBreak object + */ + @Override + public Object clone() { + ChartBreak aCB = new ChartBreak(_chartType); + aCB.setCaption(this.getCaption()); + aCB.setAlignType(_alignType); + aCB.setBarWidth(_barWidth); + aCB.setChartData(new ArrayList<>(_chartData)); + aCB.setColor(this.getColor()); + aCB.setDrawShape(this.isDrawShape()); + aCB.setLegendScheme(_legendScheme); + aCB.setMaxSize(_maxSize); + aCB.setMaxValue(_maxValue); + aCB.setMinSize(_minSize); + aCB.setMinValue(_minValue); + aCB.setThickness(_thickness); + aCB.setView3D(_view3D); + aCB.setXShift(_xShift); + aCB.setYShift(_yShift); + aCB.setDrawLabel(this.drawLabel); + aCB.setLabelColor(this.labelColor); + aCB.setLabelFont(labelFont); + aCB.setDecimalDigits(this.decimalDigits); + + return aCB; + } + + /** + * Get sample chart break + * + * @return Sample chart break + */ + public ChartBreak getSampleChartBreak() { + ChartBreak aCB = (ChartBreak) clone(); + int i; + switch (aCB.getChartType()) { + case BarChart: + float min = aCB.getMaxValue() / aCB.getItemNum(); + float dv = (aCB.getMaxValue() - min) / aCB.getItemNum(); + for (i = 0; i < aCB.getItemNum(); i++) { + aCB.getChartData().set(i, min + dv * i); + } + break; + case PieChart: + //float sum = (aCB.getMaxValue() - aCB.getMinValue()) * 2 / 3; + float sum = aCB.getMaxValue(); + float data = sum / aCB.getItemNum(); + for (i = 0; i < aCB.getItemNum(); i++) { + aCB.getChartData().set(i, data); + } + aCB.setMinSize(aCB._maxSize); + //aCB.setMaxSize(20); + break; + } + + return aCB; + } + + /** + * Get draw extent + * + * @param aPoint start point + * @return draw extent + */ + public Extent getDrawExtent(PointF aPoint) { + int width = this.getWidth(); + int height = this.getHeight(); + switch (_alignType) { + case Center: + aPoint.X -= width / 2; + aPoint.Y += height / 2; + break; + case Left: + aPoint.X -= width; + aPoint.Y += height / 2; + break; + case Right: + aPoint.Y += height / 2; + break; + } + aPoint.X += _xShift; + aPoint.Y -= _yShift; + + Extent aExtent = new Extent(); + aExtent.minX = aPoint.X; + aExtent.maxX = aPoint.X + width; + aExtent.minY = aPoint.Y - height; + aExtent.maxY = aPoint.Y; + + return aExtent; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ColorScheme.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ColorScheme.java index 860d494b..6b750fe3 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ColorScheme.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/ColorScheme.java @@ -1,53 +1,54 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.legend; - -import java.awt.Color; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.colors.ColorMap; - -/** - * - * @author yaqiang - */ -public class ColorScheme { - // - private double[] values; - private Color[] colors; - // - // - /** - * Constructor - * @param min Minimum value - * @param max Maximum value - * @param n Level number - * @param ct Color table - */ - public ColorScheme(double min, double max, int n, ColorMap ct){ - this.values = MIMath.getIntervalValues(min, max, n); - this.colors = ct.getColors(n); - } - // - // - /** - * Get values - * @return Values - */ - public double[] getValues(){ - return this.values; - } - - /** - * Get colors - * @return Colors - */ - public Color[] getColors(){ - return this.colors; - } - // - // - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.legend; + +import java.awt.Color; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.global.colors.ColorMap; + +/** + * + * @author yaqiang + */ +public class ColorScheme { + // + private double[] values; + private Color[] colors; + // + // + /** + * Constructor + * @param min Minimum value + * @param max Maximum value + * @param n Level number + * @param ct Color table + */ + public ColorScheme(double min, double max, int n, ColorMap ct){ + this.values = MIMath.getIntervalValues(min, max, n); + this.colors = ct.getColors(n); + } + // + // + /** + * Get values + * @return Values + */ + public double[] getValues(){ + return this.values; + } + + /** + * Get colors + * @return Colors + */ + public Color[] getColors(){ + return this.colors; + } + // + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendSet.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendSet.java index f10047ea..7e25a363 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendSet.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendSet.java @@ -5,7 +5,7 @@ package org.meteoinfo.legend; import com.formdev.flatlaf.extras.FlatSVGIcon; -import org.meteoinfo.global.GenericFileFilter; +import org.meteoinfo.common.GenericFileFilter; import org.meteoinfo.shape.ShapeTypes; import java.awt.Color; import java.io.File; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmPointSymbolSet.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmPointSymbolSet.java index b73df7f1..e1afbbdd 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmPointSymbolSet.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmPointSymbolSet.java @@ -4,7 +4,7 @@ */ package org.meteoinfo.legend; -import org.meteoinfo.global.util.GlobalUtil; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.global.event.ISelectedCellChangedListener; import org.meteoinfo.global.event.SelectedCellChangedEvent; import org.meteoinfo.layout.MapLayout; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LabelBreak.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LabelBreak.java index 80e70eeb..ede7d29f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LabelBreak.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LabelBreak.java @@ -1,243 +1,243 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.legend; - -import org.meteoinfo.global.event.ISizeChangedListener; -import org.meteoinfo.global.event.SizeChangedEvent; -import java.awt.Color; -import java.awt.Font; -import java.util.HashMap; -import javax.swing.event.EventListenerList; -import org.meteoinfo.global.util.GlobalUtil; - -/** - * Label break class - * - * @author Yaqiang Wang - */ -public class LabelBreak extends ColorBreak { - // - - private EventListenerList _listeners = new EventListenerList(); - private String _text; - private float _angle; - private Font _font; - private AlignType _alignType; - private float _xShift; - private float _yShift; - // - // - - public LabelBreak() { - super(); - this.setBreakType(BreakTypes.LabelBreak); - _text = ""; - _angle = 0; - this.setColor(Color.black); - _font = new Font(GlobalUtil.getDefaultFontName(), Font.PLAIN, 7); - _alignType = AlignType.Center; - _yShift = 0; - } - // - // - - /** - * Get text string - * - * @return Text string - */ - public String getText() { - return _text; - } - - /** - * Set text string and fire size changed event - * - * @param text Text string - */ - public void setText(String text) { - _text = text; - this.fireSizeChangedEvent(new SizeChangedEvent(this)); - } - - /** - * Get angle - * - * @return Angle - */ - public float getAngle() { - return _angle; - } - - /** - * Set angle - * - * @param angle Angle - */ - public void setAngle(float angle) { - _angle = angle; - } - - /** - * Get font - * - * @return Font - */ - public Font getFont() { - return _font; - } - - /** - * Set font and fire size changed event - * - * @param f Font - */ - public void setFont(Font f) { - _font = f; - this.fireSizeChangedEvent(new SizeChangedEvent(this)); - } - - /** - * Get align type - * - * @return Align type - */ - public AlignType getAlignType() { - return _alignType; - } - - /** - * Set align type - * - * @param at Align type - */ - public void setAlignType(AlignType at) { - _alignType = at; - } - - /** - * Get y shift - * - * @return Y shift - */ - public float getYShift() { - return _yShift; - } - - /** - * Set y shift - * - * @param yshift Y shift - */ - public void setYShift(float yshift) { - _yShift = yshift; - } - - /** - * Get x shift - * - * @return X shift - */ - public float getXShift() { - return _xShift; - } - - /** - * Set x shift - * - * @param xshift X shift - */ - public void setXShift(float xshift) { - _xShift = xshift; - } - - // - // - /** - * Get property object - * - * @return Property object - */ - @Override - public Object getPropertyObject() { - HashMap objAttr = new HashMap(); - objAttr.put("Text", "Text"); - objAttr.put("Angle", "Angle"); - objAttr.put("Color", "Color"); - objAttr.put("Font", "Font"); - //objAttr.Add("AlignType", "AlignType"); - //objAttr.Add("YShift", "YShift"); - //CustomProperty cp = new CustomProperty(this, objAttr); - return objAttr; - } - - /** - * Clone - * - * @return LabelBreak object - */ - @Override - public Object clone() { - LabelBreak aCB = new LabelBreak(); - aCB.setCaption(this.getCaption()); - aCB.setColor(this.getColor()); - aCB.setDrawShape(this.isDrawShape()); - aCB.setEndValue(this.getEndValue()); - aCB.setNoData(this.isNoData()); - aCB.setStartValue(this.getStartValue()); - aCB.setAngle(_angle); - aCB.setText(_text); - aCB.setFont(_font); - aCB.setAlignType(_alignType); - aCB.setYShift(_yShift); - aCB.setXShift(_xShift); - - return aCB; - } - // - // - - /** - * Add size changed listener - * - * @param scl SizeChangedListener interface - */ - public void addSizeChangedListener(ISizeChangedListener scl) { - this._listeners.add(ISizeChangedListener.class, scl); - } - - /** - * Remove size changed listener - * - * @param scl SizeChangedListener interface - */ - public void removeSizeChangedListener(ISizeChangedListener scl) { - this._listeners.remove(ISizeChangedListener.class, scl); - } - - /** - * Fire size changed event - * - * @param event SizeChangedEvent - */ - public void fireSizeChangedEvent(SizeChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ISizeChangedListener.class) { - ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); - } - } - } - // + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.legend; + +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.global.event.ISizeChangedListener; +import org.meteoinfo.global.event.SizeChangedEvent; +import java.awt.Color; +import java.awt.Font; +import java.util.HashMap; +import javax.swing.event.EventListenerList; + + /** + * Label break class + * + * @author Yaqiang Wang + */ +public class LabelBreak extends ColorBreak { + // + + private EventListenerList _listeners = new EventListenerList(); + private String _text; + private float _angle; + private Font _font; + private AlignType _alignType; + private float _xShift; + private float _yShift; + // + // + + public LabelBreak() { + super(); + this.setBreakType(BreakTypes.LabelBreak); + _text = ""; + _angle = 0; + this.setColor(Color.black); + _font = new Font(GlobalUtil.getDefaultFontName(), Font.PLAIN, 7); + _alignType = AlignType.Center; + _yShift = 0; + } + // + // + + /** + * Get text string + * + * @return Text string + */ + public String getText() { + return _text; + } + + /** + * Set text string and fire size changed event + * + * @param text Text string + */ + public void setText(String text) { + _text = text; + this.fireSizeChangedEvent(new SizeChangedEvent(this)); + } + + /** + * Get angle + * + * @return Angle + */ + public float getAngle() { + return _angle; + } + + /** + * Set angle + * + * @param angle Angle + */ + public void setAngle(float angle) { + _angle = angle; + } + + /** + * Get font + * + * @return Font + */ + public Font getFont() { + return _font; + } + + /** + * Set font and fire size changed event + * + * @param f Font + */ + public void setFont(Font f) { + _font = f; + this.fireSizeChangedEvent(new SizeChangedEvent(this)); + } + + /** + * Get align type + * + * @return Align type + */ + public AlignType getAlignType() { + return _alignType; + } + + /** + * Set align type + * + * @param at Align type + */ + public void setAlignType(AlignType at) { + _alignType = at; + } + + /** + * Get y shift + * + * @return Y shift + */ + public float getYShift() { + return _yShift; + } + + /** + * Set y shift + * + * @param yshift Y shift + */ + public void setYShift(float yshift) { + _yShift = yshift; + } + + /** + * Get x shift + * + * @return X shift + */ + public float getXShift() { + return _xShift; + } + + /** + * Set x shift + * + * @param xshift X shift + */ + public void setXShift(float xshift) { + _xShift = xshift; + } + + // + // + /** + * Get property object + * + * @return Property object + */ + @Override + public Object getPropertyObject() { + HashMap objAttr = new HashMap(); + objAttr.put("Text", "Text"); + objAttr.put("Angle", "Angle"); + objAttr.put("Color", "Color"); + objAttr.put("Font", "Font"); + //objAttr.Add("AlignType", "AlignType"); + //objAttr.Add("YShift", "YShift"); + //CustomProperty cp = new CustomProperty(this, objAttr); + return objAttr; + } + + /** + * Clone + * + * @return LabelBreak object + */ + @Override + public Object clone() { + LabelBreak aCB = new LabelBreak(); + aCB.setCaption(this.getCaption()); + aCB.setColor(this.getColor()); + aCB.setDrawShape(this.isDrawShape()); + aCB.setEndValue(this.getEndValue()); + aCB.setNoData(this.isNoData()); + aCB.setStartValue(this.getStartValue()); + aCB.setAngle(_angle); + aCB.setText(_text); + aCB.setFont(_font); + aCB.setAlignType(_alignType); + aCB.setYShift(_yShift); + aCB.setXShift(_xShift); + + return aCB; + } + // + // + + /** + * Add size changed listener + * + * @param scl SizeChangedListener interface + */ + public void addSizeChangedListener(ISizeChangedListener scl) { + this._listeners.add(ISizeChangedListener.class, scl); + } + + /** + * Remove size changed listener + * + * @param scl SizeChangedListener interface + */ + public void removeSizeChangedListener(ISizeChangedListener scl) { + this._listeners.remove(ISizeChangedListener.class, scl); + } + + /** + * Fire size changed event + * + * @param event SizeChangedEvent + */ + public void fireSizeChangedEvent(SizeChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ISizeChangedListener.class) { + ((ISizeChangedListener) listeners[i + 1]).sizeChangedEvent(event); + } + } + } + // } \ No newline at end of file diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LayersLegend.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LayersLegend.java index d7b70400..72bb903f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LayersLegend.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LayersLegend.java @@ -14,6 +14,9 @@ package org.meteoinfo.legend; import com.formdev.flatlaf.extras.FlatSVGIcon; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.PointF; import org.meteoinfo.data.mapdata.MapDataManage; import org.meteoinfo.drawing.Draw; import org.meteoinfo.global.event.ActiveMapFrameChangedEvent; @@ -22,8 +25,6 @@ import org.meteoinfo.global.event.ILayersUpdatedListener; import org.meteoinfo.global.event.IMapFramesUpdatedListener; import org.meteoinfo.global.event.LayersUpdatedEvent; import org.meteoinfo.global.event.MapFramesUpdatedEvent; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.PointF; import org.meteoinfo.layer.FrmLayerProperty; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; @@ -51,7 +52,6 @@ import java.awt.geom.GeneralPath; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -65,7 +65,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.meteoinfo.data.mapdata.FrmAttriData; import org.meteoinfo.data.mapdata.webmap.WebMapProvider; -import org.meteoinfo.global.Extent; import org.meteoinfo.global.FrmProperty; import org.meteoinfo.global.event.INodeSelectedListener; import org.meteoinfo.global.event.NodeSelectedEvent; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java index 46335336..86b8b904 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java @@ -13,10 +13,10 @@ */ package org.meteoinfo.legend; +import org.meteoinfo.common.MIMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; import org.meteoinfo.drawing.ContourDraw; -import org.meteoinfo.global.MIMath; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.shape.ShapeTypes; import java.awt.Color; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendScheme.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendScheme.java index 19705aa4..198ca6fc 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendScheme.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendScheme.java @@ -17,7 +17,6 @@ import org.meteoinfo.data.meteodata.DrawType2D; import org.meteoinfo.global.DataConvert; import org.meteoinfo.global.colors.ColorMap; import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.shape.ShapeTypes; import java.awt.Color; import java.io.BufferedReader; @@ -44,15 +43,6 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import static org.meteoinfo.shape.ShapeTypes.Point; -import static org.meteoinfo.shape.ShapeTypes.PointM; -import static org.meteoinfo.shape.ShapeTypes.PointZ; -import static org.meteoinfo.shape.ShapeTypes.Polygon; -import static org.meteoinfo.shape.ShapeTypes.PolygonM; -import static org.meteoinfo.shape.ShapeTypes.PolygonZ; -import static org.meteoinfo.shape.ShapeTypes.Polyline; -import static org.meteoinfo.shape.ShapeTypes.PolylineM; -import static org.meteoinfo.shape.ShapeTypes.PolylineZ; import org.w3c.dom.DOMException; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendView.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendView.java index da8c9135..ef98cca7 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendView.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendView.java @@ -13,9 +13,10 @@ */ package org.meteoinfo.legend; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointF; import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointF; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/SymbolControl.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/SymbolControl.java index ae98043e..04a599a1 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/SymbolControl.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/SymbolControl.java @@ -1,496 +1,496 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.legend; - -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.event.ISelectedCellChangedListener; -import org.meteoinfo.global.event.SelectedCellChangedEvent; -import org.meteoinfo.global.PointF; -import org.meteoinfo.shape.ShapeTypes; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JPanel; -import javax.swing.JScrollBar; -import javax.swing.event.EventListenerList; - -/** - * - * @author Yaqiang Wang - */ -public class SymbolControl extends JPanel { - // - - private EventListenerList _listeners = new EventListenerList(); - private ShapeTypes _shapeType; - private MarkerType _markerType; - private Dimension _cellSize; - private int _symbolNumber; - private int _colNumber; - private int _rowNumber; - private int _selectedCell; - private List _imageList; - private JScrollBar _vScrollBar; - private Color _selColor = new Color(210, 255, 255); - // - // - - public SymbolControl() { - initComponents(); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - onComponentResized(e); - } - }); - - this.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - onMouseClicked(e); - } - }); - - _shapeType = ShapeTypes.Point; - _markerType = MarkerType.Simple; - _cellSize = new Dimension(25, 25); - _symbolNumber = PointStyle.values().length; - _colNumber = 10; - _rowNumber = 26; - _selectedCell = -1; - _imageList = new ArrayList<>(); - } - - private void initComponents() { - this.setPreferredSize(new Dimension(200, 100)); - this.setLayout(new BorderLayout()); - this.setBackground(Color.white); - - _vScrollBar = new JScrollBar(JScrollBar.VERTICAL); - _vScrollBar.addAdjustmentListener(new AdjustmentListener() { - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - onScrollValueChanged(e); - } - }); - this.add(_vScrollBar, BorderLayout.EAST); - //this._vScrollBar.setSize(this._vScrollBar.getWidth(), this.getHeight()); - this._vScrollBar.setSize(20, this.getHeight()); - this._vScrollBar.setLocation(this.getWidth() - this._vScrollBar.getWidth(), 0); - } - // - - // - public void addSelectedCellChangedListener(ISelectedCellChangedListener listener) { - this._listeners.add(ISelectedCellChangedListener.class, listener); - } - - public void removeSelectedCellChangedListener(ISelectedCellChangedListener listener) { - this._listeners.remove(ISelectedCellChangedListener.class, listener); - } - - public void fireSelectedCellChangedEvent() { - fireSelectedCellChangedEvent(new SelectedCellChangedEvent(this)); - } - - private void fireSelectedCellChangedEvent(SelectedCellChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == ISelectedCellChangedListener.class) { - ((ISelectedCellChangedListener) listeners[i + 1]).selectedCellChangedEvent(event); - } - } - } - - public void onScrollValueChanged(AdjustmentEvent e) { - _vScrollBar.setValue(e.getValue()); - this.repaint(); - } - - public void onComponentResized(ComponentEvent e) { - if (this.getWidth() > 0 && this.getHeight() > 0) { - this.updateSize(); - this._vScrollBar.setLocation(this.getWidth() - this._vScrollBar.getWidth(), 0); - this._vScrollBar.setSize(this._vScrollBar.getWidth(), this.getHeight()); - } - this.repaint(); - } - - public void onMouseClicked(MouseEvent e) { - int col = e.getX() / _cellSize.width; - int row = (e.getY() + _vScrollBar.getValue()) / _cellSize.height; - int sel = row * _colNumber + col; - if (sel < _symbolNumber) { - _selectedCell = row * _colNumber + col; - //((frmPointSymbolSet)this.ParentForm).PointBreak.CharIndex = _selectedCell; - this.repaint(); - - this.fireSelectedCellChangedEvent(); - } - } - // - // - - /** - * Get shape type - * - * @return The shape type - */ - public ShapeTypes getShapeType() { - return _shapeType; - } - - /** - * Set shape type - * - * @param st The shape type - */ - public void setShapeType(ShapeTypes st) { - _shapeType = st; - switch (_shapeType) { - case Point: - setCellSize(new Dimension(25, 25)); - if (_markerType == MarkerType.Simple) { - setSymbolNumber(PointStyle.values().length); - } else { - setSymbolNumber(256); - } - break; - case Polyline: - setCellSize(new Dimension(50, 40)); - setSymbolNumber(LineStyles.values().length); - break; - case Polygon: - setCellSize(new Dimension(30, 30)); - setSymbolNumber(HatchStyle.values().length); - break; - } - } - - /** - * Get marker type - * - * @return Marker type - */ - public MarkerType getMarkerType() { - return _markerType; - } - - /** - * Set marker type - * - * @param mt - */ - public void setMarkerType(MarkerType mt) { - _markerType = mt; - if (_selectedCell < 0 || _selectedCell >= _symbolNumber) { - _selectedCell = 0; - } - this.repaint(); - } - - /** - * Get cell size - * - * @return Cell size - */ - public Dimension getCellSize() { - return _cellSize; - } - - /** - * Set cell size - * - * @param size Cell size - */ - public void setCellSize(Dimension size) { - _cellSize = size; - this.updateSize(); - } - - /** - * Get selected cell index - * - * @return Selected cell index - */ - public int getSelectedCell() { - return _selectedCell; - } - - /** - * Set selected cell index - * - * @param idx Selected cell index - */ - public void setSelectedCell(int idx) { - _selectedCell = idx; - } - - /** - * Get symbol number - * - * @return The symbol number - */ - public int getSymbolNumber() { - return _symbolNumber; - } - - /** - * Set symbol number - * - * @param sn The symbol number - */ - public void setSymbolNumber(int sn) { - _symbolNumber = sn; - _rowNumber = (int) Math.ceil((float) _symbolNumber / _colNumber); - } - - /** - * Get column number - * - * @return The column number - */ - public int getColumnNumber() { - return _colNumber; - } - - /** - * Set column number - * - * @param n The column number - */ - public void setColumnNumber(int n) { - _colNumber = n; - } - // - // - - /** - * Set image list - * - * @param imageList The image list - */ - public void setIamgeList(List imageList) { - _imageList = imageList; - setSymbolNumber(imageList.size()); - } - - private void updateSize() { - if (this._vScrollBar.isVisible()) { - this._colNumber = (this.getWidth() - this._vScrollBar.getWidth()) / this._cellSize.width; - } else { - this._colNumber = this.getWidth() / this._cellSize.width; - } - if (_colNumber == 0) { - _colNumber = 1; - } - this._rowNumber = (int) Math.ceil((float) _symbolNumber / _colNumber); - } - - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - - Graphics2D g2 = (Graphics2D) g; - - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - paintGraphics(g2); - //g2.dispose(); - } - - private void paintGraphics(Graphics2D g) { - int TotalHeight = calcTotalDrawHeight(); - Rectangle rect; - if (TotalHeight > this.getHeight()) { - _vScrollBar.setMinimum(0); - _vScrollBar.setUnitIncrement(_cellSize.height); - _vScrollBar.setBlockIncrement(this.getHeight()); - _vScrollBar.setMaximum(TotalHeight); - - if (_vScrollBar.isVisible() == false) { - _vScrollBar.setValue(0); - _vScrollBar.setVisible(true); - } - rect = new Rectangle(0, -_vScrollBar.getValue(), this.getWidth() - _vScrollBar.getWidth(), TotalHeight); - } else { - _vScrollBar.setVisible(false); - rect = new Rectangle(0, 0, this.getWidth(), this.getHeight()); - } - - this.updateSize(); - drawCells(g, rect.y); - } - - private void drawCells(Graphics2D g, int sHeight) { - int hideRows = 0; - switch (_shapeType) { - case Point: - switch (_markerType) { - case Character: - Font smallFont = new Font(this.getFont().getFamily(), Font.PLAIN, (int) (_cellSize.width * 0.8F)); - for (int i = 0; i < _symbolNumber; i++) { - int row = i / _colNumber; - if (row > hideRows) { - sHeight += _cellSize.height; - hideRows = row; - } - if (sHeight + _cellSize.height < 0) { - continue; - } - - int col = i % _colNumber; - if (i == _selectedCell) { - g.setColor(_selColor); - g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); - } - - String text = String.valueOf((char) i); - g.setColor(Color.black); - g.setFont(smallFont); - g.drawString(text, col * _cellSize.width, sHeight + _cellSize.height); - } - break; - case Simple: - PointBreak aPB = new PointBreak(); - aPB.setColor(Color.red); - aPB.setDrawOutline(true); - aPB.setSize(_cellSize.width * 0.8f); - for (int i = 0; i < _symbolNumber; i++) { -// if (i == PointStyle.values().length) { -// break; -// } - - int row = i / _colNumber; - if (row > hideRows) { - sHeight += _cellSize.height; - hideRows = row; - } - if (sHeight + _cellSize.height < 0) { - continue; - } - - int col = i % _colNumber; - if (i == _selectedCell) { - g.setColor(_selColor); - g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); - } - - PointF sP = new PointF(col * _cellSize.width + _cellSize.width / 2, - sHeight + _cellSize.height / 2); - aPB.setStyle(PointStyle.values()[i]); - Draw.drawPoint(sP, aPB, g); - } - break; - case Image: - float size = _cellSize.width * 0.8f; - for (int i = 0; i < _symbolNumber; i++) { - int row = i / _colNumber; - if (row > hideRows) { - sHeight += _cellSize.height; - hideRows = row; - } - if (sHeight + _cellSize.height < 0) { - continue; - } - - int col = i % _colNumber; - if (i == _selectedCell) { - g.setColor(_selColor); - g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); - } - - //((Bitmap)_imageList[i]).MakeTransparent(Color.White); - if (_imageList.size() > i) { - g.drawImage(_imageList.get(i), col * _cellSize.width, sHeight, (int) size, (int) size, null); - } - } - break; - } - break; - case Polyline: - PolylineBreak aPLB = new PolylineBreak(); - aPLB.setWidth(2); - aPLB.setColor(Color.black); - for (int i = 0; i < _symbolNumber; i++) { - int row = i / _colNumber; - if (row > hideRows) { - sHeight += _cellSize.height; - hideRows = row; - } - if (sHeight + _cellSize.height < 0) { - continue; - } - - int col = i % _colNumber; - Rectangle rect = new Rectangle(col * _cellSize.width, sHeight + _cellSize.height / 4, - _cellSize.width, _cellSize.height / 2); - if (i == _selectedCell) { - g.setColor(_selColor); - g.fill(rect); - } - - aPLB.setStyle(LineStyles.values()[i]); - Draw.drawPolylineSymbol(new PointF(rect.x + rect.width / 2, rect.y + rect.height / 2), - rect.width * 0.8f, rect.height * 0.8f, aPLB, g); - } - break; - case Polygon: - PolygonBreak aPGB = new PolygonBreak(); - aPGB.setColor(Color.red); - aPGB.setOutlineColor(Color.black); - for (int i = 0; i < _symbolNumber; i++) { - int row = i / _colNumber; - if (row > hideRows) { - sHeight += _cellSize.height; - hideRows = row; - } - if (sHeight + _cellSize.height < 0) { - continue; - } - - int col = i % _colNumber; - Rectangle rect = new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height); - if (i == _selectedCell) { - g.setColor(_selColor); - g.fill(rect); - } - - aPGB.setStyle(HatchStyle.values()[i]); - Draw.drawPolygonSymbol(new PointF(rect.x + rect.width / 2, rect.y + rect.height / 2), - rect.width * 0.8f, rect.height * 0.8f, aPGB, g); - } - break; - } - } - - private int calcTotalDrawHeight() { - return _cellSize.height * _rowNumber; - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.legend; + +import org.meteoinfo.common.PointF; +import org.meteoinfo.drawing.Draw; +import org.meteoinfo.global.event.ISelectedCellChangedListener; +import org.meteoinfo.global.event.SelectedCellChangedEvent; +import org.meteoinfo.shape.ShapeTypes; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.event.EventListenerList; + +/** + * + * @author Yaqiang Wang + */ +public class SymbolControl extends JPanel { + // + + private EventListenerList _listeners = new EventListenerList(); + private ShapeTypes _shapeType; + private MarkerType _markerType; + private Dimension _cellSize; + private int _symbolNumber; + private int _colNumber; + private int _rowNumber; + private int _selectedCell; + private List _imageList; + private JScrollBar _vScrollBar; + private Color _selColor = new Color(210, 255, 255); + // + // + + public SymbolControl() { + initComponents(); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + onComponentResized(e); + } + }); + + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + onMouseClicked(e); + } + }); + + _shapeType = ShapeTypes.Point; + _markerType = MarkerType.Simple; + _cellSize = new Dimension(25, 25); + _symbolNumber = PointStyle.values().length; + _colNumber = 10; + _rowNumber = 26; + _selectedCell = -1; + _imageList = new ArrayList<>(); + } + + private void initComponents() { + this.setPreferredSize(new Dimension(200, 100)); + this.setLayout(new BorderLayout()); + this.setBackground(Color.white); + + _vScrollBar = new JScrollBar(JScrollBar.VERTICAL); + _vScrollBar.addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + onScrollValueChanged(e); + } + }); + this.add(_vScrollBar, BorderLayout.EAST); + //this._vScrollBar.setSize(this._vScrollBar.getWidth(), this.getHeight()); + this._vScrollBar.setSize(20, this.getHeight()); + this._vScrollBar.setLocation(this.getWidth() - this._vScrollBar.getWidth(), 0); + } + // + + // + public void addSelectedCellChangedListener(ISelectedCellChangedListener listener) { + this._listeners.add(ISelectedCellChangedListener.class, listener); + } + + public void removeSelectedCellChangedListener(ISelectedCellChangedListener listener) { + this._listeners.remove(ISelectedCellChangedListener.class, listener); + } + + public void fireSelectedCellChangedEvent() { + fireSelectedCellChangedEvent(new SelectedCellChangedEvent(this)); + } + + private void fireSelectedCellChangedEvent(SelectedCellChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == ISelectedCellChangedListener.class) { + ((ISelectedCellChangedListener) listeners[i + 1]).selectedCellChangedEvent(event); + } + } + } + + public void onScrollValueChanged(AdjustmentEvent e) { + _vScrollBar.setValue(e.getValue()); + this.repaint(); + } + + public void onComponentResized(ComponentEvent e) { + if (this.getWidth() > 0 && this.getHeight() > 0) { + this.updateSize(); + this._vScrollBar.setLocation(this.getWidth() - this._vScrollBar.getWidth(), 0); + this._vScrollBar.setSize(this._vScrollBar.getWidth(), this.getHeight()); + } + this.repaint(); + } + + public void onMouseClicked(MouseEvent e) { + int col = e.getX() / _cellSize.width; + int row = (e.getY() + _vScrollBar.getValue()) / _cellSize.height; + int sel = row * _colNumber + col; + if (sel < _symbolNumber) { + _selectedCell = row * _colNumber + col; + //((frmPointSymbolSet)this.ParentForm).PointBreak.CharIndex = _selectedCell; + this.repaint(); + + this.fireSelectedCellChangedEvent(); + } + } + // + // + + /** + * Get shape type + * + * @return The shape type + */ + public ShapeTypes getShapeType() { + return _shapeType; + } + + /** + * Set shape type + * + * @param st The shape type + */ + public void setShapeType(ShapeTypes st) { + _shapeType = st; + switch (_shapeType) { + case Point: + setCellSize(new Dimension(25, 25)); + if (_markerType == MarkerType.Simple) { + setSymbolNumber(PointStyle.values().length); + } else { + setSymbolNumber(256); + } + break; + case Polyline: + setCellSize(new Dimension(50, 40)); + setSymbolNumber(LineStyles.values().length); + break; + case Polygon: + setCellSize(new Dimension(30, 30)); + setSymbolNumber(HatchStyle.values().length); + break; + } + } + + /** + * Get marker type + * + * @return Marker type + */ + public MarkerType getMarkerType() { + return _markerType; + } + + /** + * Set marker type + * + * @param mt + */ + public void setMarkerType(MarkerType mt) { + _markerType = mt; + if (_selectedCell < 0 || _selectedCell >= _symbolNumber) { + _selectedCell = 0; + } + this.repaint(); + } + + /** + * Get cell size + * + * @return Cell size + */ + public Dimension getCellSize() { + return _cellSize; + } + + /** + * Set cell size + * + * @param size Cell size + */ + public void setCellSize(Dimension size) { + _cellSize = size; + this.updateSize(); + } + + /** + * Get selected cell index + * + * @return Selected cell index + */ + public int getSelectedCell() { + return _selectedCell; + } + + /** + * Set selected cell index + * + * @param idx Selected cell index + */ + public void setSelectedCell(int idx) { + _selectedCell = idx; + } + + /** + * Get symbol number + * + * @return The symbol number + */ + public int getSymbolNumber() { + return _symbolNumber; + } + + /** + * Set symbol number + * + * @param sn The symbol number + */ + public void setSymbolNumber(int sn) { + _symbolNumber = sn; + _rowNumber = (int) Math.ceil((float) _symbolNumber / _colNumber); + } + + /** + * Get column number + * + * @return The column number + */ + public int getColumnNumber() { + return _colNumber; + } + + /** + * Set column number + * + * @param n The column number + */ + public void setColumnNumber(int n) { + _colNumber = n; + } + // + // + + /** + * Set image list + * + * @param imageList The image list + */ + public void setIamgeList(List imageList) { + _imageList = imageList; + setSymbolNumber(imageList.size()); + } + + private void updateSize() { + if (this._vScrollBar.isVisible()) { + this._colNumber = (this.getWidth() - this._vScrollBar.getWidth()) / this._cellSize.width; + } else { + this._colNumber = this.getWidth() / this._cellSize.width; + } + if (_colNumber == 0) { + _colNumber = 1; + } + this._rowNumber = (int) Math.ceil((float) _symbolNumber / _colNumber); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + + Graphics2D g2 = (Graphics2D) g; + + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + paintGraphics(g2); + //g2.dispose(); + } + + private void paintGraphics(Graphics2D g) { + int TotalHeight = calcTotalDrawHeight(); + Rectangle rect; + if (TotalHeight > this.getHeight()) { + _vScrollBar.setMinimum(0); + _vScrollBar.setUnitIncrement(_cellSize.height); + _vScrollBar.setBlockIncrement(this.getHeight()); + _vScrollBar.setMaximum(TotalHeight); + + if (_vScrollBar.isVisible() == false) { + _vScrollBar.setValue(0); + _vScrollBar.setVisible(true); + } + rect = new Rectangle(0, -_vScrollBar.getValue(), this.getWidth() - _vScrollBar.getWidth(), TotalHeight); + } else { + _vScrollBar.setVisible(false); + rect = new Rectangle(0, 0, this.getWidth(), this.getHeight()); + } + + this.updateSize(); + drawCells(g, rect.y); + } + + private void drawCells(Graphics2D g, int sHeight) { + int hideRows = 0; + switch (_shapeType) { + case Point: + switch (_markerType) { + case Character: + Font smallFont = new Font(this.getFont().getFamily(), Font.PLAIN, (int) (_cellSize.width * 0.8F)); + for (int i = 0; i < _symbolNumber; i++) { + int row = i / _colNumber; + if (row > hideRows) { + sHeight += _cellSize.height; + hideRows = row; + } + if (sHeight + _cellSize.height < 0) { + continue; + } + + int col = i % _colNumber; + if (i == _selectedCell) { + g.setColor(_selColor); + g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); + } + + String text = String.valueOf((char) i); + g.setColor(Color.black); + g.setFont(smallFont); + g.drawString(text, col * _cellSize.width, sHeight + _cellSize.height); + } + break; + case Simple: + PointBreak aPB = new PointBreak(); + aPB.setColor(Color.red); + aPB.setDrawOutline(true); + aPB.setSize(_cellSize.width * 0.8f); + for (int i = 0; i < _symbolNumber; i++) { +// if (i == PointStyle.values().length) { +// break; +// } + + int row = i / _colNumber; + if (row > hideRows) { + sHeight += _cellSize.height; + hideRows = row; + } + if (sHeight + _cellSize.height < 0) { + continue; + } + + int col = i % _colNumber; + if (i == _selectedCell) { + g.setColor(_selColor); + g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); + } + + PointF sP = new PointF(col * _cellSize.width + _cellSize.width / 2, + sHeight + _cellSize.height / 2); + aPB.setStyle(PointStyle.values()[i]); + Draw.drawPoint(sP, aPB, g); + } + break; + case Image: + float size = _cellSize.width * 0.8f; + for (int i = 0; i < _symbolNumber; i++) { + int row = i / _colNumber; + if (row > hideRows) { + sHeight += _cellSize.height; + hideRows = row; + } + if (sHeight + _cellSize.height < 0) { + continue; + } + + int col = i % _colNumber; + if (i == _selectedCell) { + g.setColor(_selColor); + g.fill(new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height)); + } + + //((Bitmap)_imageList[i]).MakeTransparent(Color.White); + if (_imageList.size() > i) { + g.drawImage(_imageList.get(i), col * _cellSize.width, sHeight, (int) size, (int) size, null); + } + } + break; + } + break; + case Polyline: + PolylineBreak aPLB = new PolylineBreak(); + aPLB.setWidth(2); + aPLB.setColor(Color.black); + for (int i = 0; i < _symbolNumber; i++) { + int row = i / _colNumber; + if (row > hideRows) { + sHeight += _cellSize.height; + hideRows = row; + } + if (sHeight + _cellSize.height < 0) { + continue; + } + + int col = i % _colNumber; + Rectangle rect = new Rectangle(col * _cellSize.width, sHeight + _cellSize.height / 4, + _cellSize.width, _cellSize.height / 2); + if (i == _selectedCell) { + g.setColor(_selColor); + g.fill(rect); + } + + aPLB.setStyle(LineStyles.values()[i]); + Draw.drawPolylineSymbol(new PointF(rect.x + rect.width / 2, rect.y + rect.height / 2), + rect.width * 0.8f, rect.height * 0.8f, aPLB, g); + } + break; + case Polygon: + PolygonBreak aPGB = new PolygonBreak(); + aPGB.setColor(Color.red); + aPGB.setOutlineColor(Color.black); + for (int i = 0; i < _symbolNumber; i++) { + int row = i / _colNumber; + if (row > hideRows) { + sHeight += _cellSize.height; + hideRows = row; + } + if (sHeight + _cellSize.height < 0) { + continue; + } + + int col = i % _colNumber; + Rectangle rect = new Rectangle(col * _cellSize.width, sHeight, _cellSize.width, _cellSize.height); + if (i == _selectedCell) { + g.setColor(_selColor); + g.fill(rect); + } + + aPGB.setStyle(HatchStyle.values()[i]); + Draw.drawPolygonSymbol(new PointF(rect.x + rect.width / 2, rect.y + rect.height / 2), + rect.width * 0.8f, rect.height * 0.8f, aPGB, g); + } + break; + } + } + + private int calcTotalDrawHeight() { + return _cellSize.height * _rowNumber; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/FrmVerticeEdit.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/FrmVerticeEdit.java index 240ee29d..8b856670 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/FrmVerticeEdit.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/FrmVerticeEdit.java @@ -5,7 +5,7 @@ */ package org.meteoinfo.map; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.PointD; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/GridLabel.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/GridLabel.java index 30aa3612..3c3e78b9 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/GridLabel.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/GridLabel.java @@ -1,190 +1,190 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.map; - -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.PointD; - -/** - * - * @author Yaqiang Wang - */ -public class GridLabel { - // - - private Direction _labDirection; - private String _labString; - private PointD _labPoint; - private PointD coord; - private boolean _isLon; - private boolean _isBorder; - private float _value; - private float angle; - // - // - /** - * Constructor - */ - public GridLabel() { - _labDirection = Direction.East; - _isLon = true; - _isBorder = true; - this.angle = Float.NaN; - } - // - // - - /** - * Get label direction - * - * @return Label direction - */ - public Direction getLabDirection() { - return _labDirection; - } - - /** - * Set label direction - * - * @param dir Label direction - */ - public void setLabDirection(Direction dir) { - _labDirection = dir; - } - - /** - * Get label string - * - * @return label string - */ - public String getLabString() { - return _labString; - } - - /** - * Set label string - * - * @param str Label string - */ - public void setLabString(String str) { - _labString = str; - } - - /** - * Get label point - * - * @return Label Point - */ - public PointD getLabPoint() { - return _labPoint; - } - - /** - * Set label point - * - * @param p Label Point - */ - public void setLabPoint(PointD p) { - _labPoint = p; - } - - /** - * Get coordinate - * @return Coordinate - */ - public PointD getCoord() { - return this.coord; - } - - /** - * Set coordinate - * @param value Coordinate - */ - public void setCoord(PointD value) { - this.coord = value; - } - - /** - * Get if is longitude - * - * @return Boolean - */ - public boolean isLongitude() { - return _isLon; - } - - /** - * Set if is longitude - * - * @param istrue Boolean - */ - public void setLongitude(boolean istrue) { - _isLon = istrue; - } - - /** - * Get if is border - * - * @return Boolean - */ - public boolean isBorder() { - return _isBorder; - } - - /** - * Set if is border - * - * @param istrue Boolean - */ - public void setBorder(boolean istrue) { - _isBorder = istrue; - } - - /** - * Get value - * - * @return Value - */ - public float getValue() { - return _value; - } - - /** - * Set value - * - * @param value Value - */ - public void setValue(float value) { - _value = value; - } - - /** - * Get angle - * @return Angle - */ - public float getAngle() { - return this.angle; - } - - /** - * Set angle - * @param value Angle - */ - public void setAnge(float value){ - this.angle = value; - } - // - // - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.map; + + import org.meteoinfo.common.Direction; + import org.meteoinfo.common.PointD; + + /** + * + * @author Yaqiang Wang + */ +public class GridLabel { + // + + private Direction _labDirection; + private String _labString; + private PointD _labPoint; + private PointD coord; + private boolean _isLon; + private boolean _isBorder; + private float _value; + private float angle; + // + // + /** + * Constructor + */ + public GridLabel() { + _labDirection = Direction.East; + _isLon = true; + _isBorder = true; + this.angle = Float.NaN; + } + // + // + + /** + * Get label direction + * + * @return Label direction + */ + public Direction getLabDirection() { + return _labDirection; + } + + /** + * Set label direction + * + * @param dir Label direction + */ + public void setLabDirection(Direction dir) { + _labDirection = dir; + } + + /** + * Get label string + * + * @return label string + */ + public String getLabString() { + return _labString; + } + + /** + * Set label string + * + * @param str Label string + */ + public void setLabString(String str) { + _labString = str; + } + + /** + * Get label point + * + * @return Label Point + */ + public PointD getLabPoint() { + return _labPoint; + } + + /** + * Set label point + * + * @param p Label Point + */ + public void setLabPoint(PointD p) { + _labPoint = p; + } + + /** + * Get coordinate + * @return Coordinate + */ + public PointD getCoord() { + return this.coord; + } + + /** + * Set coordinate + * @param value Coordinate + */ + public void setCoord(PointD value) { + this.coord = value; + } + + /** + * Get if is longitude + * + * @return Boolean + */ + public boolean isLongitude() { + return _isLon; + } + + /** + * Set if is longitude + * + * @param istrue Boolean + */ + public void setLongitude(boolean istrue) { + _isLon = istrue; + } + + /** + * Get if is border + * + * @return Boolean + */ + public boolean isBorder() { + return _isBorder; + } + + /** + * Set if is border + * + * @param istrue Boolean + */ + public void setBorder(boolean istrue) { + _isBorder = istrue; + } + + /** + * Get value + * + * @return Value + */ + public float getValue() { + return _value; + } + + /** + * Set value + * + * @param value Value + */ + public void setValue(float value) { + _value = value; + } + + /** + * Get angle + * @return Angle + */ + public float getAngle() { + return this.angle; + } + + /** + * Set angle + * @param value Angle + */ + public void setAnge(float value){ + this.angle = value; + } + // + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java index 44281733..1d03dcd5 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java @@ -18,13 +18,15 @@ import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfTemplate; import com.itextpdf.text.pdf.PdfWriter; +import org.meteoinfo.common.*; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.data.mapdata.MapDataManage; import org.meteoinfo.drawing.Draw; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.legend.PointStyle; import org.meteoinfo.geoprocess.GeoComputation; import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.global.Direction; import org.meteoinfo.global.event.GraphicSelectedEvent; import org.meteoinfo.global.event.IGraphicSelectedListener; import org.meteoinfo.global.event.ILayersUpdatedListener; @@ -33,13 +35,8 @@ import org.meteoinfo.global.event.IViewExtentChangedListener; import org.meteoinfo.global.event.LayersUpdatedEvent; import org.meteoinfo.global.event.ProjectionChangedEvent; import org.meteoinfo.global.event.ViewExtentChangedEvent; -import org.meteoinfo.global.Extent; import org.meteoinfo.global.FrmMeasurement; import org.meteoinfo.global.FrmMeasurement.MeasureTypes; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.util.BigDecimalUtil; import org.meteoinfo.layer.ChartSet; @@ -8860,7 +8857,7 @@ public class MapView extends JPanel implements IWebMapPanel { aY = (float) sXY[1]; points.add(new PointD(aX, aY)); } - Extent aExtent = MIMath.getPointsExtent(points); + Extent aExtent = GeometryUtil.getPointsExtent(points); rect.x = (int) aExtent.minX; rect.y = (int) aExtent.minY; rect.width = (int) (aExtent.maxX - aExtent.minX); diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapViewUndoRedo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapViewUndoRedo.java index 8e986269..a71d4849 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapViewUndoRedo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapViewUndoRedo.java @@ -1,943 +1,944 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.map; - -import java.awt.Point; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.undo.AbstractUndoableEdit; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.shape.Graphic; -import org.meteoinfo.shape.PolygonShape; -import org.meteoinfo.shape.Shape; -import org.meteoinfo.table.DataRow; - -/** - * - * @author yaqiang - */ -public class MapViewUndoRedo { - // - public class ZoomEdit extends AbstractUndoableEdit { - MapView mapView; - Extent newExtent; - Extent oldExtent; - - public ZoomEdit(MapView mapView, Extent oldExtent, Extent newExtent){ - this.mapView = mapView; - this.newExtent = newExtent; - this.oldExtent = oldExtent; - } - - @Override - public String getPresentationName() { - return "Zoom"; - } - - @Override - public void undo() { - super.undo(); - mapView.zoomToExtent(oldExtent); - } - - @Override - public void redo(){ - super.redo(); - mapView.zoomToExtent(newExtent); - } - } - - public class AddFeatureEdit extends FeatureUndoableEdit { - MapView mapView; - Shape shape; - VectorLayer layer; - - public AddFeatureEdit(MapView mapView, VectorLayer layer, Shape shape){ - this.mapView = mapView; - this.layer = layer; - this.shape = shape; - } - - @Override - public String getPresentationName() { - return "Add a Feature"; - } - - @Override - public void undo() { - super.undo(); - layer.editRemoveShape(shape); - mapView.paintLayers(); - System.out.println("Undo add a feature"); - } - - @Override - public void redo(){ - super.redo(); - try { - layer.editAddShape(shape); - mapView.paintLayers(); - System.out.println("Redo add a feature"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class AddFeaturesEdit extends FeatureUndoableEdit { - MapView mapView; - List shapes; - VectorLayer layer; - - public AddFeaturesEdit(MapView mapView, VectorLayer layer, List shapes){ - this.mapView = mapView; - this.layer = layer; - this.shapes = shapes; - } - - @Override - public String getPresentationName() { - return "Add Features"; - } - - @Override - public void undo() { - super.undo(); - for (Shape shape : shapes) - layer.editRemoveShape(shape); - mapView.paintLayers(); - System.out.println("Undo add features"); - } - - @Override - public void redo(){ - super.redo(); - try { - for (Shape shape : shapes) - layer.editAddShape(shape); - mapView.paintLayers(); - System.out.println("Redo add features"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class ReplaceFeatureEdit extends FeatureUndoableEdit { - MapView mapView; - Shape s0; - Shape s1; - Shape s00; - VectorLayer layer; - - public ReplaceFeatureEdit(MapView mapView, VectorLayer layer, Shape s0, Shape s1){ - this.mapView = mapView; - this.layer = layer; - this.s0 = s0; - this.s1 = s1; - this.s00 = (Shape)s0.clone(); - } - - @Override - public String getPresentationName() { - return "Replace Feature"; - } - - @Override - public void undo() { - super.undo(); - s0.cloneValue(s00); - mapView.paintLayers(); - System.out.println("Undo replace feature"); - } - - @Override - public void redo(){ - super.redo(); - s0.cloneValue(s1); - mapView.paintLayers(); - System.out.println("Redo replace feature"); - } - } - - public class SplitFeatureEdit extends FeatureUndoableEdit { - MapView mapView; - Shape shape; - List shapes; - VectorLayer layer; - - public SplitFeatureEdit(MapView mapView, VectorLayer layer, Shape shape, List shapes){ - this.mapView = mapView; - this.layer = layer; - this.shape = shape; - this.shapes = shapes; - } - - @Override - public String getPresentationName() { - return "Split Feature"; - } - - @Override - public void undo() { - super.undo(); - for (Shape s : shapes) - layer.editRemoveShape(s); - try { - layer.editAddShape(shape); - } catch (Exception ex) { - Logger.getLogger(MapViewUndoRedo.class.getName()).log(Level.SEVERE, null, ex); - } - mapView.paintLayers(); - System.out.println("Undo split feature"); - } - - @Override - public void redo(){ - super.redo(); - try { - for (Shape s : shapes) - layer.editAddShape(s); - layer.editRemoveShape(shape); - mapView.paintLayers(); - System.out.println("Redo split feature"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class UnionFeaturesEdit extends FeatureUndoableEdit { - MapView mapView; - Shape shape; - List shapes; - VectorLayer layer; - - public UnionFeaturesEdit(MapView mapView, VectorLayer layer, Shape shape, List shapes){ - this.mapView = mapView; - this.layer = layer; - this.shape = shape; - this.shapes = shapes; - } - - @Override - public String getPresentationName() { - return "Union Features"; - } - - @Override - public void undo() { - super.undo(); - try { - layer.editRemoveShape(shape); - for (Shape s : shapes) - layer.editAddShape(s); - mapView.paintLayers(); - System.out.println("Undo split feature"); - } catch (Exception ex){ - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - - @Override - public void redo(){ - super.redo(); - try { - for (Shape s : shapes) - layer.editRemoveShape(s); - layer.editAddShape(shape); - mapView.paintLayers(); - System.out.println("Redo split feature"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class AddRingEdit extends FeatureUndoableEdit { - MapView mapView; - PolygonShape shape; - List points; - int polyIdx; - int holeIdx; - - public AddRingEdit(MapView mapView, PolygonShape shape, List points, - int polygonIdx, int holeIdx){ - this.mapView = mapView; - this.shape = shape; - this.points = points; - this.polyIdx = polygonIdx; - this.holeIdx = holeIdx; - } - - @Override - public String getPresentationName() { - return "Add a hole"; - } - - @Override - public void undo() { - super.undo(); - shape.removeHole(polyIdx, holeIdx); - mapView.paintLayers(); - System.out.println("Undo add a hole"); - } - - @Override - public void redo(){ - super.redo(); - try { - shape.addHole(points, polyIdx); - mapView.paintLayers(); - System.out.println("Redo add a hole"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class FillRingEdit extends FeatureUndoableEdit { - MapView mapView; - VectorLayer layer; - PolygonShape shape; - PolygonShape hole; - int polyIdx; - int holeIdx; - - public FillRingEdit(MapView mapView, VectorLayer layer, PolygonShape shape, PolygonShape hole, - int polygonIdx, int holeIdx){ - this.mapView = mapView; - this.layer = layer; - this.shape = shape; - this.hole = hole; - this.polyIdx = polygonIdx; - this.holeIdx = holeIdx; - } - - @Override - public String getPresentationName() { - return "Fill a hole"; - } - - @Override - public void undo() { - super.undo(); - shape.removeHole(polyIdx, holeIdx); - layer.editRemoveShape(hole); - mapView.paintLayers(); - System.out.println("Undo Fill a hole"); - } - - @Override - public void redo(){ - super.redo(); - try { - shape.addHole((List)hole.getPoints(), polyIdx); - layer.editAddShape(hole); - mapView.paintLayers(); - System.out.println("Redo Fill a hole"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - public class RemoveRingEdit extends FeatureUndoableEdit { - MapView mapView; - PolygonShape shape; - List points; - int polyIdx; - int holeIdx; - - public RemoveRingEdit(MapView mapView, PolygonShape shape, List hole, int polygonIdx, int holeIdx){ - this.mapView = mapView; - this.shape = shape; - this.points = hole; - this.polyIdx = polygonIdx; - this.holeIdx = holeIdx; - } - - @Override - public String getPresentationName() { - return "Remove a hole"; - } - - @Override - public void undo() { - super.undo(); - try { - shape.addHole(points, polyIdx); - mapView.paintLayers(); - System.out.println("Redo remove a hole"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - - @Override - public void redo(){ - super.redo(); - shape.removeHole(polyIdx, holeIdx); - mapView.paintLayers(); - System.out.println("Undo remove a hole"); - } - } - - public class RemoveFeaturesEdit extends FeatureUndoableEdit { - MapView mapView; - List shapes; - VectorLayer layer; - List indices; - List records; - - public RemoveFeaturesEdit(MapView mapView, VectorLayer layer, List shapes){ - this.mapView = mapView; - this.layer = layer; - this.shapes = shapes; - indices = new ArrayList<>(); - records = new ArrayList<>(); - int idx; - DataRow row; - for (Shape shape : shapes){ - idx = layer.getShapes().indexOf(shape); - row = layer.getAttributeTable().getTable().getRows().get(idx); - indices.add(idx); - records.add(row); - } - } - - @Override - public String getPresentationName() { - return "Remove Features"; - } - - @Override - public void undo() { - super.undo(); - try { - for (int i = 0; i < shapes.size(); i++){ - layer.editInsertShape(shapes.get(i), indices.get(i), records.get(i)); - } - mapView.paintLayers(); - System.out.println("Undo remove features"); - } catch (Exception ex) { - Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); - } - } - - @Override - public void redo(){ - super.redo(); - for (Shape shape : shapes) - layer.editRemoveShape(shape); - mapView.paintLayers(); - System.out.println("Undo remove features"); - } - } - - class MoveFeatureEdit extends FeatureUndoableEdit { - MapView mapView; - Shape shape; - Point fromPoint; - Point toPoint; - - public MoveFeatureEdit(MapView mapView, Shape shape, Point fromPoint, Point toPoint){ - this.mapView = mapView; - this.shape = shape; - this.fromPoint = new Point(fromPoint.x, fromPoint.y); - this.toPoint = new Point(toPoint.x, toPoint.y); - } - - @Override - public String getPresentationName() { - return "Move a Feature"; - } - - @Override - public void undo() { - super.undo(); - mapView.moveShapeOnScreen(shape, toPoint, fromPoint); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.moveShapeOnScreen(shape, fromPoint, toPoint); - mapView.paintLayers(); - } - } - - class MoveFeaturesEdit extends FeatureUndoableEdit { - MapView mapView; - List shapes; - Point fromPoint; - Point toPoint; - - public MoveFeaturesEdit(MapView mapView, List shapes, Point fromPoint, Point toPoint){ - this.mapView = mapView; - this.shapes = shapes; - this.fromPoint = new Point(fromPoint.x, fromPoint.y); - this.toPoint = new Point(toPoint.x, toPoint.y); - } - - @Override - public String getPresentationName() { - return "Move a Feature"; - } - - @Override - public void undo() { - super.undo(); - for (Shape shape : shapes) - mapView.moveShapeOnScreen(shape, toPoint, fromPoint); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - for (Shape shape : shapes) - mapView.moveShapeOnScreen(shape, fromPoint, toPoint); - mapView.paintLayers(); - } - } - - class MoveFeatureVerticeEdit extends FeatureUndoableEdit { - MapView mapView; - Shape shape; - int verticeIdx; - double newX; - double newY; - double oldX; - double oldY; - - public MoveFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx, double newX, double newY){ - this.mapView = mapView; - this.shape = shape; - this.verticeIdx = vIdx; - this.newX = newX; - this.newY = newY; - this.oldX = shape.getPoints().get(vIdx).X; - this.oldY = shape.getPoints().get(vIdx).Y; - } - - @Override - public String getPresentationName() { - return "Move a Feature"; - } - - @Override - public void undo() { - super.undo(); - shape.moveVertice(verticeIdx, oldX, oldY); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - shape.moveVertice(verticeIdx, newX, newY); - mapView.paintLayers(); - } - } - - class AddFeatureVerticeEdit extends AbstractUndoableEdit { - MapView mapView; - Shape shape; - int verticeIdx; - PointD vertice; - - public AddFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx, PointD vertice){ - this.mapView = mapView; - this.shape = shape; - this.verticeIdx = vIdx; - this.vertice = vertice; - } - - @Override - public String getPresentationName() { - return "Add feature vertice"; - } - - @Override - public void undo() { - super.undo(); - shape.removeVerice(verticeIdx); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - shape.addVertice(verticeIdx, vertice); - mapView.paintLayers(); - } - } - - class RemoveFeatureVerticeEdit extends AbstractUndoableEdit { - MapView mapView; - Shape shape; - int verticeIdx; - PointD vertice; - - public RemoveFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx){ - this.mapView = mapView; - this.shape = shape; - this.verticeIdx = vIdx; - this.vertice = shape.getPoints().get(vIdx); - } - - @Override - public String getPresentationName() { - return "Remove feature vertice"; - } - - @Override - public void undo() { - super.undo(); - shape.addVertice(verticeIdx, vertice); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - shape.removeVerice(verticeIdx); - mapView.paintLayers(); - } - } - - class AddGraphicEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - - public AddGraphicEdit(MapView mapView, Graphic graphic){ - this.mapView = mapView; - this.graphic = graphic; - } - - @Override - public String getPresentationName() { - return "Add a Graphic"; - } - - @Override - public void undo() { - super.undo(); - mapView.removeGraphic(graphic); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.getGraphicCollection().add(graphic); - mapView.paintLayers(); - } - } - - class RemoveGraphicEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - - public RemoveGraphicEdit(MapView mapView, Graphic graphic){ - this.mapView = mapView; - this.graphic = graphic; - } - - @Override - public String getPresentationName() { - return "Remove a Graphic"; - } - - @Override - public void undo() { - super.undo(); - mapView.getGraphicCollection().add(graphic); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.removeGraphic(graphic); - mapView.paintLayers(); - } - } - - class RemoveGraphicsEdit extends AbstractUndoableEdit { - MapView mapView; - List graphics; - - public RemoveGraphicsEdit(MapView mapView, List graphics){ - this.mapView = mapView; - this.graphics = new ArrayList<>(graphics); - } - - @Override - public String getPresentationName() { - return "Remove Graphics"; - } - - @Override - public void undo() { - super.undo(); - mapView.getGraphicCollection().addAll(graphics); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.getGraphicCollection().removeAll(graphics); - mapView.paintLayers(); - } - } - - class MoveGraphicEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - Point fromPoint; - Point toPoint; - - public MoveGraphicEdit(MapView mapView, Graphic graphic, Point fromPoint, Point toPoint){ - this.mapView = mapView; - this.graphic = graphic; - this.fromPoint = new Point(fromPoint.x, fromPoint.y); - this.toPoint = new Point(toPoint.x, toPoint.y); - } - - @Override - public String getPresentationName() { - return "Move a Graphic"; - } - - @Override - public void undo() { - super.undo(); - mapView.moveShapeOnScreen(graphic.getShape(), toPoint, fromPoint); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.moveShapeOnScreen(graphic.getShape(), fromPoint, toPoint); - mapView.paintLayers(); - } - } - - class MoveGraphicVerticeEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - int verticeIdx; - double newX; - double newY; - double oldX; - double oldY; - - public MoveGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx, double newX, double newY){ - this.mapView = mapView; - this.graphic = graphic; - this.verticeIdx = vIdx; - this.newX = newX; - this.newY = newY; - this.oldX = graphic.getShape().getPoints().get(vIdx).X; - this.oldY = graphic.getShape().getPoints().get(vIdx).Y; - } - - @Override - public String getPresentationName() { - return "Move Grahic vertice"; - } - - @Override - public void undo() { - super.undo(); - graphic.verticeMoveUpdate(verticeIdx, oldX, oldY); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - graphic.verticeMoveUpdate(verticeIdx, newX, newY); - mapView.paintLayers(); - } - } - - class AddGraphicVerticeEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - int verticeIdx; - PointD vertice; - - public AddGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx, PointD vertice){ - this.mapView = mapView; - this.graphic = graphic; - this.verticeIdx = vIdx; - this.vertice = vertice; - } - - @Override - public String getPresentationName() { - return "Add Grahic vertice"; - } - - @Override - public void undo() { - super.undo(); - graphic.verticeRemoveUpdate(verticeIdx); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - graphic.verticeAddUpdate(verticeIdx, vertice); - mapView.paintLayers(); - } - } - - class RemoveGraphicVerticeEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - int verticeIdx; - PointD vertice; - - public RemoveGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx){ - this.mapView = mapView; - this.graphic = graphic; - this.verticeIdx = vIdx; - this.vertice = graphic.getShape().getPoints().get(vIdx); - } - - @Override - public String getPresentationName() { - return "Remove Grahic vertice"; - } - - @Override - public void undo() { - super.undo(); - graphic.verticeAddUpdate(verticeIdx, vertice); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - graphic.verticeRemoveUpdate(verticeIdx); - mapView.paintLayers(); - } - } - - class ResizeGraphicEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - Rectangle oldRect; - Rectangle newRect; - - public ResizeGraphicEdit(MapView mapView, Graphic graphic, Rectangle newRect){ - this.mapView = mapView; - this.graphic = graphic; - this.newRect = newRect; - this.oldRect = mapView.getGraphicRectangle(graphic); - } - - @Override - public String getPresentationName() { - return "Resize a Graphic"; - } - - @Override - public void undo() { - super.undo(); - mapView.resizeShapeOnScreen(graphic, oldRect); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - mapView.resizeShapeOnScreen(graphic, newRect); - mapView.paintLayers(); - } - } - - class SmoothGraphicEdit extends AbstractUndoableEdit { - MapView mapView; - Graphic graphic; - List oldPoints; - List newPoints; - - public SmoothGraphicEdit(MapView mapView, Graphic graphic, List points){ - this.mapView = mapView; - this.graphic = graphic; - this.newPoints = points; - this.oldPoints = (List)graphic.getShape().getPoints(); - } - - @Override - public String getPresentationName() { - return "Resize a Graphic"; - } - - @Override - public void undo() { - super.undo(); - graphic.getShape().setPoints(oldPoints); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - graphic.getShape().setPoints(newPoints); - mapView.paintLayers(); - } - } - - class SmoothFeatureEdit extends AbstractUndoableEdit { - MapView mapView; - Shape shape; - List oldPoints; - List newPoints; - - public SmoothFeatureEdit(MapView mapView, Shape shape, List points){ - this.mapView = mapView; - this.shape = shape; - this.newPoints = points; - this.oldPoints = (List)shape.getPoints(); - } - - @Override - public String getPresentationName() { - return "Resize a Graphic"; - } - - @Override - public void undo() { - super.undo(); - shape.setPoints(oldPoints); - mapView.paintLayers(); - } - - @Override - public void redo(){ - super.redo(); - shape.setPoints(newPoints); - mapView.paintLayers(); - } - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.map; + +import java.awt.Point; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.undo.AbstractUndoableEdit; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.shape.Graphic; +import org.meteoinfo.shape.PolygonShape; +import org.meteoinfo.shape.Shape; +import org.meteoinfo.table.DataRow; + +/** + * + * @author yaqiang + */ +public class MapViewUndoRedo { + // + public class ZoomEdit extends AbstractUndoableEdit { + MapView mapView; + Extent newExtent; + Extent oldExtent; + + public ZoomEdit(MapView mapView, Extent oldExtent, Extent newExtent){ + this.mapView = mapView; + this.newExtent = newExtent; + this.oldExtent = oldExtent; + } + + @Override + public String getPresentationName() { + return "Zoom"; + } + + @Override + public void undo() { + super.undo(); + mapView.zoomToExtent(oldExtent); + } + + @Override + public void redo(){ + super.redo(); + mapView.zoomToExtent(newExtent); + } + } + + public class AddFeatureEdit extends FeatureUndoableEdit { + MapView mapView; + Shape shape; + VectorLayer layer; + + public AddFeatureEdit(MapView mapView, VectorLayer layer, Shape shape){ + this.mapView = mapView; + this.layer = layer; + this.shape = shape; + } + + @Override + public String getPresentationName() { + return "Add a Feature"; + } + + @Override + public void undo() { + super.undo(); + layer.editRemoveShape(shape); + mapView.paintLayers(); + System.out.println("Undo add a feature"); + } + + @Override + public void redo(){ + super.redo(); + try { + layer.editAddShape(shape); + mapView.paintLayers(); + System.out.println("Redo add a feature"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class AddFeaturesEdit extends FeatureUndoableEdit { + MapView mapView; + List shapes; + VectorLayer layer; + + public AddFeaturesEdit(MapView mapView, VectorLayer layer, List shapes){ + this.mapView = mapView; + this.layer = layer; + this.shapes = shapes; + } + + @Override + public String getPresentationName() { + return "Add Features"; + } + + @Override + public void undo() { + super.undo(); + for (Shape shape : shapes) + layer.editRemoveShape(shape); + mapView.paintLayers(); + System.out.println("Undo add features"); + } + + @Override + public void redo(){ + super.redo(); + try { + for (Shape shape : shapes) + layer.editAddShape(shape); + mapView.paintLayers(); + System.out.println("Redo add features"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class ReplaceFeatureEdit extends FeatureUndoableEdit { + MapView mapView; + Shape s0; + Shape s1; + Shape s00; + VectorLayer layer; + + public ReplaceFeatureEdit(MapView mapView, VectorLayer layer, Shape s0, Shape s1){ + this.mapView = mapView; + this.layer = layer; + this.s0 = s0; + this.s1 = s1; + this.s00 = (Shape)s0.clone(); + } + + @Override + public String getPresentationName() { + return "Replace Feature"; + } + + @Override + public void undo() { + super.undo(); + s0.cloneValue(s00); + mapView.paintLayers(); + System.out.println("Undo replace feature"); + } + + @Override + public void redo(){ + super.redo(); + s0.cloneValue(s1); + mapView.paintLayers(); + System.out.println("Redo replace feature"); + } + } + + public class SplitFeatureEdit extends FeatureUndoableEdit { + MapView mapView; + Shape shape; + List shapes; + VectorLayer layer; + + public SplitFeatureEdit(MapView mapView, VectorLayer layer, Shape shape, List shapes){ + this.mapView = mapView; + this.layer = layer; + this.shape = shape; + this.shapes = shapes; + } + + @Override + public String getPresentationName() { + return "Split Feature"; + } + + @Override + public void undo() { + super.undo(); + for (Shape s : shapes) + layer.editRemoveShape(s); + try { + layer.editAddShape(shape); + } catch (Exception ex) { + Logger.getLogger(MapViewUndoRedo.class.getName()).log(Level.SEVERE, null, ex); + } + mapView.paintLayers(); + System.out.println("Undo split feature"); + } + + @Override + public void redo(){ + super.redo(); + try { + for (Shape s : shapes) + layer.editAddShape(s); + layer.editRemoveShape(shape); + mapView.paintLayers(); + System.out.println("Redo split feature"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class UnionFeaturesEdit extends FeatureUndoableEdit { + MapView mapView; + Shape shape; + List shapes; + VectorLayer layer; + + public UnionFeaturesEdit(MapView mapView, VectorLayer layer, Shape shape, List shapes){ + this.mapView = mapView; + this.layer = layer; + this.shape = shape; + this.shapes = shapes; + } + + @Override + public String getPresentationName() { + return "Union Features"; + } + + @Override + public void undo() { + super.undo(); + try { + layer.editRemoveShape(shape); + for (Shape s : shapes) + layer.editAddShape(s); + mapView.paintLayers(); + System.out.println("Undo split feature"); + } catch (Exception ex){ + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + + @Override + public void redo(){ + super.redo(); + try { + for (Shape s : shapes) + layer.editRemoveShape(s); + layer.editAddShape(shape); + mapView.paintLayers(); + System.out.println("Redo split feature"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class AddRingEdit extends FeatureUndoableEdit { + MapView mapView; + PolygonShape shape; + List points; + int polyIdx; + int holeIdx; + + public AddRingEdit(MapView mapView, PolygonShape shape, List points, + int polygonIdx, int holeIdx){ + this.mapView = mapView; + this.shape = shape; + this.points = points; + this.polyIdx = polygonIdx; + this.holeIdx = holeIdx; + } + + @Override + public String getPresentationName() { + return "Add a hole"; + } + + @Override + public void undo() { + super.undo(); + shape.removeHole(polyIdx, holeIdx); + mapView.paintLayers(); + System.out.println("Undo add a hole"); + } + + @Override + public void redo(){ + super.redo(); + try { + shape.addHole(points, polyIdx); + mapView.paintLayers(); + System.out.println("Redo add a hole"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class FillRingEdit extends FeatureUndoableEdit { + MapView mapView; + VectorLayer layer; + PolygonShape shape; + PolygonShape hole; + int polyIdx; + int holeIdx; + + public FillRingEdit(MapView mapView, VectorLayer layer, PolygonShape shape, PolygonShape hole, + int polygonIdx, int holeIdx){ + this.mapView = mapView; + this.layer = layer; + this.shape = shape; + this.hole = hole; + this.polyIdx = polygonIdx; + this.holeIdx = holeIdx; + } + + @Override + public String getPresentationName() { + return "Fill a hole"; + } + + @Override + public void undo() { + super.undo(); + shape.removeHole(polyIdx, holeIdx); + layer.editRemoveShape(hole); + mapView.paintLayers(); + System.out.println("Undo Fill a hole"); + } + + @Override + public void redo(){ + super.redo(); + try { + shape.addHole((List)hole.getPoints(), polyIdx); + layer.editAddShape(hole); + mapView.paintLayers(); + System.out.println("Redo Fill a hole"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public class RemoveRingEdit extends FeatureUndoableEdit { + MapView mapView; + PolygonShape shape; + List points; + int polyIdx; + int holeIdx; + + public RemoveRingEdit(MapView mapView, PolygonShape shape, List hole, int polygonIdx, int holeIdx){ + this.mapView = mapView; + this.shape = shape; + this.points = hole; + this.polyIdx = polygonIdx; + this.holeIdx = holeIdx; + } + + @Override + public String getPresentationName() { + return "Remove a hole"; + } + + @Override + public void undo() { + super.undo(); + try { + shape.addHole(points, polyIdx); + mapView.paintLayers(); + System.out.println("Redo remove a hole"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + + @Override + public void redo(){ + super.redo(); + shape.removeHole(polyIdx, holeIdx); + mapView.paintLayers(); + System.out.println("Undo remove a hole"); + } + } + + public class RemoveFeaturesEdit extends FeatureUndoableEdit { + MapView mapView; + List shapes; + VectorLayer layer; + List indices; + List records; + + public RemoveFeaturesEdit(MapView mapView, VectorLayer layer, List shapes){ + this.mapView = mapView; + this.layer = layer; + this.shapes = shapes; + indices = new ArrayList<>(); + records = new ArrayList<>(); + int idx; + DataRow row; + for (Shape shape : shapes){ + idx = layer.getShapes().indexOf(shape); + row = layer.getAttributeTable().getTable().getRows().get(idx); + indices.add(idx); + records.add(row); + } + } + + @Override + public String getPresentationName() { + return "Remove Features"; + } + + @Override + public void undo() { + super.undo(); + try { + for (int i = 0; i < shapes.size(); i++){ + layer.editInsertShape(shapes.get(i), indices.get(i), records.get(i)); + } + mapView.paintLayers(); + System.out.println("Undo remove features"); + } catch (Exception ex) { + Logger.getLogger(MapView.class.getName()).log(Level.SEVERE, null, ex); + } + } + + @Override + public void redo(){ + super.redo(); + for (Shape shape : shapes) + layer.editRemoveShape(shape); + mapView.paintLayers(); + System.out.println("Undo remove features"); + } + } + + class MoveFeatureEdit extends FeatureUndoableEdit { + MapView mapView; + Shape shape; + Point fromPoint; + Point toPoint; + + public MoveFeatureEdit(MapView mapView, Shape shape, Point fromPoint, Point toPoint){ + this.mapView = mapView; + this.shape = shape; + this.fromPoint = new Point(fromPoint.x, fromPoint.y); + this.toPoint = new Point(toPoint.x, toPoint.y); + } + + @Override + public String getPresentationName() { + return "Move a Feature"; + } + + @Override + public void undo() { + super.undo(); + mapView.moveShapeOnScreen(shape, toPoint, fromPoint); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.moveShapeOnScreen(shape, fromPoint, toPoint); + mapView.paintLayers(); + } + } + + class MoveFeaturesEdit extends FeatureUndoableEdit { + MapView mapView; + List shapes; + Point fromPoint; + Point toPoint; + + public MoveFeaturesEdit(MapView mapView, List shapes, Point fromPoint, Point toPoint){ + this.mapView = mapView; + this.shapes = shapes; + this.fromPoint = new Point(fromPoint.x, fromPoint.y); + this.toPoint = new Point(toPoint.x, toPoint.y); + } + + @Override + public String getPresentationName() { + return "Move a Feature"; + } + + @Override + public void undo() { + super.undo(); + for (Shape shape : shapes) + mapView.moveShapeOnScreen(shape, toPoint, fromPoint); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + for (Shape shape : shapes) + mapView.moveShapeOnScreen(shape, fromPoint, toPoint); + mapView.paintLayers(); + } + } + + class MoveFeatureVerticeEdit extends FeatureUndoableEdit { + MapView mapView; + Shape shape; + int verticeIdx; + double newX; + double newY; + double oldX; + double oldY; + + public MoveFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx, double newX, double newY){ + this.mapView = mapView; + this.shape = shape; + this.verticeIdx = vIdx; + this.newX = newX; + this.newY = newY; + this.oldX = shape.getPoints().get(vIdx).X; + this.oldY = shape.getPoints().get(vIdx).Y; + } + + @Override + public String getPresentationName() { + return "Move a Feature"; + } + + @Override + public void undo() { + super.undo(); + shape.moveVertice(verticeIdx, oldX, oldY); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + shape.moveVertice(verticeIdx, newX, newY); + mapView.paintLayers(); + } + } + + class AddFeatureVerticeEdit extends AbstractUndoableEdit { + MapView mapView; + Shape shape; + int verticeIdx; + PointD vertice; + + public AddFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx, PointD vertice){ + this.mapView = mapView; + this.shape = shape; + this.verticeIdx = vIdx; + this.vertice = vertice; + } + + @Override + public String getPresentationName() { + return "Add feature vertice"; + } + + @Override + public void undo() { + super.undo(); + shape.removeVerice(verticeIdx); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + shape.addVertice(verticeIdx, vertice); + mapView.paintLayers(); + } + } + + class RemoveFeatureVerticeEdit extends AbstractUndoableEdit { + MapView mapView; + Shape shape; + int verticeIdx; + PointD vertice; + + public RemoveFeatureVerticeEdit(MapView mapView, Shape shape, int vIdx){ + this.mapView = mapView; + this.shape = shape; + this.verticeIdx = vIdx; + this.vertice = shape.getPoints().get(vIdx); + } + + @Override + public String getPresentationName() { + return "Remove feature vertice"; + } + + @Override + public void undo() { + super.undo(); + shape.addVertice(verticeIdx, vertice); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + shape.removeVerice(verticeIdx); + mapView.paintLayers(); + } + } + + class AddGraphicEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + + public AddGraphicEdit(MapView mapView, Graphic graphic){ + this.mapView = mapView; + this.graphic = graphic; + } + + @Override + public String getPresentationName() { + return "Add a Graphic"; + } + + @Override + public void undo() { + super.undo(); + mapView.removeGraphic(graphic); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.getGraphicCollection().add(graphic); + mapView.paintLayers(); + } + } + + class RemoveGraphicEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + + public RemoveGraphicEdit(MapView mapView, Graphic graphic){ + this.mapView = mapView; + this.graphic = graphic; + } + + @Override + public String getPresentationName() { + return "Remove a Graphic"; + } + + @Override + public void undo() { + super.undo(); + mapView.getGraphicCollection().add(graphic); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.removeGraphic(graphic); + mapView.paintLayers(); + } + } + + class RemoveGraphicsEdit extends AbstractUndoableEdit { + MapView mapView; + List graphics; + + public RemoveGraphicsEdit(MapView mapView, List graphics){ + this.mapView = mapView; + this.graphics = new ArrayList<>(graphics); + } + + @Override + public String getPresentationName() { + return "Remove Graphics"; + } + + @Override + public void undo() { + super.undo(); + mapView.getGraphicCollection().addAll(graphics); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.getGraphicCollection().removeAll(graphics); + mapView.paintLayers(); + } + } + + class MoveGraphicEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + Point fromPoint; + Point toPoint; + + public MoveGraphicEdit(MapView mapView, Graphic graphic, Point fromPoint, Point toPoint){ + this.mapView = mapView; + this.graphic = graphic; + this.fromPoint = new Point(fromPoint.x, fromPoint.y); + this.toPoint = new Point(toPoint.x, toPoint.y); + } + + @Override + public String getPresentationName() { + return "Move a Graphic"; + } + + @Override + public void undo() { + super.undo(); + mapView.moveShapeOnScreen(graphic.getShape(), toPoint, fromPoint); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.moveShapeOnScreen(graphic.getShape(), fromPoint, toPoint); + mapView.paintLayers(); + } + } + + class MoveGraphicVerticeEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + int verticeIdx; + double newX; + double newY; + double oldX; + double oldY; + + public MoveGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx, double newX, double newY){ + this.mapView = mapView; + this.graphic = graphic; + this.verticeIdx = vIdx; + this.newX = newX; + this.newY = newY; + this.oldX = graphic.getShape().getPoints().get(vIdx).X; + this.oldY = graphic.getShape().getPoints().get(vIdx).Y; + } + + @Override + public String getPresentationName() { + return "Move Grahic vertice"; + } + + @Override + public void undo() { + super.undo(); + graphic.verticeMoveUpdate(verticeIdx, oldX, oldY); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + graphic.verticeMoveUpdate(verticeIdx, newX, newY); + mapView.paintLayers(); + } + } + + class AddGraphicVerticeEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + int verticeIdx; + PointD vertice; + + public AddGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx, PointD vertice){ + this.mapView = mapView; + this.graphic = graphic; + this.verticeIdx = vIdx; + this.vertice = vertice; + } + + @Override + public String getPresentationName() { + return "Add Grahic vertice"; + } + + @Override + public void undo() { + super.undo(); + graphic.verticeRemoveUpdate(verticeIdx); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + graphic.verticeAddUpdate(verticeIdx, vertice); + mapView.paintLayers(); + } + } + + class RemoveGraphicVerticeEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + int verticeIdx; + PointD vertice; + + public RemoveGraphicVerticeEdit(MapView mapView, Graphic graphic, int vIdx){ + this.mapView = mapView; + this.graphic = graphic; + this.verticeIdx = vIdx; + this.vertice = graphic.getShape().getPoints().get(vIdx); + } + + @Override + public String getPresentationName() { + return "Remove Grahic vertice"; + } + + @Override + public void undo() { + super.undo(); + graphic.verticeAddUpdate(verticeIdx, vertice); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + graphic.verticeRemoveUpdate(verticeIdx); + mapView.paintLayers(); + } + } + + class ResizeGraphicEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + Rectangle oldRect; + Rectangle newRect; + + public ResizeGraphicEdit(MapView mapView, Graphic graphic, Rectangle newRect){ + this.mapView = mapView; + this.graphic = graphic; + this.newRect = newRect; + this.oldRect = mapView.getGraphicRectangle(graphic); + } + + @Override + public String getPresentationName() { + return "Resize a Graphic"; + } + + @Override + public void undo() { + super.undo(); + mapView.resizeShapeOnScreen(graphic, oldRect); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + mapView.resizeShapeOnScreen(graphic, newRect); + mapView.paintLayers(); + } + } + + class SmoothGraphicEdit extends AbstractUndoableEdit { + MapView mapView; + Graphic graphic; + List oldPoints; + List newPoints; + + public SmoothGraphicEdit(MapView mapView, Graphic graphic, List points){ + this.mapView = mapView; + this.graphic = graphic; + this.newPoints = points; + this.oldPoints = (List)graphic.getShape().getPoints(); + } + + @Override + public String getPresentationName() { + return "Resize a Graphic"; + } + + @Override + public void undo() { + super.undo(); + graphic.getShape().setPoints(oldPoints); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + graphic.getShape().setPoints(newPoints); + mapView.paintLayers(); + } + } + + class SmoothFeatureEdit extends AbstractUndoableEdit { + MapView mapView; + Shape shape; + List oldPoints; + List newPoints; + + public SmoothFeatureEdit(MapView mapView, Shape shape, List points){ + this.mapView = mapView; + this.shape = shape; + this.newPoints = points; + this.oldPoints = (List)shape.getPoints(); + } + + @Override + public String getPresentationName() { + return "Resize a Graphic"; + } + + @Override + public void undo() { + super.undo(); + shape.setPoints(oldPoints); + mapView.paintLayers(); + } + + @Override + public void redo(){ + super.redo(); + shape.setPoints(newPoints); + mapView.paintLayers(); + } + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/ProjectionSet.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/ProjectionSet.java index 785d5d5f..b5ab4c73 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/ProjectionSet.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/ProjectionSet.java @@ -1,1248 +1,1248 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.map; - -import org.meteoinfo.global.event.IProjectionChangedListener; -import org.meteoinfo.global.event.ProjectionChangedEvent; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.layer.RasterLayer; -import org.meteoinfo.layer.VectorLayer; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.info.ProjectionInfo; -import org.meteoinfo.projection.Reproject; -import org.meteoinfo.shape.CircleShape; -import org.meteoinfo.shape.CurveLineShape; -import org.meteoinfo.shape.CurvePolygonShape; -import org.meteoinfo.shape.EllipseShape; -import org.meteoinfo.shape.Graphic; -import org.meteoinfo.shape.GraphicCollection; -import org.meteoinfo.shape.PointShape; -import org.meteoinfo.shape.Polygon; -import org.meteoinfo.shape.PolygonShape; -import org.meteoinfo.shape.Polyline; -import org.meteoinfo.shape.PolylineShape; -import org.meteoinfo.shape.Shape; -import org.meteoinfo.shape.StationModelShape; -import org.meteoinfo.shape.WindArrow; -import org.meteoinfo.shape.WindBarb; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.swing.event.EventListenerList; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CRSFactory; - -/** - * - * @author Yaqiang Wang - */ -public class ProjectionSet { - // - - private final EventListenerList _listeners = new EventListenerList(); - CRSFactory _crsFactory = new CRSFactory(); - private ProjectionInfo _projInfo; - //private String _projStr; - //private double _refLon; - //private double _refCutLon; - // - // - - /** - * Constructor - */ - public ProjectionSet() { - _projInfo = KnownCoordinateSystems.geographic.world.WGS1984; - //_projStr = _projInfo.getParameterString(); - //_refLon = 0; - } - // - - // - public void addProjectionChangedListener(IProjectionChangedListener listener) { - this._listeners.add(IProjectionChangedListener.class, listener); - } - - public void removeViewExtentChangedListener(IProjectionChangedListener listener) { - this._listeners.remove(IProjectionChangedListener.class, listener); - } - - public void fireProjectionChangedEvent() { - fireProjectionChangedEvent(new ProjectionChangedEvent(this)); - } - - private void fireProjectionChangedEvent(ProjectionChangedEvent event) { - Object[] listeners = _listeners.getListenerList(); - for (int i = 0; i < listeners.length; i = i + 2) { - if (listeners[i] == IProjectionChangedListener.class) { - ((IProjectionChangedListener) listeners[i + 1]).projectionChangedEvent(event); - } - } - } - // - // - - /** - * Get if is Lon/Lat projection - * - * @return Boolean - */ - public boolean isLonLatMap() { - return "longlat".equals(_projInfo.getCoordinateReferenceSystem().getProjection().toString().toLowerCase()); - } - - /** - * Get projection info - * - * @return Projection Info - */ - public ProjectionInfo getProjInfo() { - return _projInfo; - } - - /** - * Set projection info - * - * @param projInfo The Projection info - */ - public void setProjInfo(ProjectionInfo projInfo) { - _projInfo = projInfo; - } - - /** - * Get Porj4 string - * - * @return Proj4 string - */ - public String getProjStr() { - return _projInfo.toProj4String(); - } - - /** - * Set proj4 string - * - * @param projStr Porj4 string - */ - public void setProjStr(String projStr) { - _projInfo = ProjectionInfo.factory(projStr); - } - -// /** -// * Get reference longitude -// * -// * @return Reference longitue -// */ -// public double getRefLon() { -// return _refLon; -// } -// -// /** -// * Set reference longitude -// * -// * @param lon Reference longitude -// */ -// public void setRefLon(double lon) { -// _refLon = lon; -// } - -// /** -// * Get reference cut longitude -// * -// * @return Reference cut longitude -// */ -// public double getRefCutLon() { -// return _refCutLon; -// } -// -// /** -// * Set reference cut longitude -// * -// * @param lon -// */ -// public void setRefCutLon(double lon) { -// _refCutLon = lon; -// } - // - // - - /** - * Get projected extent from lon/lat - * - * @param sExtent Lon/lat extent - * @return Projected extent - */ - public Extent getProjectedExtentFromLonLat(Extent sExtent) { - Extent aExtent = new Extent(); - ProjectionInfo fromProj = KnownCoordinateSystems.geographic.world.WGS1984; - ProjectionInfo toProj = _projInfo; - - //Get the border of longitude and latitude - double[][] points = new double[4][]; - points[0] = new double[]{sExtent.minX, sExtent.minY}; - points[1] = new double[]{sExtent.minX, sExtent.maxY}; - points[2] = new double[]{sExtent.maxX, sExtent.maxY}; - points[3] = new double[]{sExtent.maxX, sExtent.minY}; - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - - //Get lon lat extent - aExtent.minX = Math.min(points[0][0], points[1][0]); - aExtent.minY = Math.min(points[0][1], points[3][1]); - aExtent.maxX = Math.max(points[2][0], points[3][0]); - aExtent.maxY = Math.max(points[1][1], points[2][1]); - - return aExtent; - } - - /** - * Project layers - * - * @param aMapView The Map view - * @param toProj To projection info - */ - public void projectLayers(MapView aMapView, ProjectionInfo toProj) { - projectLayers(aMapView, toProj, true); - } - - /** - * Project layers - * - * @param aMapView The map view - * @param toProj To projection - * @param isUpdateView If repaint mapview - */ - public void projectLayers(MapView aMapView, ProjectionInfo toProj, boolean isUpdateView) { - if (aMapView.getProjection().getProjInfo().toProj4String().equals(toProj.toProj4String())) { - return; - } - - aMapView.setLockViewUpdate(true); - - ProjectionInfo fromProj = aMapView.getProjection().getProjInfo(); - - aMapView.getProjection().setProjInfo(toProj); - double refLon = toProj.getRefCutLon(); - //aMapView.getProjection().setRefCutLon(refLon); - - for (int i = 0; i < aMapView.getLayers().size(); i++) { - switch (aMapView.getLayers().get(i).getLayerType()) { - case VectorLayer: - VectorLayer oLayer = (VectorLayer) aMapView.getLayers().get(i); - //projectLayer(oLayer, toProj); - ProjectionUtil.projectLayer(oLayer, toProj); - break; - case RasterLayer: - RasterLayer oRLayer = (RasterLayer) aMapView.getLayers().get(i); - ProjectionUtil.projectLayer(oRLayer, toProj); - break; - } - } - - //Project graphics - if (aMapView.getGraphicCollection().size() > 0) { - GraphicCollection newGCollection = projectGraphics(aMapView.getGraphicCollection(), fromProj, toProj); - aMapView.setGraphicCollection(newGCollection); - } - - aMapView.setExtent(aMapView.getLayersWholeExtent()); - Extent aExten = aMapView.getExtent(); - aMapView.setLonLatLayer(aMapView.generateLonLatLayer()); - ProjectionUtil.projectLayer(aMapView.getLonLatLayer(), toProj); - //aMapView.setLonLatProjLayer(aMapView.getLonLatLayer()); - for (int i = 0; i < aMapView.getLonLatLayer().getShapeNum(); i++) { - PolylineShape aPLS = (PolylineShape) aMapView.getLonLatLayer().getShapes().get(i); - if (aPLS.getPolylines().size() == 2) { - PointD aP = aPLS.getPolylines().get(0).getPointList().get(aPLS.getPolylines().get(0).getPointList().size() - 1); - PointD bP = aPLS.getPolylines().get(1).getPointList().get(aPLS.getPolylines().get(1).getPointList().size() - 1); - boolean isJoin = false; - if (refLon == 0) { - if (Math.abs(aP.X) < 0.1 && Math.abs(bP.X) < 0.1 && MIMath.doubleEquals(aP.Y, bP.Y)) { - isJoin = true; - } - } else if (MIMath.doubleEquals(aP.X, bP.X) && MIMath.doubleEquals(aP.Y, bP.Y)) { - isJoin = true; - } - - if (isJoin) { - List polyLines = new ArrayList<>(); - Polyline aPL = new Polyline(); - List pList = (List) new ArrayList<>(aPLS.getPolylines().get(1).getPointList()); - List bPList = (List) new ArrayList<>(aPLS.getPolylines().get(0).getPointList()); - Collections.reverse(bPList); - pList.addAll(bPList); - aPL.setPointList(pList); - polyLines.add(aPL); - aPLS.setPolylines(polyLines); - //aMapView.getLonLatProjLayer().getShapes().get(i) = aPLS; - } - } - } - - if (isUpdateView) { - aMapView.setLockViewUpdate(false); - } - aMapView.zoomToExtent(aExten); - - this.fireProjectionChangedEvent(); - } - -// /** -// * Project raster layer -// * -// * @param oLayer The layer -// * @param toProj To projection -// */ -// public void projectLayer(RasterLayer oLayer, ProjectionInfo toProj) { -// try { -// // if (toProj.getProjectionName() == ProjectionNames.Robinson) { -//// return; -//// } -// -// if (oLayer.getProjInfo().toProj4String().equals(toProj.toProj4String())) { -// if (oLayer.isProjected()) { -// oLayer.getOriginData(); -// oLayer.updateGridData(); -// if (oLayer.getLegendScheme().getBreakNum() < 50) { -// oLayer.updateImage(); -// } else { -// oLayer.setPaletteByLegend(); -// } -// } -// return; -// } -// -// if (!oLayer.isProjected()) { -// oLayer.updateOriginData(); -// } else { -// oLayer.getOriginData(); -// } -// -// oLayer.setGridData(oLayer.getGridData().project(oLayer.getProjInfo(), toProj)); -// oLayer.updateImage(oLayer.getLegendScheme()); -//// if (oLayer.getLegendScheme().getBreakNum() < 50) { -//// oLayer.updateImage(oLayer.getLegendScheme()); -//// } else { -//// oLayer.setPaletteByLegend(); -//// } -// } catch (InvalidRangeException ex) { -// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); -// } -// } -// -// /** -// * Project vector layer -// * -// * @param oLayer The layer -// * @param toProj To projection info -// */ -// public void projectLayer(VectorLayer oLayer, ProjectionInfo toProj) { -// projectLayer(oLayer, toProj, true); -// } -// -// /** -// * Project vector layer -// * -// * @param oLayer The layer -// * @param toProj To projection info -// * @param projectLabels If project labels -// */ -// public void projectLayer(VectorLayer oLayer, ProjectionInfo toProj, boolean projectLabels) { -// ProjectionInfo fromProj = oLayer.getProjInfo(); -// if (fromProj.equals(toProj)) { -// if (oLayer.isProjected()) { -// oLayer.getOriginData(); -// } -// -// return; -// } -// -// if (oLayer.isProjected()) { -// oLayer.getOriginData(); -// } else { -// oLayer.updateOriginData(); -// } -// -// double refLon = toProj.getRefCutLon(); -// if (oLayer.getExtent().maxX > 180 && oLayer.getExtent().minX > refLon) { -// refLon += 360; -// } -// -// //coordinate transform process -// int i, s; -// ArrayList newPoints = new ArrayList(); -// Extent lExtent = new Extent(); -// -// DataTable aTable = new DataTable(); -// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { -// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); -// aTable.getColumns().add(bDC); -// } -// -// //aLayer.AttributeTable.Table.Rows.Clear(); -// switch (oLayer.getShapeType()) { -// case Point: -// case PointM: -// case PointZ: -// case WeatherSymbol: -// case WindArraw: -// case WindBarb: -// case StationModel: -// List shapePoints = new ArrayList<>(); -// newPoints.clear(); -// for (s = 0; s < oLayer.getShapeNum(); s++) { -// PointShape aPS = (PointShape) oLayer.getShapes().get(s); -// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { -// switch (toProj.getProjectionName()) { -// case Lambert_Conformal_Conic: -// if (aPS.getPoint().Y < -80) { -// continue; -// } -// break; -// case North_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().Y < 0) { -// continue; -// } -// break; -// case South_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().Y > 0) { -// continue; -// } -// break; -// case Mercator: -// if (aPS.getPoint().Y > 85.0511 || aPS.getPoint().Y < -85.0511) { -// continue; -// } -// break; -// } -// } -// aPS = projectPointShape(aPS, fromProj, toProj); -// if (aPS != null) { -// shapePoints.add(aPS); -// newPoints.add(aPS.getPoint()); -// -// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); -// try { -// aTable.addRow(aDR); -// } catch (Exception ex) { -// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); -// } -// } -// } -// oLayer.setShapes(new ArrayList<>(shapePoints)); -// oLayer.setExtent(MIMath.getPointsExtent(newPoints)); -// -// break; -// case Polyline: -// case PolylineM: -// case PolylineZ: -// List newPolylines = new ArrayList<>(); -// for (s = 0; s < oLayer.getShapeNum(); s++) { -// PolylineShape aPLS = (PolylineShape) oLayer.getShapes().get(s); -// List plsList = new ArrayList<>(); -// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { -// switch (toProj.getProjectionName()) { -// case Lambert_Conformal_Conic: -// if (aPLS.getExtent().minY < -80) { -// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, -80, true); -// } -// break; -// case North_Polar_Stereographic_Azimuthal: -// if (aPLS.getExtent().minY < 0) { -// //continue; -// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 0, true); -// } -// break; -// case South_Polar_Stereographic_Azimuthal: -// if (aPLS.getExtent().maxY > 0) { -// //continue; -// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 0, false); -// } -// break; -// case Mercator: -// if (aPLS.getExtent().maxY > 85.0511) { -// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 85.0511, false); -// } -// if (aPLS.getExtent().minY < -85.0511) { -// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, -85.0511, true); -// } -// break; -// } -// if (aPLS == null) { -// continue; -// } -// -//// aPLS = GeoComputation.clipPolylineShape_Lon(aPLS, refLon); -//// if (aPLS == null) { -//// continue; -//// } -// if (aPLS.getExtent().minX < refLon && aPLS.getExtent().maxX > refLon) { -// plsList.add(GeoComputation.clipPolylineShape_Lon(aPLS, refLon)); -// } else { -// plsList.add(aPLS); -// } -// } else { -// plsList.add(aPLS); -// } -// for (i = 0; i < plsList.size(); i++) { -// aPLS = plsList.get(i); -// aPLS = projectPolylineShape(aPLS, fromProj, toProj); -// if (aPLS != null) { -// newPolylines.add(aPLS); -// -// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); -// try { -// aTable.addRow(aDR); -// } catch (Exception ex) { -// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); -// } -// -// if (s == 0 && i == 0) { -// lExtent = (Extent) aPLS.getExtent().clone(); -// } else { -// lExtent = MIMath.getLagerExtent(lExtent, aPLS.getExtent()); -// } -// } -// } -// } -// oLayer.setShapes(new ArrayList<>(newPolylines)); -// newPolylines.clear(); -// oLayer.setExtent(lExtent); -// break; -// case Polygon: -// case PolygonM: -// List newPolygons = new ArrayList<>(); -// for (s = 0; s < oLayer.getShapeNum(); s++) { -// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); -// PolygonShape aPGS = (PolygonShape) oLayer.getShapes().get(s); -// List pgsList = new ArrayList<>(); -// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { -// switch (toProj.getProjectionName()) { -// case Lambert_Conformal_Conic: -// if (aPGS.getExtent().minY < -80) { -// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, -80, true); -// } -// break; -// case North_Polar_Stereographic_Azimuthal: -// if (aPGS.getExtent().minY < 0) { -// //continue; -// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 0, true); -// } -// break; -// case South_Polar_Stereographic_Azimuthal: -// if (aPGS.getExtent().maxY > 0) { -// //continue; -// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 0, false); -// } -// break; -// case Mercator: -// if (aPGS.getExtent().maxY > 85.0511) { -// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 85.0511, false); -// } -// if (aPGS.getExtent().minY < -85.0511) { -// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, -85.0511, true); -// } -// break; -// } -// if (aPGS == null) { -// continue; -// } -// -// if (aPGS.getExtent().minX <= refLon && aPGS.getExtent().maxX >= refLon) { -// pgsList.add(GeoComputation.clipPolygonShape_Lon(aPGS, refLon)); -// } else { -// pgsList.add(aPGS); -// } -// } else { -// pgsList.add(aPGS); -// } -// for (i = 0; i < pgsList.size(); i++) { -// aPGS = pgsList.get(i); -// aPGS = projectPolygonShape(aPGS, fromProj, toProj); -// if (aPGS != null) { -// newPolygons.add(aPGS); -// -// aTable.getRows().add(aDR); -// -// if (s == 0) { -// lExtent = (Extent) aPGS.getExtent().clone(); -// } else { -// lExtent = MIMath.getLagerExtent(lExtent, aPGS.getExtent()); -// } -// } -// } -// } -// oLayer.setShapes(new ArrayList<>(newPolygons)); -// newPolygons.clear(); -// oLayer.setExtent(lExtent); -// break; -// } -// oLayer.getAttributeTable().setTable(aTable); -// -// if (oLayer.getLabelPoints().size() > 0) { -// if (projectLabels) { -// oLayer.setLabelPoints(projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); -// } else { -// oLayer.setLabelPoints(new ArrayList<>(oLayer.getLabelPoints())); -// } -// } -// } -// -// /** -// * Project layer angle -// * -// * @param oLayer The layer -// * @param fromProj From projection -// * @param toProj To projection -// * @return VectorLayer -// */ -// public VectorLayer projectLayerAngle(VectorLayer oLayer, ProjectionInfo fromProj, ProjectionInfo toProj) { -// //coordinate transform process -// ArrayList newPoints = new ArrayList(); -// -// VectorLayer aLayer = (VectorLayer) oLayer.clone(); -// -// //aLayer.AttributeTable.Table = oLayer.AttributeTable.Table.Clone(); -// DataTable aTable = new DataTable(); -// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { -// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); -// aTable.getColumns().add(bDC); -// } -// -// int s; -// List vectors = new ArrayList<>(); -// newPoints.clear(); -// for (s = 0; s < aLayer.getShapeNum(); s++) { -// PointShape aPS = (PointShape) aLayer.getShapes().get(s); -// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { -// switch (toProj.getProjectionName()) { -// case Lambert_Conformal_Conic: -// case North_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().X < -89) { -// continue; -// } -// break; -// case South_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().Y > 89) { -// continue; -// } -// break; -// } -// } -// double[] fromP = new double[]{aPS.getPoint().X, aPS.getPoint().Y}; -// double[] toP; -// double[][] points = new double[1][]; -// points[0] = (double[]) fromP.clone(); -// try { -// //Reproject point back to fromProj -// Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length); -// toP = points[0]; -// switch (aLayer.getLayerDrawType()) { -// case Vector: -// ((WindArrow) aPS).angle = projectAngle(((WindArrow) aPS).angle, toP, fromP, fromProj, toProj); -// break; -// case Barb: -// ((WindBarb) aPS).angle = projectAngle(((WindBarb) aPS).angle, toP, fromP, fromProj, toProj); -// break; -// case StationModel: -// ((StationModelShape) aPS).windBarb.angle = projectAngle(((StationModelShape) aPS).windBarb.angle, toP, fromP, fromProj, toProj); -// break; -// } -// newPoints.add(aPS.getPoint()); -// vectors.add(aPS); -// -// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); -// aTable.getRows().add(aDR); -// } catch (Exception e) { -// } -// } -// aLayer.setShapes(new ArrayList<>(vectors)); -// aLayer.setExtent(MIMath.getPointsExtent(newPoints)); -// aLayer.getAttributeTable().setTable(aTable); -// -// //if (aLayer.LabelSetV.DrawLabels) -// //{ -// // aLayer.AddLabels(); -// //} -// return aLayer; -// } - -// /** -// * Project wind layer -// * -// * @param oLayer Origin layer -// * @param toProj To projection -// * @param IfReprojectAngle If reproject wind angle -// */ -// public void projectWindLayer(VectorLayer oLayer, ProjectionInfo toProj, boolean IfReprojectAngle) { -// ProjectionInfo fromProj = oLayer.getProjInfo(); -// if (fromProj.toProj4String().equals(toProj.toProj4String())) { -// if (oLayer.isProjected()) { -// oLayer.getOriginData(); -// } -// -// return; -// } -// -// if (oLayer.isProjected()) { -// oLayer.getOriginData(); -// } else { -// oLayer.updateOriginData(); -// } -// -// //Set reference longitude -// double refLon = toProj.getRefCutLon(); -// if (oLayer.getExtent().maxX > 180 && oLayer.getExtent().minX > refLon) { -// refLon += 360; -// } -// -// //coordinate transform process -// int s; -// //PointD wPoint = new PointD(); -// PointD aPoint; -// List newPoints = new ArrayList<>(); -// //Extent lExtent = new Extent(); -// -// DataTable aTable = new DataTable(); -// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { -// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); -// aTable.getColumns().add(bDC); -// } -// -// List shapes = new ArrayList<>(); -// newPoints.clear(); -// for (s = 0; s < oLayer.getShapeNum(); s++) { -// PointShape aPS = (PointShape) oLayer.getShapes().get(s); -// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { -// switch (toProj.getProjectionName()) { -// case Lambert_Conformal_Conic: -// case North_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().Y < -89) { -// continue; -// } -// break; -// case South_Polar_Stereographic_Azimuthal: -// if (aPS.getPoint().Y > 89) { -// continue; -// } -// break; -// } -// } -// double[] fromP = new double[]{aPS.getPoint().X, aPS.getPoint().Y}; -// double[] toP; -// double[][] points = new double[1][]; -// points[0] = (double[]) fromP.clone(); -// try { -// Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); -// toP = points[0]; -// aPoint = new PointD(); -// aPoint.X = (float) toP[0]; -// aPoint.Y = (float) toP[1]; -// aPS.setPoint(aPoint); -// if (IfReprojectAngle) { -// switch (oLayer.getLayerDrawType()) { -// case Vector: -// ((WindArrow) aPS).angle = projectAngle(((WindArrow) aPS).angle, fromP, toP, fromProj, toProj); -// break; -// case Barb: -// ((WindBarb) aPS).angle = projectAngle(((WindBarb) aPS).angle, fromP, toP, fromProj, toProj); -// break; -// case StationModel: -// ((StationModelShape) aPS).windBarb.angle = projectAngle(((StationModelShape) aPS).windBarb.angle, fromP, toP, fromProj, toProj); -// break; -// } -// } -// newPoints.add(aPoint); -// shapes.add(aPS); -// -// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); -// aTable.getRows().add(aDR); -// } catch (Exception e) { -// } -// } -// oLayer.setShapes(new ArrayList<>(shapes)); -// oLayer.setExtent(MIMath.getPointsExtent(newPoints)); -// oLayer.getAttributeTable().setTable(aTable); -// -// if (oLayer.getLabelPoints().size() > 0) { -// oLayer.setLabelPoints(projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); -// } -// } - - private PointShape projectPointShape(PointShape aPS, ProjectionInfo fromProj, ProjectionInfo toProj) { - PointShape newPS = (PointShape) aPS.clone(); - double[][] points = new double[1][]; - points[0] = new double[]{newPS.getPoint().X, newPS.getPoint().Y}; - double[] fromP = new double[]{newPS.getPoint().X, newPS.getPoint().Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - double[] toP = points[0]; - newPS.setPoint(new PointD(points[0][0], points[0][1])); - switch (aPS.getShapeType()) { - case WindBarb: - ((WindBarb) newPS).angle = projectAngle(((WindBarb) newPS).angle, fromP, toP, fromProj, toProj); - break; - case WindArraw: - ((WindArrow) newPS).angle = projectAngle(((WindArrow) newPS).angle, fromP, toP, fromProj, toProj); - break; - case StationModel: - ((StationModelShape) newPS).windBarb.angle = projectAngle(((StationModelShape) newPS).windBarb.angle, fromP, toP, fromProj, toProj); - break; - } - return newPS; - } else { - return null; - } - } catch (Exception e) { - return null; - } - } - - private PolylineShape projectPolylineShape(PolylineShape aPLS, ProjectionInfo fromProj, ProjectionInfo toProj) { - List polyLines = new ArrayList<>(); - for (int i = 0; i < aPLS.getPolylines().size(); i++) { - List newPoints = new ArrayList<>(); - Polyline aPL = aPLS.getPolylines().get(i); - Polyline bPL; - double x; - for (int j = 0; j < aPL.getPointList().size(); j++) { - double[][] points = new double[1][]; - PointD wPoint = aPL.getPointList().get(j); - x = wPoint.X; - if (fromProj.isLonLat()) { - if (x > 180) { - x -= 360; - } else if (x < -180) { - x += 360; - } - } - points[0] = new double[]{x, wPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - //wPoint = new PointD(); - wPoint.X = points[0][0]; - wPoint.Y = points[0][1]; - newPoints.add(wPoint); - } - } catch (Exception e) { - //break; - } - } - - if (newPoints.size() > 1) { - bPL = new Polyline(); - bPL.setPointList(newPoints); - polyLines.add(bPL); - } - } - - if (polyLines.size() > 0) { - aPLS.setPolylines(polyLines); - - return aPLS; - } else { - return null; - } - } - - private CurveLineShape projectCurvelineShape(CurveLineShape aPLS, ProjectionInfo fromProj, ProjectionInfo toProj) { - List polyLines = new ArrayList<>(); - for (int i = 0; i < aPLS.getPolylines().size(); i++) { - List newPoints = new ArrayList<>(); - Polyline aPL = aPLS.getPolylines().get(i); - Polyline bPL; - for (int j = 0; j < aPL.getPointList().size(); j++) { - double[][] points = new double[1][]; - PointD wPoint = aPL.getPointList().get(j); - points[0] = new double[]{wPoint.X, wPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - wPoint = new PointD(); - wPoint.X = points[0][0]; - wPoint.Y = points[0][1]; - newPoints.add(wPoint); - } - } catch (Exception e) { - break; - } - } - - if (newPoints.size() > 1) { - bPL = new Polyline(); - bPL.setPointList(newPoints); - polyLines.add(bPL); - } - } - - if (polyLines.size() > 0) { - aPLS.setPolylines(polyLines); - - return aPLS; - } else { - return null; - } - } - - /** - * Project polygon shape - * - * @param aPGS A polygon shape - * @param fromProj From projection - * @param toProj To porjection - * @return Projected polygon shape - */ - public PolygonShape projectPolygonShape(PolygonShape aPGS, ProjectionInfo fromProj, ProjectionInfo toProj) { - List polygons = new ArrayList<>(); - for (int i = 0; i < aPGS.getPolygons().size(); i++) { - Polygon aPG = aPGS.getPolygons().get(i); - Polygon bPG = null; - for (int r = 0; r < aPG.getRingNumber(); r++) { - List pList = (List)aPG.getRings().get(r); - List newPoints = new ArrayList<>(); - for (int j = 0; j < pList.size(); j++) { - double[][] points = new double[1][]; - PointD wPoint = pList.get(j); - points[0] = new double[]{wPoint.X, wPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - wPoint = new PointD(); - wPoint.X = points[0][0]; - wPoint.Y = points[0][1]; - newPoints.add(wPoint); - } - } catch (Exception e) { - break; - } - } - - if (r == 0) { - if (newPoints.size() > 2) { - bPG = new Polygon(); - bPG.setOutLine(newPoints); - } else { - break; - } - } else if (newPoints.size() > 2) { - if (bPG != null) - bPG.addHole(newPoints); - } - } - - if (bPG != null) { - polygons.add(bPG); - } - } - - if (polygons.size() > 0) { - aPGS.setPolygons(polygons); - - return aPGS; - } else { - return null; - } - } - - private CurvePolygonShape projectCurvePolygonShape(CurvePolygonShape aPGS, ProjectionInfo fromProj, ProjectionInfo toProj) { - List polygons = new ArrayList<>(); - for (int i = 0; i < aPGS.getPolygons().size(); i++) { - Polygon aPG = aPGS.getPolygons().get(i); - Polygon bPG = null; - for (int r = 0; r < aPG.getRingNumber(); r++) { - List pList = (List)aPG.getRings().get(r); - List newPoints = new ArrayList<>(); - for (int j = 0; j < pList.size(); j++) { - double[][] points = new double[1][]; - PointD wPoint = pList.get(j); - points[0] = new double[]{wPoint.X, wPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - wPoint = new PointD(); - wPoint.X = points[0][0]; - wPoint.Y = points[0][1]; - newPoints.add(wPoint); - } - } catch (Exception e) { - break; - } - } - - if (r == 0) { - if (newPoints.size() > 2) { - bPG = new Polygon(); - bPG.setOutLine(newPoints); - } else { - break; - } - } else if (newPoints.size() > 2) { - if (bPG != null) - bPG.addHole(newPoints); - } - } - - if (bPG != null) { - polygons.add(bPG); - } - } - - if (polygons.size() > 0) { - aPGS.setPolygons(polygons); - - return aPGS; - } else { - return null; - } - } - - private CircleShape projectCircleShape(CircleShape aCS, ProjectionInfo fromProj, ProjectionInfo toProj) { - double radius = Math.abs(aCS.getPoints().get(1).X - aCS.getPoints().get(0).X); - double[][] points = new double[1][]; - PointD centerPoint = new PointD(aCS.getPoints().get(0).X + radius, aCS.getPoints().get(0).Y); - points[0] = new double[]{centerPoint.X, centerPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - centerPoint.X = points[0][0]; - centerPoint.Y = points[0][1]; - } else { - return null; - } - } catch (Exception e) { - return null; - } - - points = new double[1][]; - PointD leftPoint = aCS.getPoints().get(0); - points[0] = new double[]{leftPoint.X, leftPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - leftPoint.X = points[0][0]; - leftPoint.Y = points[0][1]; - } else { - return null; - } - } catch (Exception e) { - return null; - } - - radius = Math.abs(centerPoint.X - leftPoint.X); - List newPoints = new ArrayList<>(); - newPoints.add(new PointD(centerPoint.X - radius, centerPoint.Y)); - newPoints.add(new PointD(centerPoint.X, centerPoint.Y - radius)); - newPoints.add(new PointD(centerPoint.X + radius, centerPoint.Y)); - newPoints.add(new PointD(centerPoint.X, centerPoint.Y + radius)); - CircleShape newCS = new CircleShape(); - newCS.setPoints(newPoints); - - return newCS; - } - - private EllipseShape projectEllipseShape(EllipseShape aES, ProjectionInfo fromProj, ProjectionInfo toProj) { - double xRadius = Math.abs(aES.getPoints().get(2).X - aES.getPoints().get(0).X) / 2; - double yRadius = Math.abs(aES.getPoints().get(2).Y - aES.getPoints().get(0).Y) / 2; - double[][] points = new double[1][]; - PointD centerPoint = new PointD(aES.getExtent().minX + xRadius, aES.getExtent().minY + yRadius); - points[0] = new double[]{centerPoint.X, centerPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - centerPoint.X = points[0][0]; - centerPoint.Y = points[0][1]; - } else { - return null; - } - } catch (Exception e) { - return null; - } - - points = new double[1][]; - PointD lbPoint = new PointD(aES.getExtent().minX, aES.getExtent().minY); - points[0] = new double[]{lbPoint.X, lbPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - lbPoint.X = points[0][0]; - lbPoint.Y = points[0][1]; - } else { - return null; - } - } catch (Exception e) { - return null; - } - - xRadius = Math.abs(centerPoint.X - lbPoint.X); - yRadius = Math.abs(centerPoint.Y - lbPoint.Y); - List newPoints = new ArrayList<>(); - newPoints.add(new PointD(centerPoint.X - xRadius, centerPoint.Y - yRadius)); - newPoints.add(new PointD(centerPoint.X - xRadius, centerPoint.Y + yRadius)); - newPoints.add(new PointD(centerPoint.X + xRadius, centerPoint.Y + yRadius)); - newPoints.add(new PointD(centerPoint.X + xRadius, centerPoint.Y - yRadius)); - EllipseShape newES = new EllipseShape(); - newES.setPoints(newPoints); - - return newES; - } - - /** - * Project angle - * - * @param oAngle The angle - * @param fromP1 From point - * @param toP1 To point - * @param fromProj From projection - * @param toProj To projection - * @return Projected angle - */ - public double projectAngle(double oAngle, double[] fromP1, double[] toP1, ProjectionInfo fromProj, ProjectionInfo toProj) { - double pAngle = oAngle; - double[] fromP2; - double[] toP2; - double[][] points = new double[1][]; - - if (fromP1[1] == 90) { - fromP2 = new double[]{fromP1[0], fromP1[1] - 10}; - points[0] = (double[]) fromP2.clone(); - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - toP2 = points[0]; - double x, y; - x = toP2[0] - toP1[0]; - y = toP2[1] - toP1[1]; - double aLen = Math.sqrt(x * x + y * y); - double angle = Math.asin(x / aLen) * 180 / Math.PI; - if (x < 0 && y < 0) { - angle = 180.0 - angle; - } else if (x > 0 && y < 0) { - angle = 180.0 - angle; - } else if (x < 0 && y > 0) { - angle = 360.0 + angle; - } - if (aLen == 0) { - System.out.print("Error"); - } - pAngle = oAngle + (angle - 180); - if (pAngle > 360) { - pAngle = pAngle - 360; - } else if (pAngle < 0) { - pAngle = pAngle + 360; - } - } catch (Exception e) { - } - } else { - fromP2 = new double[]{fromP1[0] + 10, fromP1[1]}; - points[0] = (double[]) fromP2.clone(); - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - toP2 = points[0]; - - double x, y; - x = toP2[0] - toP1[0]; - y = toP2[1] - toP1[1]; - double aLen = Math.sqrt(x * x + y * y); - if (aLen == 0) { - return pAngle; - } - - double angle = Math.asin(x / aLen) * 180 / Math.PI; - if (Double.isNaN(angle)) { - return pAngle; - } - - if (x < 0 && y < 0) { - angle = 180.0 - angle; - } else if (x > 0 && y < 0) { - angle = 180.0 - angle; - } else if (x < 0 && y > 0) { - angle = 360.0 + angle; - } - - pAngle = oAngle + (angle - 90); - if (pAngle > 360) { - pAngle = pAngle - 360; - } else if (pAngle < 0) { - pAngle = pAngle + 360; - } - } catch (Exception e) { - } - } - - return pAngle; - } - - private GraphicCollection projectGraphics(GraphicCollection aGCollection, ProjectionInfo fromProj, ProjectionInfo toProj) { - GraphicCollection newGCollection = new GraphicCollection(); - for (Graphic aGraphic : aGCollection.getGraphics()) { - aGraphic.setShape(projectShape(aGraphic.getShape(), fromProj, toProj)); - if (aGraphic.getShape() != null) { - newGCollection.add(aGraphic); - } - } - - return newGCollection; - } - - private List projectGraphics(List graphics, ProjectionInfo fromProj, ProjectionInfo toProj) { - List newGraphics = new ArrayList<>(); - for (Graphic aGraphic : graphics) { - Shape aShape = projectShape(aGraphic.getShape(), fromProj, toProj); - if (aShape != null) { - newGraphics.add(new Graphic(aShape, aGraphic.getLegend())); - } - } - - return newGraphics; - } - - private Shape projectShape(Shape aShape, ProjectionInfo fromProj, ProjectionInfo toProj) { - Shape newShape; - switch (aShape.getShapeType()) { - case Point: - case PointM: - newShape = projectPointShape((PointShape) aShape, fromProj, toProj); - break; - case Polyline: - case PolylineM: - newShape = projectPolylineShape((PolylineShape) aShape, fromProj, toProj); - break; - case CurveLine: - newShape = projectCurvelineShape((CurveLineShape) aShape, fromProj, toProj); - break; - case Polygon: - case PolygonM: - case Rectangle: - newShape = projectPolygonShape((PolygonShape) aShape, fromProj, toProj); - break; - case CurvePolygon: - newShape = projectCurvePolygonShape((CurvePolygonShape) aShape, fromProj, toProj); - break; - case Circle: - newShape = projectCircleShape((CircleShape) aShape, fromProj, toProj); - break; - case Ellipse: - newShape = projectEllipseShape((EllipseShape) aShape, fromProj, toProj); - break; - default: - newShape = null; - break; - } - - return newShape; - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.map; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.global.event.IProjectionChangedListener; +import org.meteoinfo.global.event.ProjectionChangedEvent; +import org.meteoinfo.layer.RasterLayer; +import org.meteoinfo.layer.VectorLayer; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.info.ProjectionInfo; +import org.meteoinfo.projection.Reproject; +import org.meteoinfo.shape.CircleShape; +import org.meteoinfo.shape.CurveLineShape; +import org.meteoinfo.shape.CurvePolygonShape; +import org.meteoinfo.shape.EllipseShape; +import org.meteoinfo.shape.Graphic; +import org.meteoinfo.shape.GraphicCollection; +import org.meteoinfo.shape.PointShape; +import org.meteoinfo.shape.Polygon; +import org.meteoinfo.shape.PolygonShape; +import org.meteoinfo.shape.Polyline; +import org.meteoinfo.shape.PolylineShape; +import org.meteoinfo.shape.Shape; +import org.meteoinfo.shape.StationModelShape; +import org.meteoinfo.shape.WindArrow; +import org.meteoinfo.shape.WindBarb; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.swing.event.EventListenerList; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CRSFactory; + +/** + * + * @author Yaqiang Wang + */ +public class ProjectionSet { + // + + private final EventListenerList _listeners = new EventListenerList(); + CRSFactory _crsFactory = new CRSFactory(); + private ProjectionInfo _projInfo; + //private String _projStr; + //private double _refLon; + //private double _refCutLon; + // + // + + /** + * Constructor + */ + public ProjectionSet() { + _projInfo = KnownCoordinateSystems.geographic.world.WGS1984; + //_projStr = _projInfo.getParameterString(); + //_refLon = 0; + } + // + + // + public void addProjectionChangedListener(IProjectionChangedListener listener) { + this._listeners.add(IProjectionChangedListener.class, listener); + } + + public void removeViewExtentChangedListener(IProjectionChangedListener listener) { + this._listeners.remove(IProjectionChangedListener.class, listener); + } + + public void fireProjectionChangedEvent() { + fireProjectionChangedEvent(new ProjectionChangedEvent(this)); + } + + private void fireProjectionChangedEvent(ProjectionChangedEvent event) { + Object[] listeners = _listeners.getListenerList(); + for (int i = 0; i < listeners.length; i = i + 2) { + if (listeners[i] == IProjectionChangedListener.class) { + ((IProjectionChangedListener) listeners[i + 1]).projectionChangedEvent(event); + } + } + } + // + // + + /** + * Get if is Lon/Lat projection + * + * @return Boolean + */ + public boolean isLonLatMap() { + return "longlat".equals(_projInfo.getCoordinateReferenceSystem().getProjection().toString().toLowerCase()); + } + + /** + * Get projection info + * + * @return Projection Info + */ + public ProjectionInfo getProjInfo() { + return _projInfo; + } + + /** + * Set projection info + * + * @param projInfo The Projection info + */ + public void setProjInfo(ProjectionInfo projInfo) { + _projInfo = projInfo; + } + + /** + * Get Porj4 string + * + * @return Proj4 string + */ + public String getProjStr() { + return _projInfo.toProj4String(); + } + + /** + * Set proj4 string + * + * @param projStr Porj4 string + */ + public void setProjStr(String projStr) { + _projInfo = ProjectionInfo.factory(projStr); + } + +// /** +// * Get reference longitude +// * +// * @return Reference longitue +// */ +// public double getRefLon() { +// return _refLon; +// } +// +// /** +// * Set reference longitude +// * +// * @param lon Reference longitude +// */ +// public void setRefLon(double lon) { +// _refLon = lon; +// } + +// /** +// * Get reference cut longitude +// * +// * @return Reference cut longitude +// */ +// public double getRefCutLon() { +// return _refCutLon; +// } +// +// /** +// * Set reference cut longitude +// * +// * @param lon +// */ +// public void setRefCutLon(double lon) { +// _refCutLon = lon; +// } + // + // + + /** + * Get projected extent from lon/lat + * + * @param sExtent Lon/lat extent + * @return Projected extent + */ + public Extent getProjectedExtentFromLonLat(Extent sExtent) { + Extent aExtent = new Extent(); + ProjectionInfo fromProj = KnownCoordinateSystems.geographic.world.WGS1984; + ProjectionInfo toProj = _projInfo; + + //Get the border of longitude and latitude + double[][] points = new double[4][]; + points[0] = new double[]{sExtent.minX, sExtent.minY}; + points[1] = new double[]{sExtent.minX, sExtent.maxY}; + points[2] = new double[]{sExtent.maxX, sExtent.maxY}; + points[3] = new double[]{sExtent.maxX, sExtent.minY}; + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + + //Get lon lat extent + aExtent.minX = Math.min(points[0][0], points[1][0]); + aExtent.minY = Math.min(points[0][1], points[3][1]); + aExtent.maxX = Math.max(points[2][0], points[3][0]); + aExtent.maxY = Math.max(points[1][1], points[2][1]); + + return aExtent; + } + + /** + * Project layers + * + * @param aMapView The Map view + * @param toProj To projection info + */ + public void projectLayers(MapView aMapView, ProjectionInfo toProj) { + projectLayers(aMapView, toProj, true); + } + + /** + * Project layers + * + * @param aMapView The map view + * @param toProj To projection + * @param isUpdateView If repaint mapview + */ + public void projectLayers(MapView aMapView, ProjectionInfo toProj, boolean isUpdateView) { + if (aMapView.getProjection().getProjInfo().toProj4String().equals(toProj.toProj4String())) { + return; + } + + aMapView.setLockViewUpdate(true); + + ProjectionInfo fromProj = aMapView.getProjection().getProjInfo(); + + aMapView.getProjection().setProjInfo(toProj); + double refLon = toProj.getRefCutLon(); + //aMapView.getProjection().setRefCutLon(refLon); + + for (int i = 0; i < aMapView.getLayers().size(); i++) { + switch (aMapView.getLayers().get(i).getLayerType()) { + case VectorLayer: + VectorLayer oLayer = (VectorLayer) aMapView.getLayers().get(i); + //projectLayer(oLayer, toProj); + ProjectionUtil.projectLayer(oLayer, toProj); + break; + case RasterLayer: + RasterLayer oRLayer = (RasterLayer) aMapView.getLayers().get(i); + ProjectionUtil.projectLayer(oRLayer, toProj); + break; + } + } + + //Project graphics + if (aMapView.getGraphicCollection().size() > 0) { + GraphicCollection newGCollection = projectGraphics(aMapView.getGraphicCollection(), fromProj, toProj); + aMapView.setGraphicCollection(newGCollection); + } + + aMapView.setExtent(aMapView.getLayersWholeExtent()); + Extent aExten = aMapView.getExtent(); + aMapView.setLonLatLayer(aMapView.generateLonLatLayer()); + ProjectionUtil.projectLayer(aMapView.getLonLatLayer(), toProj); + //aMapView.setLonLatProjLayer(aMapView.getLonLatLayer()); + for (int i = 0; i < aMapView.getLonLatLayer().getShapeNum(); i++) { + PolylineShape aPLS = (PolylineShape) aMapView.getLonLatLayer().getShapes().get(i); + if (aPLS.getPolylines().size() == 2) { + PointD aP = aPLS.getPolylines().get(0).getPointList().get(aPLS.getPolylines().get(0).getPointList().size() - 1); + PointD bP = aPLS.getPolylines().get(1).getPointList().get(aPLS.getPolylines().get(1).getPointList().size() - 1); + boolean isJoin = false; + if (refLon == 0) { + if (Math.abs(aP.X) < 0.1 && Math.abs(bP.X) < 0.1 && MIMath.doubleEquals(aP.Y, bP.Y)) { + isJoin = true; + } + } else if (MIMath.doubleEquals(aP.X, bP.X) && MIMath.doubleEquals(aP.Y, bP.Y)) { + isJoin = true; + } + + if (isJoin) { + List polyLines = new ArrayList<>(); + Polyline aPL = new Polyline(); + List pList = (List) new ArrayList<>(aPLS.getPolylines().get(1).getPointList()); + List bPList = (List) new ArrayList<>(aPLS.getPolylines().get(0).getPointList()); + Collections.reverse(bPList); + pList.addAll(bPList); + aPL.setPointList(pList); + polyLines.add(aPL); + aPLS.setPolylines(polyLines); + //aMapView.getLonLatProjLayer().getShapes().get(i) = aPLS; + } + } + } + + if (isUpdateView) { + aMapView.setLockViewUpdate(false); + } + aMapView.zoomToExtent(aExten); + + this.fireProjectionChangedEvent(); + } + +// /** +// * Project raster layer +// * +// * @param oLayer The layer +// * @param toProj To projection +// */ +// public void projectLayer(RasterLayer oLayer, ProjectionInfo toProj) { +// try { +// // if (toProj.getProjectionName() == ProjectionNames.Robinson) { +//// return; +//// } +// +// if (oLayer.getProjInfo().toProj4String().equals(toProj.toProj4String())) { +// if (oLayer.isProjected()) { +// oLayer.getOriginData(); +// oLayer.updateGridData(); +// if (oLayer.getLegendScheme().getBreakNum() < 50) { +// oLayer.updateImage(); +// } else { +// oLayer.setPaletteByLegend(); +// } +// } +// return; +// } +// +// if (!oLayer.isProjected()) { +// oLayer.updateOriginData(); +// } else { +// oLayer.getOriginData(); +// } +// +// oLayer.setGridData(oLayer.getGridData().project(oLayer.getProjInfo(), toProj)); +// oLayer.updateImage(oLayer.getLegendScheme()); +//// if (oLayer.getLegendScheme().getBreakNum() < 50) { +//// oLayer.updateImage(oLayer.getLegendScheme()); +//// } else { +//// oLayer.setPaletteByLegend(); +//// } +// } catch (InvalidRangeException ex) { +// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); +// } +// } +// +// /** +// * Project vector layer +// * +// * @param oLayer The layer +// * @param toProj To projection info +// */ +// public void projectLayer(VectorLayer oLayer, ProjectionInfo toProj) { +// projectLayer(oLayer, toProj, true); +// } +// +// /** +// * Project vector layer +// * +// * @param oLayer The layer +// * @param toProj To projection info +// * @param projectLabels If project labels +// */ +// public void projectLayer(VectorLayer oLayer, ProjectionInfo toProj, boolean projectLabels) { +// ProjectionInfo fromProj = oLayer.getProjInfo(); +// if (fromProj.equals(toProj)) { +// if (oLayer.isProjected()) { +// oLayer.getOriginData(); +// } +// +// return; +// } +// +// if (oLayer.isProjected()) { +// oLayer.getOriginData(); +// } else { +// oLayer.updateOriginData(); +// } +// +// double refLon = toProj.getRefCutLon(); +// if (oLayer.getExtent().maxX > 180 && oLayer.getExtent().minX > refLon) { +// refLon += 360; +// } +// +// //coordinate transform process +// int i, s; +// ArrayList newPoints = new ArrayList(); +// Extent lExtent = new Extent(); +// +// DataTable aTable = new DataTable(); +// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { +// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); +// aTable.getColumns().add(bDC); +// } +// +// //aLayer.AttributeTable.Table.Rows.Clear(); +// switch (oLayer.getShapeType()) { +// case Point: +// case PointM: +// case PointZ: +// case WeatherSymbol: +// case WindArraw: +// case WindBarb: +// case StationModel: +// List shapePoints = new ArrayList<>(); +// newPoints.clear(); +// for (s = 0; s < oLayer.getShapeNum(); s++) { +// PointShape aPS = (PointShape) oLayer.getShapes().get(s); +// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { +// switch (toProj.getProjectionName()) { +// case Lambert_Conformal_Conic: +// if (aPS.getPoint().Y < -80) { +// continue; +// } +// break; +// case North_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().Y < 0) { +// continue; +// } +// break; +// case South_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().Y > 0) { +// continue; +// } +// break; +// case Mercator: +// if (aPS.getPoint().Y > 85.0511 || aPS.getPoint().Y < -85.0511) { +// continue; +// } +// break; +// } +// } +// aPS = projectPointShape(aPS, fromProj, toProj); +// if (aPS != null) { +// shapePoints.add(aPS); +// newPoints.add(aPS.getPoint()); +// +// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); +// try { +// aTable.addRow(aDR); +// } catch (Exception ex) { +// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); +// } +// } +// } +// oLayer.setShapes(new ArrayList<>(shapePoints)); +// oLayer.setExtent(MIMath.getPointsExtent(newPoints)); +// +// break; +// case Polyline: +// case PolylineM: +// case PolylineZ: +// List newPolylines = new ArrayList<>(); +// for (s = 0; s < oLayer.getShapeNum(); s++) { +// PolylineShape aPLS = (PolylineShape) oLayer.getShapes().get(s); +// List plsList = new ArrayList<>(); +// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { +// switch (toProj.getProjectionName()) { +// case Lambert_Conformal_Conic: +// if (aPLS.getExtent().minY < -80) { +// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, -80, true); +// } +// break; +// case North_Polar_Stereographic_Azimuthal: +// if (aPLS.getExtent().minY < 0) { +// //continue; +// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 0, true); +// } +// break; +// case South_Polar_Stereographic_Azimuthal: +// if (aPLS.getExtent().maxY > 0) { +// //continue; +// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 0, false); +// } +// break; +// case Mercator: +// if (aPLS.getExtent().maxY > 85.0511) { +// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, 85.0511, false); +// } +// if (aPLS.getExtent().minY < -85.0511) { +// aPLS = GeoComputation.clipPolylineShape_Lat(aPLS, -85.0511, true); +// } +// break; +// } +// if (aPLS == null) { +// continue; +// } +// +//// aPLS = GeoComputation.clipPolylineShape_Lon(aPLS, refLon); +//// if (aPLS == null) { +//// continue; +//// } +// if (aPLS.getExtent().minX < refLon && aPLS.getExtent().maxX > refLon) { +// plsList.add(GeoComputation.clipPolylineShape_Lon(aPLS, refLon)); +// } else { +// plsList.add(aPLS); +// } +// } else { +// plsList.add(aPLS); +// } +// for (i = 0; i < plsList.size(); i++) { +// aPLS = plsList.get(i); +// aPLS = projectPolylineShape(aPLS, fromProj, toProj); +// if (aPLS != null) { +// newPolylines.add(aPLS); +// +// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); +// try { +// aTable.addRow(aDR); +// } catch (Exception ex) { +// Logger.getLogger(ProjectionSet.class.getName()).log(Level.SEVERE, null, ex); +// } +// +// if (s == 0 && i == 0) { +// lExtent = (Extent) aPLS.getExtent().clone(); +// } else { +// lExtent = MIMath.getLagerExtent(lExtent, aPLS.getExtent()); +// } +// } +// } +// } +// oLayer.setShapes(new ArrayList<>(newPolylines)); +// newPolylines.clear(); +// oLayer.setExtent(lExtent); +// break; +// case Polygon: +// case PolygonM: +// List newPolygons = new ArrayList<>(); +// for (s = 0; s < oLayer.getShapeNum(); s++) { +// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); +// PolygonShape aPGS = (PolygonShape) oLayer.getShapes().get(s); +// List pgsList = new ArrayList<>(); +// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { +// switch (toProj.getProjectionName()) { +// case Lambert_Conformal_Conic: +// if (aPGS.getExtent().minY < -80) { +// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, -80, true); +// } +// break; +// case North_Polar_Stereographic_Azimuthal: +// if (aPGS.getExtent().minY < 0) { +// //continue; +// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 0, true); +// } +// break; +// case South_Polar_Stereographic_Azimuthal: +// if (aPGS.getExtent().maxY > 0) { +// //continue; +// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 0, false); +// } +// break; +// case Mercator: +// if (aPGS.getExtent().maxY > 85.0511) { +// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, 85.0511, false); +// } +// if (aPGS.getExtent().minY < -85.0511) { +// aPGS = GeoComputation.clipPolygonShape_Lat(aPGS, -85.0511, true); +// } +// break; +// } +// if (aPGS == null) { +// continue; +// } +// +// if (aPGS.getExtent().minX <= refLon && aPGS.getExtent().maxX >= refLon) { +// pgsList.add(GeoComputation.clipPolygonShape_Lon(aPGS, refLon)); +// } else { +// pgsList.add(aPGS); +// } +// } else { +// pgsList.add(aPGS); +// } +// for (i = 0; i < pgsList.size(); i++) { +// aPGS = pgsList.get(i); +// aPGS = projectPolygonShape(aPGS, fromProj, toProj); +// if (aPGS != null) { +// newPolygons.add(aPGS); +// +// aTable.getRows().add(aDR); +// +// if (s == 0) { +// lExtent = (Extent) aPGS.getExtent().clone(); +// } else { +// lExtent = MIMath.getLagerExtent(lExtent, aPGS.getExtent()); +// } +// } +// } +// } +// oLayer.setShapes(new ArrayList<>(newPolygons)); +// newPolygons.clear(); +// oLayer.setExtent(lExtent); +// break; +// } +// oLayer.getAttributeTable().setTable(aTable); +// +// if (oLayer.getLabelPoints().size() > 0) { +// if (projectLabels) { +// oLayer.setLabelPoints(projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); +// } else { +// oLayer.setLabelPoints(new ArrayList<>(oLayer.getLabelPoints())); +// } +// } +// } +// +// /** +// * Project layer angle +// * +// * @param oLayer The layer +// * @param fromProj From projection +// * @param toProj To projection +// * @return VectorLayer +// */ +// public VectorLayer projectLayerAngle(VectorLayer oLayer, ProjectionInfo fromProj, ProjectionInfo toProj) { +// //coordinate transform process +// ArrayList newPoints = new ArrayList(); +// +// VectorLayer aLayer = (VectorLayer) oLayer.clone(); +// +// //aLayer.AttributeTable.Table = oLayer.AttributeTable.Table.Clone(); +// DataTable aTable = new DataTable(); +// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { +// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); +// aTable.getColumns().add(bDC); +// } +// +// int s; +// List vectors = new ArrayList<>(); +// newPoints.clear(); +// for (s = 0; s < aLayer.getShapeNum(); s++) { +// PointShape aPS = (PointShape) aLayer.getShapes().get(s); +// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { +// switch (toProj.getProjectionName()) { +// case Lambert_Conformal_Conic: +// case North_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().X < -89) { +// continue; +// } +// break; +// case South_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().Y > 89) { +// continue; +// } +// break; +// } +// } +// double[] fromP = new double[]{aPS.getPoint().X, aPS.getPoint().Y}; +// double[] toP; +// double[][] points = new double[1][]; +// points[0] = (double[]) fromP.clone(); +// try { +// //Reproject point back to fromProj +// Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length); +// toP = points[0]; +// switch (aLayer.getLayerDrawType()) { +// case Vector: +// ((WindArrow) aPS).angle = projectAngle(((WindArrow) aPS).angle, toP, fromP, fromProj, toProj); +// break; +// case Barb: +// ((WindBarb) aPS).angle = projectAngle(((WindBarb) aPS).angle, toP, fromP, fromProj, toProj); +// break; +// case StationModel: +// ((StationModelShape) aPS).windBarb.angle = projectAngle(((StationModelShape) aPS).windBarb.angle, toP, fromP, fromProj, toProj); +// break; +// } +// newPoints.add(aPS.getPoint()); +// vectors.add(aPS); +// +// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); +// aTable.getRows().add(aDR); +// } catch (Exception e) { +// } +// } +// aLayer.setShapes(new ArrayList<>(vectors)); +// aLayer.setExtent(MIMath.getPointsExtent(newPoints)); +// aLayer.getAttributeTable().setTable(aTable); +// +// //if (aLayer.LabelSetV.DrawLabels) +// //{ +// // aLayer.AddLabels(); +// //} +// return aLayer; +// } + +// /** +// * Project wind layer +// * +// * @param oLayer Origin layer +// * @param toProj To projection +// * @param IfReprojectAngle If reproject wind angle +// */ +// public void projectWindLayer(VectorLayer oLayer, ProjectionInfo toProj, boolean IfReprojectAngle) { +// ProjectionInfo fromProj = oLayer.getProjInfo(); +// if (fromProj.toProj4String().equals(toProj.toProj4String())) { +// if (oLayer.isProjected()) { +// oLayer.getOriginData(); +// } +// +// return; +// } +// +// if (oLayer.isProjected()) { +// oLayer.getOriginData(); +// } else { +// oLayer.updateOriginData(); +// } +// +// //Set reference longitude +// double refLon = toProj.getRefCutLon(); +// if (oLayer.getExtent().maxX > 180 && oLayer.getExtent().minX > refLon) { +// refLon += 360; +// } +// +// //coordinate transform process +// int s; +// //PointD wPoint = new PointD(); +// PointD aPoint; +// List newPoints = new ArrayList<>(); +// //Extent lExtent = new Extent(); +// +// DataTable aTable = new DataTable(); +// for (DataColumn aDC : oLayer.getAttributeTable().getTable().getColumns()) { +// Field bDC = new Field(aDC.getColumnName(), aDC.getDataType()); +// aTable.getColumns().add(bDC); +// } +// +// List shapes = new ArrayList<>(); +// newPoints.clear(); +// for (s = 0; s < oLayer.getShapeNum(); s++) { +// PointShape aPS = (PointShape) oLayer.getShapes().get(s); +// if (fromProj.getProjectionName() == ProjectionNames.LongLat) { +// switch (toProj.getProjectionName()) { +// case Lambert_Conformal_Conic: +// case North_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().Y < -89) { +// continue; +// } +// break; +// case South_Polar_Stereographic_Azimuthal: +// if (aPS.getPoint().Y > 89) { +// continue; +// } +// break; +// } +// } +// double[] fromP = new double[]{aPS.getPoint().X, aPS.getPoint().Y}; +// double[] toP; +// double[][] points = new double[1][]; +// points[0] = (double[]) fromP.clone(); +// try { +// Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); +// toP = points[0]; +// aPoint = new PointD(); +// aPoint.X = (float) toP[0]; +// aPoint.Y = (float) toP[1]; +// aPS.setPoint(aPoint); +// if (IfReprojectAngle) { +// switch (oLayer.getLayerDrawType()) { +// case Vector: +// ((WindArrow) aPS).angle = projectAngle(((WindArrow) aPS).angle, fromP, toP, fromProj, toProj); +// break; +// case Barb: +// ((WindBarb) aPS).angle = projectAngle(((WindBarb) aPS).angle, fromP, toP, fromProj, toProj); +// break; +// case StationModel: +// ((StationModelShape) aPS).windBarb.angle = projectAngle(((StationModelShape) aPS).windBarb.angle, fromP, toP, fromProj, toProj); +// break; +// } +// } +// newPoints.add(aPoint); +// shapes.add(aPS); +// +// DataRow aDR = oLayer.getAttributeTable().getTable().getRows().get(s); +// aTable.getRows().add(aDR); +// } catch (Exception e) { +// } +// } +// oLayer.setShapes(new ArrayList<>(shapes)); +// oLayer.setExtent(MIMath.getPointsExtent(newPoints)); +// oLayer.getAttributeTable().setTable(aTable); +// +// if (oLayer.getLabelPoints().size() > 0) { +// oLayer.setLabelPoints(projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); +// } +// } + + private PointShape projectPointShape(PointShape aPS, ProjectionInfo fromProj, ProjectionInfo toProj) { + PointShape newPS = (PointShape) aPS.clone(); + double[][] points = new double[1][]; + points[0] = new double[]{newPS.getPoint().X, newPS.getPoint().Y}; + double[] fromP = new double[]{newPS.getPoint().X, newPS.getPoint().Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + double[] toP = points[0]; + newPS.setPoint(new PointD(points[0][0], points[0][1])); + switch (aPS.getShapeType()) { + case WindBarb: + ((WindBarb) newPS).angle = projectAngle(((WindBarb) newPS).angle, fromP, toP, fromProj, toProj); + break; + case WindArraw: + ((WindArrow) newPS).angle = projectAngle(((WindArrow) newPS).angle, fromP, toP, fromProj, toProj); + break; + case StationModel: + ((StationModelShape) newPS).windBarb.angle = projectAngle(((StationModelShape) newPS).windBarb.angle, fromP, toP, fromProj, toProj); + break; + } + return newPS; + } else { + return null; + } + } catch (Exception e) { + return null; + } + } + + private PolylineShape projectPolylineShape(PolylineShape aPLS, ProjectionInfo fromProj, ProjectionInfo toProj) { + List polyLines = new ArrayList<>(); + for (int i = 0; i < aPLS.getPolylines().size(); i++) { + List newPoints = new ArrayList<>(); + Polyline aPL = aPLS.getPolylines().get(i); + Polyline bPL; + double x; + for (int j = 0; j < aPL.getPointList().size(); j++) { + double[][] points = new double[1][]; + PointD wPoint = aPL.getPointList().get(j); + x = wPoint.X; + if (fromProj.isLonLat()) { + if (x > 180) { + x -= 360; + } else if (x < -180) { + x += 360; + } + } + points[0] = new double[]{x, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + //wPoint = new PointD(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + //break; + } + } + + if (newPoints.size() > 1) { + bPL = new Polyline(); + bPL.setPointList(newPoints); + polyLines.add(bPL); + } + } + + if (polyLines.size() > 0) { + aPLS.setPolylines(polyLines); + + return aPLS; + } else { + return null; + } + } + + private CurveLineShape projectCurvelineShape(CurveLineShape aPLS, ProjectionInfo fromProj, ProjectionInfo toProj) { + List polyLines = new ArrayList<>(); + for (int i = 0; i < aPLS.getPolylines().size(); i++) { + List newPoints = new ArrayList<>(); + Polyline aPL = aPLS.getPolylines().get(i); + Polyline bPL; + for (int j = 0; j < aPL.getPointList().size(); j++) { + double[][] points = new double[1][]; + PointD wPoint = aPL.getPointList().get(j); + points[0] = new double[]{wPoint.X, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + wPoint = new PointD(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + break; + } + } + + if (newPoints.size() > 1) { + bPL = new Polyline(); + bPL.setPointList(newPoints); + polyLines.add(bPL); + } + } + + if (polyLines.size() > 0) { + aPLS.setPolylines(polyLines); + + return aPLS; + } else { + return null; + } + } + + /** + * Project polygon shape + * + * @param aPGS A polygon shape + * @param fromProj From projection + * @param toProj To porjection + * @return Projected polygon shape + */ + public PolygonShape projectPolygonShape(PolygonShape aPGS, ProjectionInfo fromProj, ProjectionInfo toProj) { + List polygons = new ArrayList<>(); + for (int i = 0; i < aPGS.getPolygons().size(); i++) { + Polygon aPG = aPGS.getPolygons().get(i); + Polygon bPG = null; + for (int r = 0; r < aPG.getRingNumber(); r++) { + List pList = (List)aPG.getRings().get(r); + List newPoints = new ArrayList<>(); + for (int j = 0; j < pList.size(); j++) { + double[][] points = new double[1][]; + PointD wPoint = pList.get(j); + points[0] = new double[]{wPoint.X, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + wPoint = new PointD(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + break; + } + } + + if (r == 0) { + if (newPoints.size() > 2) { + bPG = new Polygon(); + bPG.setOutLine(newPoints); + } else { + break; + } + } else if (newPoints.size() > 2) { + if (bPG != null) + bPG.addHole(newPoints); + } + } + + if (bPG != null) { + polygons.add(bPG); + } + } + + if (polygons.size() > 0) { + aPGS.setPolygons(polygons); + + return aPGS; + } else { + return null; + } + } + + private CurvePolygonShape projectCurvePolygonShape(CurvePolygonShape aPGS, ProjectionInfo fromProj, ProjectionInfo toProj) { + List polygons = new ArrayList<>(); + for (int i = 0; i < aPGS.getPolygons().size(); i++) { + Polygon aPG = aPGS.getPolygons().get(i); + Polygon bPG = null; + for (int r = 0; r < aPG.getRingNumber(); r++) { + List pList = (List)aPG.getRings().get(r); + List newPoints = new ArrayList<>(); + for (int j = 0; j < pList.size(); j++) { + double[][] points = new double[1][]; + PointD wPoint = pList.get(j); + points[0] = new double[]{wPoint.X, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + wPoint = new PointD(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + break; + } + } + + if (r == 0) { + if (newPoints.size() > 2) { + bPG = new Polygon(); + bPG.setOutLine(newPoints); + } else { + break; + } + } else if (newPoints.size() > 2) { + if (bPG != null) + bPG.addHole(newPoints); + } + } + + if (bPG != null) { + polygons.add(bPG); + } + } + + if (polygons.size() > 0) { + aPGS.setPolygons(polygons); + + return aPGS; + } else { + return null; + } + } + + private CircleShape projectCircleShape(CircleShape aCS, ProjectionInfo fromProj, ProjectionInfo toProj) { + double radius = Math.abs(aCS.getPoints().get(1).X - aCS.getPoints().get(0).X); + double[][] points = new double[1][]; + PointD centerPoint = new PointD(aCS.getPoints().get(0).X + radius, aCS.getPoints().get(0).Y); + points[0] = new double[]{centerPoint.X, centerPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + centerPoint.X = points[0][0]; + centerPoint.Y = points[0][1]; + } else { + return null; + } + } catch (Exception e) { + return null; + } + + points = new double[1][]; + PointD leftPoint = aCS.getPoints().get(0); + points[0] = new double[]{leftPoint.X, leftPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + leftPoint.X = points[0][0]; + leftPoint.Y = points[0][1]; + } else { + return null; + } + } catch (Exception e) { + return null; + } + + radius = Math.abs(centerPoint.X - leftPoint.X); + List newPoints = new ArrayList<>(); + newPoints.add(new PointD(centerPoint.X - radius, centerPoint.Y)); + newPoints.add(new PointD(centerPoint.X, centerPoint.Y - radius)); + newPoints.add(new PointD(centerPoint.X + radius, centerPoint.Y)); + newPoints.add(new PointD(centerPoint.X, centerPoint.Y + radius)); + CircleShape newCS = new CircleShape(); + newCS.setPoints(newPoints); + + return newCS; + } + + private EllipseShape projectEllipseShape(EllipseShape aES, ProjectionInfo fromProj, ProjectionInfo toProj) { + double xRadius = Math.abs(aES.getPoints().get(2).X - aES.getPoints().get(0).X) / 2; + double yRadius = Math.abs(aES.getPoints().get(2).Y - aES.getPoints().get(0).Y) / 2; + double[][] points = new double[1][]; + PointD centerPoint = new PointD(aES.getExtent().minX + xRadius, aES.getExtent().minY + yRadius); + points[0] = new double[]{centerPoint.X, centerPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + centerPoint.X = points[0][0]; + centerPoint.Y = points[0][1]; + } else { + return null; + } + } catch (Exception e) { + return null; + } + + points = new double[1][]; + PointD lbPoint = new PointD(aES.getExtent().minX, aES.getExtent().minY); + points[0] = new double[]{lbPoint.X, lbPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + lbPoint.X = points[0][0]; + lbPoint.Y = points[0][1]; + } else { + return null; + } + } catch (Exception e) { + return null; + } + + xRadius = Math.abs(centerPoint.X - lbPoint.X); + yRadius = Math.abs(centerPoint.Y - lbPoint.Y); + List newPoints = new ArrayList<>(); + newPoints.add(new PointD(centerPoint.X - xRadius, centerPoint.Y - yRadius)); + newPoints.add(new PointD(centerPoint.X - xRadius, centerPoint.Y + yRadius)); + newPoints.add(new PointD(centerPoint.X + xRadius, centerPoint.Y + yRadius)); + newPoints.add(new PointD(centerPoint.X + xRadius, centerPoint.Y - yRadius)); + EllipseShape newES = new EllipseShape(); + newES.setPoints(newPoints); + + return newES; + } + + /** + * Project angle + * + * @param oAngle The angle + * @param fromP1 From point + * @param toP1 To point + * @param fromProj From projection + * @param toProj To projection + * @return Projected angle + */ + public double projectAngle(double oAngle, double[] fromP1, double[] toP1, ProjectionInfo fromProj, ProjectionInfo toProj) { + double pAngle = oAngle; + double[] fromP2; + double[] toP2; + double[][] points = new double[1][]; + + if (fromP1[1] == 90) { + fromP2 = new double[]{fromP1[0], fromP1[1] - 10}; + points[0] = (double[]) fromP2.clone(); + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + toP2 = points[0]; + double x, y; + x = toP2[0] - toP1[0]; + y = toP2[1] - toP1[1]; + double aLen = Math.sqrt(x * x + y * y); + double angle = Math.asin(x / aLen) * 180 / Math.PI; + if (x < 0 && y < 0) { + angle = 180.0 - angle; + } else if (x > 0 && y < 0) { + angle = 180.0 - angle; + } else if (x < 0 && y > 0) { + angle = 360.0 + angle; + } + if (aLen == 0) { + System.out.print("Error"); + } + pAngle = oAngle + (angle - 180); + if (pAngle > 360) { + pAngle = pAngle - 360; + } else if (pAngle < 0) { + pAngle = pAngle + 360; + } + } catch (Exception e) { + } + } else { + fromP2 = new double[]{fromP1[0] + 10, fromP1[1]}; + points[0] = (double[]) fromP2.clone(); + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + toP2 = points[0]; + + double x, y; + x = toP2[0] - toP1[0]; + y = toP2[1] - toP1[1]; + double aLen = Math.sqrt(x * x + y * y); + if (aLen == 0) { + return pAngle; + } + + double angle = Math.asin(x / aLen) * 180 / Math.PI; + if (Double.isNaN(angle)) { + return pAngle; + } + + if (x < 0 && y < 0) { + angle = 180.0 - angle; + } else if (x > 0 && y < 0) { + angle = 180.0 - angle; + } else if (x < 0 && y > 0) { + angle = 360.0 + angle; + } + + pAngle = oAngle + (angle - 90); + if (pAngle > 360) { + pAngle = pAngle - 360; + } else if (pAngle < 0) { + pAngle = pAngle + 360; + } + } catch (Exception e) { + } + } + + return pAngle; + } + + private GraphicCollection projectGraphics(GraphicCollection aGCollection, ProjectionInfo fromProj, ProjectionInfo toProj) { + GraphicCollection newGCollection = new GraphicCollection(); + for (Graphic aGraphic : aGCollection.getGraphics()) { + aGraphic.setShape(projectShape(aGraphic.getShape(), fromProj, toProj)); + if (aGraphic.getShape() != null) { + newGCollection.add(aGraphic); + } + } + + return newGCollection; + } + + private List projectGraphics(List graphics, ProjectionInfo fromProj, ProjectionInfo toProj) { + List newGraphics = new ArrayList<>(); + for (Graphic aGraphic : graphics) { + Shape aShape = projectShape(aGraphic.getShape(), fromProj, toProj); + if (aShape != null) { + newGraphics.add(new Graphic(aShape, aGraphic.getLegend())); + } + } + + return newGraphics; + } + + private Shape projectShape(Shape aShape, ProjectionInfo fromProj, ProjectionInfo toProj) { + Shape newShape; + switch (aShape.getShapeType()) { + case Point: + case PointM: + newShape = projectPointShape((PointShape) aShape, fromProj, toProj); + break; + case Polyline: + case PolylineM: + newShape = projectPolylineShape((PolylineShape) aShape, fromProj, toProj); + break; + case CurveLine: + newShape = projectCurvelineShape((CurveLineShape) aShape, fromProj, toProj); + break; + case Polygon: + case PolygonM: + case Rectangle: + newShape = projectPolygonShape((PolygonShape) aShape, fromProj, toProj); + break; + case CurvePolygon: + newShape = projectCurvePolygonShape((CurvePolygonShape) aShape, fromProj, toProj); + break; + case Circle: + newShape = projectCircleShape((CircleShape) aShape, fromProj, toProj); + break; + case Ellipse: + newShape = projectEllipseShape((EllipseShape) aShape, fromProj, toProj); + break; + default: + newShape = null; + break; + } + + return newShape; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/fitting/FittingUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/math/fitting/FittingUtil.java index aa24f905..7b81325d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/fitting/FittingUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/math/fitting/FittingUtil.java @@ -7,6 +7,7 @@ package org.meteoinfo.math.fitting; import java.util.ArrayList; import java.util.List; + import org.meteoinfo.math.ArrayMath; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/interpolate/InterpUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/math/interpolate/InterpUtil.java index 52e38ddd..801b7254 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/interpolate/InterpUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/math/interpolate/InterpUtil.java @@ -11,8 +11,8 @@ import org.apache.commons.math3.analysis.BivariateFunction; import org.apache.commons.math3.analysis.UnivariateFunction; import org.apache.commons.math3.analysis.interpolation.*; import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction; +import org.meteoinfo.common.PointD; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.PointD; import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.math.spatial.KDTree; import org.meteoinfo.ndarray.Array; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/linalg/LinalgUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/math/linalg/LinalgUtil.java index 29b4e477..91731734 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/linalg/LinalgUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/math/linalg/LinalgUtil.java @@ -1,541 +1,541 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.math.linalg; - -import java.util.List; -import org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder; -import org.apache.commons.math3.fitting.leastsquares.LeastSquaresOptimizer; -import org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem; -import org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer; -import org.apache.commons.math3.fitting.leastsquares.MultivariateJacobianFunction; -import org.apache.commons.math3.linear.Array2DRowRealMatrix; -import org.apache.commons.math3.linear.ArrayRealVector; -import org.apache.commons.math3.linear.CholeskyDecomposition; -import org.apache.commons.math3.linear.DecompositionSolver; -import org.apache.commons.math3.linear.EigenDecomposition; -import org.apache.commons.math3.linear.LUDecomposition; -import org.apache.commons.math3.linear.MatrixUtils; -import org.apache.commons.math3.linear.QRDecomposition; -import org.apache.commons.math3.linear.RealMatrix; -import org.apache.commons.math3.linear.RealVector; -import org.apache.commons.math3.linear.SingularValueDecomposition; -import org.apache.commons.math3.util.Pair; -import org.ejml.data.Complex_F64; -import org.ejml.simple.SimpleBase; -import org.ejml.simple.SimpleEVD; -import org.ejml.simple.SimpleMatrix; -import org.ejml.simple.SimpleSVD; -import org.meteoinfo.bak.ArrayUtil; -import org.meteoinfo.ndarray.Complex; -import org.meteoinfo.ndarray.Array; -import org.meteoinfo.ndarray.DataType; - -/** - * - * @author Yaqiang Wang - */ -public class LinalgUtil { - - /** - * Solve a linear matrix equation, or system of linear scalar equations. - * - * @param a Coefficient matrix. - * @param b Ordinate or “dependent variable” values. - * @return Solution to the system a x = b. Returned shape is identical to b. - */ - public static Array solve(Array a, Array b) { - Array r = Array.factory(DataType.DOUBLE, b.getShape()); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix coefficients = new Array2DRowRealMatrix(aa, false); - DecompositionSolver solver = new LUDecomposition(coefficients).getSolver(); - double[] bb = (double[]) ArrayUtil.copyToNDJavaArray_Double(b); - RealVector constants = new ArrayRealVector(bb, false); - RealVector solution = solver.solve(constants); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, solution.getEntry(i)); - } - - return r; - } - - /** - * Calculates the Cholesky decomposition of a matrix. The Cholesky - * decomposition of a real symmetric positive-definite matrix A consists of - * a lower triangular matrix L with same size such that: A = LLT. In a - * sense, this is the square root of A. - * - * @param a The given matrix. - * @return Result array. - */ - public static Array cholesky(Array a) { - Array r = Array.factory(DataType.DOUBLE, a.getShape()); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - CholeskyDecomposition decomposition = new CholeskyDecomposition(matrix); - RealMatrix L = decomposition.getL(); - int n = L.getColumnDimension(); - int m = L.getRowDimension(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - r.setDouble(i * n + j, L.getEntry(i, j)); - } - } - - return r; - } - - /** - * Calculates the LUP-decomposition of a square matrix. The - * LUP-decomposition of a matrix A consists of three matrices L, U and P - * that satisfy: P×A = L×U. L is lower triangular (with unit diagonal - * terms), U is upper triangular and P is a permutation matrix. All matrices - * are m×m. - * - * @param a Given matrix. - * @return Result P/L/U arrays. - */ - public static Array[] lu(Array a) { - Array Pa = Array.factory(DataType.DOUBLE, a.getShape()); - Array La = Array.factory(DataType.DOUBLE, a.getShape()); - Array Ua = Array.factory(DataType.DOUBLE, a.getShape()); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - LUDecomposition decomposition = new LUDecomposition(matrix); - RealMatrix P = decomposition.getP(); - RealMatrix L = decomposition.getL(); - RealMatrix U = decomposition.getU(); - int n = L.getColumnDimension(); - int m = L.getRowDimension(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - Pa.setDouble(i * n + j, P.getEntry(i, j)); - La.setDouble(i * n + j, L.getEntry(i, j)); - Ua.setDouble(i * n + j, U.getEntry(i, j)); - } - } - - return new Array[]{Pa, La, Ua}; - } - - /** - * Calculates the QR-decomposition of a matrix. The QR-decomposition of a - * matrix A consists of two matrices Q and R that satisfy: A = QR, Q is - * orthogonal (QTQ = I), and R is upper triangular. If A is m×n, Q is m×m - * and R m×n. - * - * @param a Given matrix. - * @return Result Q/R arrays. - */ - public static Array[] qr(Array a) { - int m = a.getShape()[0]; - int n = a.getShape()[1]; - Array Qa = Array.factory(DataType.DOUBLE, new int[]{m, m}); - Array Ra = Array.factory(DataType.DOUBLE, a.getShape()); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - QRDecomposition decomposition = new QRDecomposition(matrix); - RealMatrix Q = decomposition.getQ(); - RealMatrix R = decomposition.getR(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < m; j++) { - Qa.setDouble(i * m + j, Q.getEntry(i, j)); - } - } - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - Ra.setDouble(i * n + j, R.getEntry(i, j)); - } - } - - return new Array[]{Qa, Ra}; - } - - /** - * Calculates the compact Singular Value Decomposition of a matrix. The - * Singular Value Decomposition of matrix A is a set of three matrices: U, Σ - * and V such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × - * p orthogonal matrix, Σ is a p × p diagonal matrix with positive or null - * elements, V is a p × n orthogonal matrix (hence VT is also orthogonal) - * where p=min(m,n). - * - * @param a Given matrix. - * @return Result U/S/V arrays. - */ - public static Array[] svd(Array a) { - int m = a.getShape()[0]; - int n = a.getShape()[1]; - int k = Math.min(m, n); - Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, k}); - Array Va = Array.factory(DataType.DOUBLE, new int[]{k, n}); - Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - SingularValueDecomposition decomposition = new SingularValueDecomposition(matrix); - RealMatrix U = decomposition.getU(); - RealMatrix V = decomposition.getVT(); - double[] sv = decomposition.getSingularValues(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < k; j++) { - Ua.setDouble(i * k + j, U.getEntry(i, j)); - } - } - for (int i = 0; i < k; i++) { - for (int j = 0; j < n; j++) { - Va.setDouble(i * n + j, V.getEntry(i, j)); - } - } - for (int i = 0; i < k; i++) { - Sa.setDouble(i, sv[i]); - } - - return new Array[]{Ua, Sa, Va}; - } - -// /** -// * Calculates the compact Singular Value Decomposition of a matrix. -// * The Singular Value Decomposition of matrix A is a set of three matrices: U, Σ and V -// * such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × p orthogonal -// * matrix, Σ is a p × p diagonal matrix with positive or null elements, V is a p × n -// * orthogonal matrix (hence VT is also orthogonal) where p=min(m,n). -// * @param a Given matrix. -// * @return Result U/S/V arrays. -// */ -// public static Array[] svd_JAMA(Array a){ -// int m = a.getShape()[0]; -// int n = a.getShape()[1]; -// int k = Math.min(m, n); -// double[][] aa = (double[][])ArrayUtil.copyToNDJavaArray_Double(a); -// Matrix M = new Matrix(aa); -// Jama.SingularValueDecomposition svd = M.svd(); -// Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, k}); -// Array Va = Array.factory(DataType.DOUBLE, new int[]{n, n}); -// Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); -// Matrix U = svd.getU(); -// Matrix V = svd.getV(); -// double[] sv = svd.getSingularValues(); -// for (int i = 0; i < m; i++){ -// for (int j = 0; j < k; j++){ -// Ua.setDouble(i * k + j, U.get(i, j)); -// } -// } -// for (int i = 0; i < n; i++){ -// for (int j = 0; j < n; j++){ -// Va.setDouble(i * n + j, V.get(i, j)); -// } -// } -// for (int i = 0; i < k; i++){ -// Sa.setDouble(i, sv[i]); -// } -// -// return new Array[]{Ua, Sa, Va}; -// } - /** - * Calculates the compact Singular Value Decomposition of a matrix. The - * Singular Value Decomposition of matrix A is a set of three matrices: U, Σ - * and V such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × - * p orthogonal matrix, Σ is a p × p diagonal matrix with positive or null - * elements, V is a p × n orthogonal matrix (hence VT is also orthogonal) - * where p=min(m,n). - * - * @param a Given matrix. - * @return Result U/S/V arrays. - */ - public static Array[] svd_EJML(Array a) { - int m = a.getShape()[0]; - int n = a.getShape()[1]; - int k = Math.min(m, n); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - SimpleMatrix M = new SimpleMatrix(aa); - SimpleSVD svd = M.svd(false); - Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, m}); - Array Va = Array.factory(DataType.DOUBLE, new int[]{n, n}); - Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); - SimpleBase U = svd.getU(); - SimpleBase V = svd.getV(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < m; j++) { - Ua.setDouble(i * m + j, U.get(i, j)); - } - } - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - Va.setDouble(j * n + i, V.get(i, j)); - } - } - for (int i = 0; i < k; i++) { - //Sa.setDouble(i, sv[i]); - Sa.setDouble(i, svd.getSingleValue(i)); - } - - return new Array[]{Ua, Sa, Va}; - } - - /** - * Calculates the eigen decomposition of a real matrix. The eigen - * decomposition of matrix A is a set of two matrices: V and D such that A = - * V × D × VT. A, V and D are all m × m matrices. - * - * @param a Given matrix. - * @return Result W/V arrays. - */ - public static Array[] eigen_bak(Array a) { - int m = a.getShape()[0]; - Array Wa; - Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - EigenDecomposition decomposition = new EigenDecomposition(matrix); - if (decomposition.hasComplexEigenvalues()) { - Wa = Array.factory(DataType.OBJECT, new int[]{m}); - double[] rev = decomposition.getRealEigenvalues(); - double[] iev = decomposition.getImagEigenvalues(); - for (int i = 0; i < m; i++) { - Wa.setObject(i, new Complex(rev[i], iev[i])); - RealVector v = decomposition.getEigenvector(i); - for (int j = 0; j < v.getDimension(); j++) { - Va.setDouble(j * m + i, v.getEntry(j)); - } - } - } else { - RealMatrix V = decomposition.getV(); - RealMatrix D = decomposition.getD(); - Wa = Array.factory(DataType.DOUBLE, new int[]{m}); - for (int i = 0; i < m; i++) { - for (int j = 0; j < m; j++) { - Va.setDouble(i * m + (m - j - 1), V.getEntry(i, j)); - if (i == j) { - Wa.setDouble(m - i - 1, D.getEntry(i, j)); - } - } - } - } - - return new Array[]{Wa, Va}; - } - - /** - * Calculates the eigen decomposition of a real matrix. The eigen - * decomposition of matrix A is a set of two matrices: V and D such that A = - * V × D × VT. A, V and D are all m × m matrices. - * - * @param a Given matrix. - * @return Result W/V arrays. - */ - public static Array[] eigen(Array a) { - int m = a.getShape()[0]; - Array Wa; - Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - EigenDecomposition decomposition = new EigenDecomposition(matrix); - double[] rev = decomposition.getRealEigenvalues(); - double[] iev = decomposition.getImagEigenvalues(); - if (decomposition.hasComplexEigenvalues()) { - Wa = Array.factory(DataType.OBJECT, new int[]{m}); - for (int i = 0; i < m; i++) { - Wa.setObject(i, new Complex(rev[i], iev[i])); - RealVector v = decomposition.getEigenvector(i); - for (int j = 0; j < v.getDimension(); j++) { - Va.setDouble(j * m + i, v.getEntry(j)); - } - } - } else { - Wa = Array.factory(DataType.DOUBLE, new int[]{m}); - for (int i = 0; i < m; i++) { - Wa.setDouble(i, rev[m - i - 1]); - RealVector v = decomposition.getEigenvector(m - i - 1); - for (int j = 0; j < v.getDimension(); j++) { - Va.setDouble(j * m + i, v.getEntry(j)); - } - } - } - - return new Array[]{Wa, Va}; - } - - /** - * Calculates the eigen decomposition of a real matrix. The eigen - * decomposition of matrix A is a set of two matrices: V and D such that A = - * V × D × VT. A, V and D are all m × m matrices. - * - * @param a Given matrix. - * @return Result W/V arrays. - */ - public static Array[] eigen_EJML(Array a) { - int m = a.getShape()[0]; - Array Wa; - Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - SimpleMatrix M = new SimpleMatrix(aa); - SimpleEVD evd = M.eig(); - List evs = evd.getEigenvalues(); - boolean isComplex = evd.getEigenVector(0) == null; - if (isComplex) { - Wa = Array.factory(DataType.OBJECT, new int[]{m}); - } else { - Wa = Array.factory(DataType.DOUBLE, new int[]{m}); - } - for (int i = 0; i < m; i++) { - if (isComplex) { - Wa.setObject(i, new Complex(evs.get(i).real, evs.get(i).imaginary)); - } else { - Wa.setDouble(i, evs.get(m - i - 1).real); - SimpleBase v = evd.getEigenVector(m - i - 1); - for (int j = 0; j < v.getNumElements(); j++) { - Va.setDouble(j * m + i, v.get(j)); - } - } - } - - return new Array[]{Wa, Va}; - } - - /** - * Calculate inverse matrix - * - * @param a The matrix - * @return Inverse matrix array - */ - public static Array inv(Array a) { - double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - RealMatrix matrix = new Array2DRowRealMatrix(aa, false); - RealMatrix invm = MatrixUtils.inverse(matrix); - if (invm == null) { - return null; - } - - int m = invm.getRowDimension(); - int n = invm.getColumnDimension(); - Array r = Array.factory(DataType.DOUBLE, new int[]{m, n}); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - r.setDouble(i * n + j, invm.getEntry(i, j)); - } - } - - return r; - } - - /** - * Not correct at present !!! - * - * @param a - * @param b - * @return - */ - public static Array lstsq(Array a, Array b) { - final double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); - final double[] bb = (double[]) ArrayUtil.copyToNDJavaArray_Double(b); - - // the model function - MultivariateJacobianFunction function = new MultivariateJacobianFunction() { - @Override - public Pair value(final RealVector point) { - RealVector value = new ArrayRealVector(bb.length); - RealMatrix jacobian = new Array2DRowRealMatrix(aa, false); - for (int i = 0; i < bb.length; ++i) { - - } - return new Pair<>(value, jacobian); - - } - }; - - // least squares problem to solve - LeastSquaresProblem problem = new LeastSquaresBuilder(). - //start(new double[]{100.0, 50.0}). - model(function). - target(bb). - lazyEvaluation(false). - maxEvaluations(1000). - maxIterations(1000). - build(); - LeastSquaresOptimizer.Optimum optimum = new LevenbergMarquardtOptimizer().optimize(problem); - - RealVector r = optimum.getPoint(); - int n = r.getDimension(); - Array x = Array.factory(DataType.DOUBLE, new int[]{n}); - for (int i = 0; i < n; i++) { - x.setDouble(i, r.getEntry(i)); - } - - return x; - } - - // Function to get cofactor of - // mat[p][q] in temp[][]. n is - // current dimension of mat[][] - public static void getCofactor(double mat[][], - double temp[][], int p, int q, int n) { - int i = 0, j = 0; - - // Looping for each element of - // the matrix - for (int row = 0; row < n; row++) { - for (int col = 0; col < n; col++) { - - // Copying into temporary matrix - // only those element which are - // not in given row and column - if (row != p && col != q) { - temp[i][j++] = mat[row][col]; - - // Row is filled, so increase - // row index and reset col - //index - if (j == n - 1) { - j = 0; - i++; - } - } - } - } - } - - /* Recursive function for finding determinant - of matrix. n is current dimension of mat[][]. */ - public static double determinantOfMatrix(double mat[][], int n, int N) { - int D = 0; // Initialize result - - // Base case : if matrix contains single - // element - if (n == 1) { - return mat[0][0]; - } - - // To store cofactors - double temp[][] = new double[N][N]; - - // To store sign multiplier - int sign = 1; - - // Iterate for each element of first row - for (int f = 0; f < n; f++) { - // Getting Cofactor of mat[0][f] - getCofactor(mat, temp, 0, f, n); - D += sign * mat[0][f] - * determinantOfMatrix(temp, n - 1, N); - - // terms are to be added with - // alternate sign - sign = -sign; - } - - return D; - } - - /** - * Calculate determinant of a matrix array - * - * @param mat Input array - * @return Determinant - */ - public static double determinantOfMatrix(Array mat) { - int n = mat.getShape()[0]; - double[][] a = (double[][]) ArrayUtil.copyToNDJavaArray_Double(mat); - return determinantOfMatrix(a, n, n); - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.math.linalg; + +import java.util.List; +import org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder; +import org.apache.commons.math3.fitting.leastsquares.LeastSquaresOptimizer; +import org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem; +import org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer; +import org.apache.commons.math3.fitting.leastsquares.MultivariateJacobianFunction; +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.ArrayRealVector; +import org.apache.commons.math3.linear.CholeskyDecomposition; +import org.apache.commons.math3.linear.DecompositionSolver; +import org.apache.commons.math3.linear.EigenDecomposition; +import org.apache.commons.math3.linear.LUDecomposition; +import org.apache.commons.math3.linear.MatrixUtils; +import org.apache.commons.math3.linear.QRDecomposition; +import org.apache.commons.math3.linear.RealMatrix; +import org.apache.commons.math3.linear.RealVector; +import org.apache.commons.math3.linear.SingularValueDecomposition; +import org.apache.commons.math3.util.Pair; +import org.ejml.data.Complex_F64; +import org.ejml.simple.SimpleBase; +import org.ejml.simple.SimpleEVD; +import org.ejml.simple.SimpleMatrix; +import org.ejml.simple.SimpleSVD; +import org.meteoinfo.math.ArrayUtil; +import org.meteoinfo.ndarray.Complex; +import org.meteoinfo.ndarray.Array; +import org.meteoinfo.ndarray.DataType; + +/** + * + * @author Yaqiang Wang + */ +public class LinalgUtil { + + /** + * Solve a linear matrix equation, or system of linear scalar equations. + * + * @param a Coefficient matrix. + * @param b Ordinate or “dependent variable” values. + * @return Solution to the system a x = b. Returned shape is identical to b. + */ + public static Array solve(Array a, Array b) { + Array r = Array.factory(DataType.DOUBLE, b.getShape()); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix coefficients = new Array2DRowRealMatrix(aa, false); + DecompositionSolver solver = new LUDecomposition(coefficients).getSolver(); + double[] bb = (double[]) ArrayUtil.copyToNDJavaArray_Double(b); + RealVector constants = new ArrayRealVector(bb, false); + RealVector solution = solver.solve(constants); + for (int i = 0; i < r.getSize(); i++) { + r.setDouble(i, solution.getEntry(i)); + } + + return r; + } + + /** + * Calculates the Cholesky decomposition of a matrix. The Cholesky + * decomposition of a real symmetric positive-definite matrix A consists of + * a lower triangular matrix L with same size such that: A = LLT. In a + * sense, this is the square root of A. + * + * @param a The given matrix. + * @return Result array. + */ + public static Array cholesky(Array a) { + Array r = Array.factory(DataType.DOUBLE, a.getShape()); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + CholeskyDecomposition decomposition = new CholeskyDecomposition(matrix); + RealMatrix L = decomposition.getL(); + int n = L.getColumnDimension(); + int m = L.getRowDimension(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + r.setDouble(i * n + j, L.getEntry(i, j)); + } + } + + return r; + } + + /** + * Calculates the LUP-decomposition of a square matrix. The + * LUP-decomposition of a matrix A consists of three matrices L, U and P + * that satisfy: P×A = L×U. L is lower triangular (with unit diagonal + * terms), U is upper triangular and P is a permutation matrix. All matrices + * are m×m. + * + * @param a Given matrix. + * @return Result P/L/U arrays. + */ + public static Array[] lu(Array a) { + Array Pa = Array.factory(DataType.DOUBLE, a.getShape()); + Array La = Array.factory(DataType.DOUBLE, a.getShape()); + Array Ua = Array.factory(DataType.DOUBLE, a.getShape()); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + LUDecomposition decomposition = new LUDecomposition(matrix); + RealMatrix P = decomposition.getP(); + RealMatrix L = decomposition.getL(); + RealMatrix U = decomposition.getU(); + int n = L.getColumnDimension(); + int m = L.getRowDimension(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + Pa.setDouble(i * n + j, P.getEntry(i, j)); + La.setDouble(i * n + j, L.getEntry(i, j)); + Ua.setDouble(i * n + j, U.getEntry(i, j)); + } + } + + return new Array[]{Pa, La, Ua}; + } + + /** + * Calculates the QR-decomposition of a matrix. The QR-decomposition of a + * matrix A consists of two matrices Q and R that satisfy: A = QR, Q is + * orthogonal (QTQ = I), and R is upper triangular. If A is m×n, Q is m×m + * and R m×n. + * + * @param a Given matrix. + * @return Result Q/R arrays. + */ + public static Array[] qr(Array a) { + int m = a.getShape()[0]; + int n = a.getShape()[1]; + Array Qa = Array.factory(DataType.DOUBLE, new int[]{m, m}); + Array Ra = Array.factory(DataType.DOUBLE, a.getShape()); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + QRDecomposition decomposition = new QRDecomposition(matrix); + RealMatrix Q = decomposition.getQ(); + RealMatrix R = decomposition.getR(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < m; j++) { + Qa.setDouble(i * m + j, Q.getEntry(i, j)); + } + } + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + Ra.setDouble(i * n + j, R.getEntry(i, j)); + } + } + + return new Array[]{Qa, Ra}; + } + + /** + * Calculates the compact Singular Value Decomposition of a matrix. The + * Singular Value Decomposition of matrix A is a set of three matrices: U, Σ + * and V such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × + * p orthogonal matrix, Σ is a p × p diagonal matrix with positive or null + * elements, V is a p × n orthogonal matrix (hence VT is also orthogonal) + * where p=min(m,n). + * + * @param a Given matrix. + * @return Result U/S/V arrays. + */ + public static Array[] svd(Array a) { + int m = a.getShape()[0]; + int n = a.getShape()[1]; + int k = Math.min(m, n); + Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, k}); + Array Va = Array.factory(DataType.DOUBLE, new int[]{k, n}); + Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + SingularValueDecomposition decomposition = new SingularValueDecomposition(matrix); + RealMatrix U = decomposition.getU(); + RealMatrix V = decomposition.getVT(); + double[] sv = decomposition.getSingularValues(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < k; j++) { + Ua.setDouble(i * k + j, U.getEntry(i, j)); + } + } + for (int i = 0; i < k; i++) { + for (int j = 0; j < n; j++) { + Va.setDouble(i * n + j, V.getEntry(i, j)); + } + } + for (int i = 0; i < k; i++) { + Sa.setDouble(i, sv[i]); + } + + return new Array[]{Ua, Sa, Va}; + } + +// /** +// * Calculates the compact Singular Value Decomposition of a matrix. +// * The Singular Value Decomposition of matrix A is a set of three matrices: U, Σ and V +// * such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × p orthogonal +// * matrix, Σ is a p × p diagonal matrix with positive or null elements, V is a p × n +// * orthogonal matrix (hence VT is also orthogonal) where p=min(m,n). +// * @param a Given matrix. +// * @return Result U/S/V arrays. +// */ +// public static Array[] svd_JAMA(Array a){ +// int m = a.getShape()[0]; +// int n = a.getShape()[1]; +// int k = Math.min(m, n); +// double[][] aa = (double[][])ArrayUtil.copyToNDJavaArray_Double(a); +// Matrix M = new Matrix(aa); +// Jama.SingularValueDecomposition svd = M.svd(); +// Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, k}); +// Array Va = Array.factory(DataType.DOUBLE, new int[]{n, n}); +// Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); +// Matrix U = svd.getU(); +// Matrix V = svd.getV(); +// double[] sv = svd.getSingularValues(); +// for (int i = 0; i < m; i++){ +// for (int j = 0; j < k; j++){ +// Ua.setDouble(i * k + j, U.get(i, j)); +// } +// } +// for (int i = 0; i < n; i++){ +// for (int j = 0; j < n; j++){ +// Va.setDouble(i * n + j, V.get(i, j)); +// } +// } +// for (int i = 0; i < k; i++){ +// Sa.setDouble(i, sv[i]); +// } +// +// return new Array[]{Ua, Sa, Va}; +// } + /** + * Calculates the compact Singular Value Decomposition of a matrix. The + * Singular Value Decomposition of matrix A is a set of three matrices: U, Σ + * and V such that A = U × Σ × VT. Let A be a m × n matrix, then U is a m × + * p orthogonal matrix, Σ is a p × p diagonal matrix with positive or null + * elements, V is a p × n orthogonal matrix (hence VT is also orthogonal) + * where p=min(m,n). + * + * @param a Given matrix. + * @return Result U/S/V arrays. + */ + public static Array[] svd_EJML(Array a) { + int m = a.getShape()[0]; + int n = a.getShape()[1]; + int k = Math.min(m, n); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + SimpleMatrix M = new SimpleMatrix(aa); + SimpleSVD svd = M.svd(false); + Array Ua = Array.factory(DataType.DOUBLE, new int[]{m, m}); + Array Va = Array.factory(DataType.DOUBLE, new int[]{n, n}); + Array Sa = Array.factory(DataType.DOUBLE, new int[]{k}); + SimpleBase U = svd.getU(); + SimpleBase V = svd.getV(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < m; j++) { + Ua.setDouble(i * m + j, U.get(i, j)); + } + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + Va.setDouble(j * n + i, V.get(i, j)); + } + } + for (int i = 0; i < k; i++) { + //Sa.setDouble(i, sv[i]); + Sa.setDouble(i, svd.getSingleValue(i)); + } + + return new Array[]{Ua, Sa, Va}; + } + + /** + * Calculates the eigen decomposition of a real matrix. The eigen + * decomposition of matrix A is a set of two matrices: V and D such that A = + * V × D × VT. A, V and D are all m × m matrices. + * + * @param a Given matrix. + * @return Result W/V arrays. + */ + public static Array[] eigen_bak(Array a) { + int m = a.getShape()[0]; + Array Wa; + Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + EigenDecomposition decomposition = new EigenDecomposition(matrix); + if (decomposition.hasComplexEigenvalues()) { + Wa = Array.factory(DataType.OBJECT, new int[]{m}); + double[] rev = decomposition.getRealEigenvalues(); + double[] iev = decomposition.getImagEigenvalues(); + for (int i = 0; i < m; i++) { + Wa.setObject(i, new Complex(rev[i], iev[i])); + RealVector v = decomposition.getEigenvector(i); + for (int j = 0; j < v.getDimension(); j++) { + Va.setDouble(j * m + i, v.getEntry(j)); + } + } + } else { + RealMatrix V = decomposition.getV(); + RealMatrix D = decomposition.getD(); + Wa = Array.factory(DataType.DOUBLE, new int[]{m}); + for (int i = 0; i < m; i++) { + for (int j = 0; j < m; j++) { + Va.setDouble(i * m + (m - j - 1), V.getEntry(i, j)); + if (i == j) { + Wa.setDouble(m - i - 1, D.getEntry(i, j)); + } + } + } + } + + return new Array[]{Wa, Va}; + } + + /** + * Calculates the eigen decomposition of a real matrix. The eigen + * decomposition of matrix A is a set of two matrices: V and D such that A = + * V × D × VT. A, V and D are all m × m matrices. + * + * @param a Given matrix. + * @return Result W/V arrays. + */ + public static Array[] eigen(Array a) { + int m = a.getShape()[0]; + Array Wa; + Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + EigenDecomposition decomposition = new EigenDecomposition(matrix); + double[] rev = decomposition.getRealEigenvalues(); + double[] iev = decomposition.getImagEigenvalues(); + if (decomposition.hasComplexEigenvalues()) { + Wa = Array.factory(DataType.OBJECT, new int[]{m}); + for (int i = 0; i < m; i++) { + Wa.setObject(i, new Complex(rev[i], iev[i])); + RealVector v = decomposition.getEigenvector(i); + for (int j = 0; j < v.getDimension(); j++) { + Va.setDouble(j * m + i, v.getEntry(j)); + } + } + } else { + Wa = Array.factory(DataType.DOUBLE, new int[]{m}); + for (int i = 0; i < m; i++) { + Wa.setDouble(i, rev[m - i - 1]); + RealVector v = decomposition.getEigenvector(m - i - 1); + for (int j = 0; j < v.getDimension(); j++) { + Va.setDouble(j * m + i, v.getEntry(j)); + } + } + } + + return new Array[]{Wa, Va}; + } + + /** + * Calculates the eigen decomposition of a real matrix. The eigen + * decomposition of matrix A is a set of two matrices: V and D such that A = + * V × D × VT. A, V and D are all m × m matrices. + * + * @param a Given matrix. + * @return Result W/V arrays. + */ + public static Array[] eigen_EJML(Array a) { + int m = a.getShape()[0]; + Array Wa; + Array Va = Array.factory(DataType.DOUBLE, new int[]{m, m}); + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + SimpleMatrix M = new SimpleMatrix(aa); + SimpleEVD evd = M.eig(); + List evs = evd.getEigenvalues(); + boolean isComplex = evd.getEigenVector(0) == null; + if (isComplex) { + Wa = Array.factory(DataType.OBJECT, new int[]{m}); + } else { + Wa = Array.factory(DataType.DOUBLE, new int[]{m}); + } + for (int i = 0; i < m; i++) { + if (isComplex) { + Wa.setObject(i, new Complex(evs.get(i).real, evs.get(i).imaginary)); + } else { + Wa.setDouble(i, evs.get(m - i - 1).real); + SimpleBase v = evd.getEigenVector(m - i - 1); + for (int j = 0; j < v.getNumElements(); j++) { + Va.setDouble(j * m + i, v.get(j)); + } + } + } + + return new Array[]{Wa, Va}; + } + + /** + * Calculate inverse matrix + * + * @param a The matrix + * @return Inverse matrix array + */ + public static Array inv(Array a) { + double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + RealMatrix matrix = new Array2DRowRealMatrix(aa, false); + RealMatrix invm = MatrixUtils.inverse(matrix); + if (invm == null) { + return null; + } + + int m = invm.getRowDimension(); + int n = invm.getColumnDimension(); + Array r = Array.factory(DataType.DOUBLE, new int[]{m, n}); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + r.setDouble(i * n + j, invm.getEntry(i, j)); + } + } + + return r; + } + + /** + * Not correct at present !!! + * + * @param a + * @param b + * @return + */ + public static Array lstsq(Array a, Array b) { + final double[][] aa = (double[][]) ArrayUtil.copyToNDJavaArray_Double(a); + final double[] bb = (double[]) ArrayUtil.copyToNDJavaArray_Double(b); + + // the model function + MultivariateJacobianFunction function = new MultivariateJacobianFunction() { + @Override + public Pair value(final RealVector point) { + RealVector value = new ArrayRealVector(bb.length); + RealMatrix jacobian = new Array2DRowRealMatrix(aa, false); + for (int i = 0; i < bb.length; ++i) { + + } + return new Pair<>(value, jacobian); + + } + }; + + // least squares problem to solve + LeastSquaresProblem problem = new LeastSquaresBuilder(). + //start(new double[]{100.0, 50.0}). + model(function). + target(bb). + lazyEvaluation(false). + maxEvaluations(1000). + maxIterations(1000). + build(); + LeastSquaresOptimizer.Optimum optimum = new LevenbergMarquardtOptimizer().optimize(problem); + + RealVector r = optimum.getPoint(); + int n = r.getDimension(); + Array x = Array.factory(DataType.DOUBLE, new int[]{n}); + for (int i = 0; i < n; i++) { + x.setDouble(i, r.getEntry(i)); + } + + return x; + } + + // Function to get cofactor of + // mat[p][q] in temp[][]. n is + // current dimension of mat[][] + public static void getCofactor(double mat[][], + double temp[][], int p, int q, int n) { + int i = 0, j = 0; + + // Looping for each element of + // the matrix + for (int row = 0; row < n; row++) { + for (int col = 0; col < n; col++) { + + // Copying into temporary matrix + // only those element which are + // not in given row and column + if (row != p && col != q) { + temp[i][j++] = mat[row][col]; + + // Row is filled, so increase + // row index and reset col + //index + if (j == n - 1) { + j = 0; + i++; + } + } + } + } + } + + /* Recursive function for finding determinant + of matrix. n is current dimension of mat[][]. */ + public static double determinantOfMatrix(double mat[][], int n, int N) { + int D = 0; // Initialize result + + // Base case : if matrix contains single + // element + if (n == 1) { + return mat[0][0]; + } + + // To store cofactors + double temp[][] = new double[N][N]; + + // To store sign multiplier + int sign = 1; + + // Iterate for each element of first row + for (int f = 0; f < n; f++) { + // Getting Cofactor of mat[0][f] + getCofactor(mat, temp, 0, f, n); + D += sign * mat[0][f] + * determinantOfMatrix(temp, n - 1, N); + + // terms are to be added with + // alternate sign + sign = -sign; + } + + return D; + } + + /** + * Calculate determinant of a matrix array + * + * @param mat Input array + * @return Determinant + */ + public static double determinantOfMatrix(Array mat) { + int n = mat.getShape()[0]; + double[][] a = (double[][]) ArrayUtil.copyToNDJavaArray_Double(mat); + return determinantOfMatrix(a, n, n); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/meteo/MeteoMath.java b/MeteoInfoLib/src/main/java/org/meteoinfo/math/meteo/MeteoMath.java index 63fad5a8..7bad3919 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/meteo/MeteoMath.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/math/meteo/MeteoMath.java @@ -6,14 +6,12 @@ package org.meteoinfo.math.meteo; import org.meteoinfo.math.ArrayMath; -import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.Index; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.IndexIterator; import java.util.Arrays; -import java.util.List; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/plot/PlotUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/plot/PlotUtil.java index 13685304..93000efe 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/plot/PlotUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/plot/PlotUtil.java @@ -1,99 +1,96 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.plot; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.print.PrintException; -import org.meteoinfo.chart.Chart; -import org.meteoinfo.chart.ChartPanel; -import org.meteoinfo.chart.plot.ChartPlotMethod; -import org.meteoinfo.chart.plot.XY1DPlot; -import org.meteoinfo.data.StationData; -import org.meteoinfo.data.XYArrayDataset; -import org.meteoinfo.data.XYDataset; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.legend.PointBreak; - -/** - * - * @author yaqiang - */ -public class PlotUtil { - - /** - * Get XYDataset from two StationData - * - * @param xdata X station data - * @param ydata Y station data - * @param seriesKey Series key - * @return XYDataset XYDataset - */ - public static XYDataset getXYDataset(StationData xdata, StationData ydata, String seriesKey) { - List xvs = new ArrayList<>(); - List yvs = new ArrayList<>(); - double x, y; - int n = xdata.getStNum(); - for (int i = 0; i < n; i++) { - x = xdata.data[i][2]; - if (MIMath.doubleEquals(x, xdata.missingValue)) { - continue; - } - y = ydata.data[i][2]; - if (MIMath.doubleEquals(y, ydata.missingValue)) { - continue; - } - xvs.add(x); - yvs.add(y); - } - - return new XYArrayDataset(xvs, yvs, seriesKey); - } - - /** - * Create scatter plot - * - * @param title Title - * @param xAxisLabel X axis label - * @param yAxisLabel Y axis label - * @param dataset XYDataset - * @return JFreeChart - */ - public static Chart createScatterPlot(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { - XY1DPlot plot = new XY1DPlot(dataset); - plot.setTitle(title); - plot.setChartPlotMethod(ChartPlotMethod.POINT); - PointBreak pb = new PointBreak(); - plot.setLegendBreak(0, pb); - plot.getXAxis().setLabel(xAxisLabel); - plot.getYAxis().setLabel(yAxisLabel); - Chart chart = new Chart(plot, null); - - return chart; - } - - /** - * Save chart as PNG image file - * - * @param fileName The file name - * @param chart The chart - * @param width Width - * @param height Heigth - * @throws java.io.FileNotFoundException - * @throws java.lang.InterruptedException - */ - public static void exportToPicture(String fileName, Chart chart, int width, int height) - throws FileNotFoundException, InterruptedException { - ChartPanel cp = new ChartPanel(chart); - cp.setSize(width, height); - cp.paintGraphics(); - cp.saveImage(fileName); - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.plot; + +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.chart.Chart; +import org.meteoinfo.chart.ChartPanel; +import org.meteoinfo.chart.plot.ChartPlotMethod; +import org.meteoinfo.chart.plot.XY1DPlot; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.data.StationData; +import org.meteoinfo.data.XYArrayDataset; +import org.meteoinfo.data.XYDataset; +import org.meteoinfo.legend.PointBreak; + +/** + * + * @author yaqiang + */ +public class PlotUtil { + + /** + * Get XYDataset from two StationData + * + * @param xdata X station data + * @param ydata Y station data + * @param seriesKey Series key + * @return XYDataset XYDataset + */ + public static XYDataset getXYDataset(StationData xdata, StationData ydata, String seriesKey) { + List xvs = new ArrayList<>(); + List yvs = new ArrayList<>(); + double x, y; + int n = xdata.getStNum(); + for (int i = 0; i < n; i++) { + x = xdata.data[i][2]; + if (MIMath.doubleEquals(x, xdata.missingValue)) { + continue; + } + y = ydata.data[i][2]; + if (MIMath.doubleEquals(y, ydata.missingValue)) { + continue; + } + xvs.add(x); + yvs.add(y); + } + + return new XYArrayDataset(xvs, yvs, seriesKey); + } + + /** + * Create scatter plot + * + * @param title Title + * @param xAxisLabel X axis label + * @param yAxisLabel Y axis label + * @param dataset XYDataset + * @return JFreeChart + */ + public static Chart createScatterPlot(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset) { + XY1DPlot plot = new XY1DPlot(dataset); + plot.setTitle(title); + plot.setChartPlotMethod(ChartPlotMethod.POINT); + PointBreak pb = new PointBreak(); + plot.setLegendBreak(0, pb); + plot.getXAxis().setLabel(xAxisLabel); + plot.getYAxis().setLabel(yAxisLabel); + Chart chart = new Chart(plot, null); + + return chart; + } + + /** + * Save chart as PNG image file + * + * @param fileName The file name + * @param chart The chart + * @param width Width + * @param height Heigth + * @throws java.io.FileNotFoundException + * @throws java.lang.InterruptedException + */ + public static void exportToPicture(String fileName, Chart chart, int width, int height) + throws FileNotFoundException, InterruptedException { + ChartPanel cp = new ChartPanel(chart); + cp.setSize(width, height); + cp.paintGraphics(); + cp.saveImage(fileName); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/ProjectionUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/ProjectionUtil.java index 49dc3091..7cfc5d3c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/ProjectionUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/ProjectionUtil.java @@ -13,6 +13,10 @@ */ package org.meteoinfo.projection; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.math.ArrayUtil; import org.meteoinfo.ndarray.Array; import org.meteoinfo.projection.info.ProjectionInfo; @@ -22,9 +26,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.meteoinfo.data.mapdata.Field; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.layer.RasterLayer; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.map.ProjectionSet; @@ -678,7 +679,7 @@ public class ProjectionUtil { } } oLayer.setShapes(new ArrayList<>(shapePoints)); - oLayer.setExtent(MIMath.getPointsExtent(newPoints)); + oLayer.setExtent(GeometryUtil.getPointsExtent(newPoints)); break; case Polyline: @@ -957,7 +958,7 @@ public class ProjectionUtil { } } aLayer.setShapes(new ArrayList<>(vectors)); - aLayer.setExtent(MIMath.getPointsExtent(newPoints)); + aLayer.setExtent(GeometryUtil.getPointsExtent(newPoints)); aLayer.getAttributeTable().setTable(aTable); return aLayer; @@ -1057,7 +1058,7 @@ public class ProjectionUtil { } } oLayer.setShapes(new ArrayList<>(shapes)); - oLayer.setExtent(MIMath.getPointsExtent(newPoints)); + oLayer.setExtent(GeometryUtil.getPointsExtent(newPoints)); oLayer.getAttributeTable().setTable(aTable); if (oLayer.getLabelPoints().size() > 0) { diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/Reproject.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/Reproject.java index ac1ecf81..dea26646 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/Reproject.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/Reproject.java @@ -17,12 +17,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.geoprocess.analysis.ResampleMethods; -import org.meteoinfo.global.Extent; -import org.meteoinfo.projection.info.ProjectionInfo; -import org.meteoinfo.global.PointD; import org.meteoinfo.math.ArrayUtil; +import org.meteoinfo.projection.info.ProjectionInfo; import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.DataType; import org.meteoinfo.ndarray.Index; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Albers.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Albers.java index 272900e6..49650240 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Albers.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Albers.java @@ -1,94 +1,94 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class Albers extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public Albers(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Albers_Equal_Area; - } - - // - // - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -90; - double maxLat = 90; - List points = new ArrayList<>(); - double lon = minLon; - double lat = minLat; - while (lon < maxLon) { - points.add(new PointD(lon, lat)); - lon += 1; - } - lon = maxLon; - while (lat < maxLat) { - points.add(new PointD(lon, lat)); - lat += 1; - } - lat = maxLat; - while (lon > minLon) { - points.add(new PointD(lon, lat)); - lon -= 1; - } - lon = minLon; - while (lat > minLat) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - lat = minLat; - points.add(new PointD(lon, lat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class Albers extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public Albers(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Albers_Equal_Area; + } + + // + // + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -90; + double maxLat = 90; + List points = new ArrayList<>(); + double lon = minLon; + double lat = minLat; + while (lon < maxLon) { + points.add(new PointD(lon, lat)); + lon += 1; + } + lon = maxLon; + while (lat < maxLat) { + points.add(new PointD(lon, lat)); + lat += 1; + } + lat = maxLat; + while (lon > minLon) { + points.add(new PointD(lon, lat)); + lon -= 1; + } + lon = minLon; + while (lat > minLat) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + lat = minLat; + points.add(new PointD(lon, lat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java index 3a783af3..45571f89 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java @@ -17,8 +17,8 @@ import java.util.List; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Direction; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; import org.meteoinfo.projection.ProjectionNames; import org.locationtech.proj4j.CoordinateReferenceSystem; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Hammer.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Hammer.java index 040d3871..bd610b1b 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Hammer.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Hammer.java @@ -1,86 +1,87 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class Hammer extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public Hammer(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Hammer_Eckert; - } - - // - // - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -90; - double maxLat = 90; - List points = new ArrayList<>(); - double lon = minLon; - double lat = minLat; - lon = maxLon; - while (lat < maxLat) { - points.add(new PointD(lon, lat)); - lat += 1; - } - lat = maxLat; - lon = minLon; - while (lat > minLat) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - lat = minLat; - points.add(new PointD(lon, lat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class Hammer extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public Hammer(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Hammer_Eckert; + } + + // + // + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -90; + double maxLat = 90; + List points = new ArrayList<>(); + double lon = minLon; + double lat = minLat; + lon = maxLon; + while (lat < maxLat) { + points.add(new PointD(lon, lat)); + lat += 1; + } + lat = maxLat; + lon = minLon; + while (lat > minLat) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + lat = minLat; + points.add(new PointD(lon, lat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java index cf4f2591..fe1dda40 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java @@ -1,78 +1,79 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.Reproject; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class LambertAzimuthalEqualArea extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public LambertAzimuthalEqualArea(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Lambert_Azimuthal_Equal_Area; - } - - // - // - @Override - void updateBoundary() { - double epsilon = 1e-10; - double a = this.crs.getDatum().getEllipsoid().getA(); - double cenLat = this.getCenterLat(); - double cenLon = this.getCenterLon(); - double lon = cenLon + 180 - epsilon; - double sign = Math.signum(cenLat); - if (sign == 0) - sign = 1; - double lat = -cenLat + sign * 0.01; - PointD p = Reproject.reprojectPoint(lon, lat, KnownCoordinateSystems.geographic.world.WGS1984, this); - double x = p.X; - double max_y = p.Y; - double easting = this.crs.getProjection().getFalseEasting(); - double northing = this.crs.getProjection().getFalseNorthing(); - List points = this.ellipse_boundary(a * 1.9999, max_y - northing, easting, northing, 61); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ps; - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.Reproject; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class LambertAzimuthalEqualArea extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public LambertAzimuthalEqualArea(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Lambert_Azimuthal_Equal_Area; + } + + // + // + @Override + void updateBoundary() { + double epsilon = 1e-10; + double a = this.crs.getDatum().getEllipsoid().getA(); + double cenLat = this.getCenterLat(); + double cenLon = this.getCenterLon(); + double lon = cenLon + 180 - epsilon; + double sign = Math.signum(cenLat); + if (sign == 0) + sign = 1; + double lat = -cenLat + sign * 0.01; + PointD p = Reproject.reprojectPoint(lon, lat, KnownCoordinateSystems.geographic.world.WGS1984, this); + double x = p.X; + double max_y = p.Y; + double easting = this.crs.getProjection().getFalseEasting(); + double northing = this.crs.getProjection().getFalseNorthing(); + List points = this.ellipse_boundary(a * 1.9999, max_y - northing, easting, northing, 61); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ps; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java index 3d594f81..b610ca10 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java @@ -1,98 +1,99 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class LambertConformalConic extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public LambertConformalConic(CoordinateReferenceSystem crs) { - this.crs = crs; - this.cutoff = -80.f; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Lambert_Conformal_Conic; - } - - // - // - /** - * Set latitude cutoff - * @param value Latitude cutoff - */ - @Override - public void setCutoff(float value) { - this.cutoff = value; - this.updateBoundary(); - } - - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - List points = new ArrayList<>(); - double lon = cenLon - 180 + epsilon; - double lat = this.cutoff; - while (lon < cenLon + 180 - epsilon) { - points.add(new PointD(lon, lat)); - lon += 1; - } - lon = cenLon + 180 - epsilon; - points.add(new PointD(lon, lat)); - lat += 1; - while (lat < 90) { - points.add(new PointD(lon, lat)); - lat += 1; - } - points.add(new PointD(lon, 90)); - lon = cenLon - 180 + epsilon; - while (lat > this.cutoff) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class LambertConformalConic extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public LambertConformalConic(CoordinateReferenceSystem crs) { + this.crs = crs; + this.cutoff = -80.f; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Lambert_Conformal_Conic; + } + + // + // + /** + * Set latitude cutoff + * @param value Latitude cutoff + */ + @Override + public void setCutoff(float value) { + this.cutoff = value; + this.updateBoundary(); + } + + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + List points = new ArrayList<>(); + double lon = cenLon - 180 + epsilon; + double lat = this.cutoff; + while (lon < cenLon + 180 - epsilon) { + points.add(new PointD(lon, lat)); + lon += 1; + } + lon = cenLon + 180 - epsilon; + points.add(new PointD(lon, lat)); + lat += 1; + while (lat < 90) { + points.add(new PointD(lon, lat)); + lat += 1; + } + points.add(new PointD(lon, 90)); + lon = cenLon - 180 + epsilon; + while (lat > this.cutoff) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java index 93bc1f63..dff74922 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java @@ -1,94 +1,95 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class LambertEqualAreaConic extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public LambertEqualAreaConic(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Lambert_Equal_Area_Conic; - } - - // - // - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -90; - double maxLat = 90; - List points = new ArrayList<>(); - double lon = minLon; - double lat = minLat; - while (lon < maxLon) { - points.add(new PointD(lon, lat)); - lon += 1; - } - lon = maxLon; - while (lat < maxLat) { - points.add(new PointD(lon, lat)); - lat += 1; - } - lat = maxLat; - while (lon > minLon) { - points.add(new PointD(lon, lat)); - lon -= 1; - } - lon = minLon; - while (lat > minLat) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - lat = minLat; - points.add(new PointD(lon, lat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class LambertEqualAreaConic extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public LambertEqualAreaConic(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Lambert_Equal_Area_Conic; + } + + // + // + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -90; + double maxLat = 90; + List points = new ArrayList<>(); + double lon = minLon; + double lat = minLat; + while (lon < maxLon) { + points.add(new PointD(lon, lat)); + lon += 1; + } + lon = maxLon; + while (lat < maxLat) { + points.add(new PointD(lon, lat)); + lat += 1; + } + lat = maxLat; + while (lon > minLon) { + points.add(new PointD(lon, lat)); + lon -= 1; + } + lon = minLon; + while (lat > minLat) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + lat = minLat; + points.add(new PointD(lon, lat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Mercator.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Mercator.java index 1d55c6aa..0ca85d44 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Mercator.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Mercator.java @@ -1,88 +1,89 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class Mercator extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public Mercator(CoordinateReferenceSystem crs) { - this.crs = crs; - this.cutoff = 85.0511f; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Mercator; - } - - // - // - /** - * Set latitude cutoff - * - * @param value Latitude cutoff - */ - @Override - public void setCutoff(float value) { - this.cutoff = value; - this.updateBoundary(); - } - - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -this.cutoff; - double maxLat = this.cutoff; - List points = new ArrayList<>(); - points.add(new PointD(minLon, minLat)); - points.add(new PointD(maxLon, minLat)); - points.add(new PointD(maxLon, maxLat)); - points.add(new PointD(minLon, maxLat)); - points.add(new PointD(minLon, minLat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class Mercator extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public Mercator(CoordinateReferenceSystem crs) { + this.crs = crs; + this.cutoff = 85.0511f; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Mercator; + } + + // + // + /** + * Set latitude cutoff + * + * @param value Latitude cutoff + */ + @Override + public void setCutoff(float value) { + this.cutoff = value; + this.updateBoundary(); + } + + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -this.cutoff; + double maxLat = this.cutoff; + List points = new ArrayList<>(); + points.add(new PointD(minLon, minLat)); + points.add(new PointD(maxLon, minLat)); + points.add(new PointD(maxLon, maxLat)); + points.add(new PointD(minLon, maxLat)); + points.add(new PointD(minLon, minLat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Molleweide.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Molleweide.java index 1dc2f1df..8c92bc2b 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Molleweide.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Molleweide.java @@ -18,8 +18,8 @@ import java.util.List; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Direction; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.ProjectionNames; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java index 3e913628..5a370f29 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java @@ -17,9 +17,8 @@ import java.util.List; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.drawing.Draw; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Direction; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; import org.meteoinfo.projection.ProjectionNames; import org.locationtech.proj4j.CoordinateReferenceSystem; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/ProjectionInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/ProjectionInfo.java index e7366999..8a1cebd1 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/ProjectionInfo.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/ProjectionInfo.java @@ -21,9 +21,9 @@ import java.util.Set; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; import org.meteoinfo.math.ArrayUtil; -import org.meteoinfo.global.PointD; import org.meteoinfo.projection.ProjectionNames; import org.locationtech.proj4j.CRSFactory; import org.locationtech.proj4j.CoordinateReferenceSystem; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Robinson.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Robinson.java index d04a6c09..b0a0ee68 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Robinson.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Robinson.java @@ -18,8 +18,8 @@ import java.util.List; import org.meteoinfo.chart.plot.XAlign; import org.meteoinfo.chart.plot.YAlign; -import org.meteoinfo.global.Direction; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.Direction; +import org.meteoinfo.common.PointD; import org.meteoinfo.map.GridLabel; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.ProjectionNames; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java index 25e23571..d5ab33ec 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java @@ -1,96 +1,97 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class Sinusoidal extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public Sinusoidal(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Sinusoidal; - } - - // - // - /** - * Get valid parameters - * @return Valid parameters - */ - @Override - public List getValidParas() { - List paras = new ArrayList<>(); - paras.add("lon_0"); - return paras; - } - - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -90; - double maxLat = 90; - List points = new ArrayList<>(); - double lon = maxLon; - double lat = minLat; - while (lat < maxLat) { - points.add(new PointD(lon, lat)); - lat += 1; - } - lat = maxLat; - lon = minLon; - while (lat > minLat) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - lat = minLat; - points.add(new PointD(lon, lat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class Sinusoidal extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public Sinusoidal(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Sinusoidal; + } + + // + // + /** + * Get valid parameters + * @return Valid parameters + */ + @Override + public List getValidParas() { + List paras = new ArrayList<>(); + paras.add("lon_0"); + return paras; + } + + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -90; + double maxLat = 90; + List points = new ArrayList<>(); + double lon = maxLon; + double lat = minLat; + while (lat < maxLat) { + points.add(new PointD(lon, lat)); + lat += 1; + } + lat = maxLat; + lon = minLon; + while (lat > minLat) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + lat = minLat; + points.add(new PointD(lon, lat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java index f597e2ac..51a10612 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java @@ -1,107 +1,108 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class StereographicAzimuthal extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public StereographicAzimuthal(CoordinateReferenceSystem crs) { - this.crs = crs; - this.cutoff = 0.f; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - if (this.isNorthPolar()) { - return ProjectionNames.North_Polar_Stereographic_Azimuthal; - } else if (this.isSouthPolar()) { - return ProjectionNames.South_Polar_Stereographic_Azimuthal; - } else { - return ProjectionNames.Stereographic_Azimuthal; - } - } - - // - // - /** - * Check is north polar or not - * - * @return Boolean - */ - public boolean isNorthPolar() { - return this.crs.getProjection().getProjectionLatitudeDegrees() == 90; - } - - /** - * Check is south polar or not - * - * @return Boolean - */ - public boolean isSouthPolar() { - return this.crs.getProjection().getProjectionLatitudeDegrees() == -90; - } - - /** - * Set latitude cutoff - * - * @param value Latitude cutoff - */ - @Override - public void setCutoff(float value) { - this.cutoff = value; - this.updateBoundary(); - } - - @Override - void updateBoundary() { - List points = new ArrayList<>(); - double lon = -180; - double lat = this.cutoff; - while (lon <= 180) { - points.add(new PointD(lon, lat)); - lon += 1; - } - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class StereographicAzimuthal extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public StereographicAzimuthal(CoordinateReferenceSystem crs) { + this.crs = crs; + this.cutoff = 0.f; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + if (this.isNorthPolar()) { + return ProjectionNames.North_Polar_Stereographic_Azimuthal; + } else if (this.isSouthPolar()) { + return ProjectionNames.South_Polar_Stereographic_Azimuthal; + } else { + return ProjectionNames.Stereographic_Azimuthal; + } + } + + // + // + /** + * Check is north polar or not + * + * @return Boolean + */ + public boolean isNorthPolar() { + return this.crs.getProjection().getProjectionLatitudeDegrees() == 90; + } + + /** + * Check is south polar or not + * + * @return Boolean + */ + public boolean isSouthPolar() { + return this.crs.getProjection().getProjectionLatitudeDegrees() == -90; + } + + /** + * Set latitude cutoff + * + * @param value Latitude cutoff + */ + @Override + public void setCutoff(float value) { + this.cutoff = value; + this.updateBoundary(); + } + + @Override + void updateBoundary() { + List points = new ArrayList<>(); + double lon = -180; + double lat = this.cutoff; + while (lon <= 180) { + points.add(new PointD(lon, lat)); + lon += 1; + } + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java index af5ffc9c..8dacc2b2 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java @@ -1,84 +1,85 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.ProjectionNames; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class TransverseMercator extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public TransverseMercator(CoordinateReferenceSystem crs) { - this.crs = crs; - this.cutoff = 85.0511f; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Transverse_Mercator; - } - - // - // - /** - * Set latitude cutoff - * - * @param value Latitude cutoff - */ - @Override - public void setCutoff(float value) { - this.cutoff = value; - this.updateBoundary(); - } - - @Override - void updateBoundary() { - double x0 = -2e7; - double x1 = 2e7; - double y0 = -1e7; - double y1 = 1e7; - List points = new ArrayList<>(); - points.add(new PointD(x0, y0)); - points.add(new PointD(x1, y0)); - points.add(new PointD(x1, y1)); - points.add(new PointD(x0, y1)); - points.add(new PointD(x0, y0)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ps; - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.ProjectionNames; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class TransverseMercator extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public TransverseMercator(CoordinateReferenceSystem crs) { + this.crs = crs; + this.cutoff = 85.0511f; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Transverse_Mercator; + } + + // + // + /** + * Set latitude cutoff + * + * @param value Latitude cutoff + */ + @Override + public void setCutoff(float value) { + this.cutoff = value; + this.updateBoundary(); + } + + @Override + void updateBoundary() { + double x0 = -2e7; + double x1 = 2e7; + double y0 = -1e7; + double y1 = 1e7; + List points = new ArrayList<>(); + points.add(new PointD(x0, y0)); + points.add(new PointD(x1, y0)); + points.add(new PointD(x1, y1)); + points.add(new PointD(x0, y1)); + points.add(new PointD(x0, y0)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ps; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Wagner3.java b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Wagner3.java index 593c2655..f5caa7e9 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Wagner3.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/projection/info/Wagner3.java @@ -1,94 +1,95 @@ -/* Copyright 2012 - Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.projection.info; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.projection.KnownCoordinateSystems; -import org.meteoinfo.projection.ProjectionNames; -import org.meteoinfo.projection.ProjectionUtil; -import org.locationtech.proj4j.CoordinateReferenceSystem; -import org.meteoinfo.shape.PolygonShape; - -/** - * - * @author Yaqiang Wang - */ -public class Wagner3 extends ProjectionInfo { - - // - // - // - /** - * Construction - * - * @param crs Coorinate reference system - */ - public Wagner3(CoordinateReferenceSystem crs) { - this.crs = crs; - } - - // - // - /** - * Get projection name - * - * @return Projection name - */ - @Override - public ProjectionNames getProjectionName() { - return ProjectionNames.Wagner3; - } - - // - // - @Override - void updateBoundary() { - double epsilon = 1e-10; - double cenLon = this.getCenterLon(); - double minLon = cenLon - 180 + epsilon; - double maxLon = cenLon + 180 - epsilon; - double minLat = -90; - double maxLat = 90; - List points = new ArrayList<>(); - double lon = minLon; - double lat = minLat; - while (lon < maxLon) { - points.add(new PointD(lon, lat)); - lon += 1; - } - lon = maxLon; - while (lat < maxLat) { - points.add(new PointD(lon, lat)); - lat += 1; - } - lat = maxLat; - while (lon > minLon) { - points.add(new PointD(lon, lat)); - lon -= 1; - } - lon = minLon; - while (lat > minLat) { - points.add(new PointD(lon, lat)); - lat -= 1; - } - lat = minLat; - points.add(new PointD(lon, lat)); - PolygonShape ps = new PolygonShape(); - ps.setPoints(points); - this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); - } - // -} +/* Copyright 2012 - Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.projection.info; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.projection.KnownCoordinateSystems; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.meteoinfo.shape.PolygonShape; + +/** + * + * @author Yaqiang Wang + */ +public class Wagner3 extends ProjectionInfo { + + // + // + // + /** + * Construction + * + * @param crs Coorinate reference system + */ + public Wagner3(CoordinateReferenceSystem crs) { + this.crs = crs; + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Wagner3; + } + + // + // + @Override + void updateBoundary() { + double epsilon = 1e-10; + double cenLon = this.getCenterLon(); + double minLon = cenLon - 180 + epsilon; + double maxLon = cenLon + 180 - epsilon; + double minLat = -90; + double maxLat = 90; + List points = new ArrayList<>(); + double lon = minLon; + double lat = minLat; + while (lon < maxLon) { + points.add(new PointD(lon, lat)); + lon += 1; + } + lon = maxLon; + while (lat < maxLat) { + points.add(new PointD(lon, lat)); + lat += 1; + } + lat = maxLat; + while (lon > minLon) { + points.add(new PointD(lon, lat)); + lon -= 1; + } + lon = minLon; + while (lat > minLat) { + points.add(new PointD(lon, lat)); + lat -= 1; + } + lat = minLat; + points.add(new PointD(lon, lat)); + PolygonShape ps = new PolygonShape(); + ps.setPoints(points); + this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoData.java index 916262b6..e02dca47 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoData.java @@ -1,295 +1,273 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.script; - -import java.awt.Color; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.WindowConstants; -import org.meteoinfo.chart.Chart; -import org.meteoinfo.chart.ChartPanel; -import org.meteoinfo.chart.plot.ChartPlotMethod; -import org.meteoinfo.chart.plot.XY1DPlot; -import org.meteoinfo.data.GridData; -import org.meteoinfo.data.XYArrayDataset; -import org.meteoinfo.data.mapdata.MapDataManage; -import org.meteoinfo.data.meteodata.DrawMeteoData; -import org.meteoinfo.data.meteodata.DrawType2D; -import org.meteoinfo.data.meteodata.MeteoDataInfo; -import org.meteoinfo.legend.PointStyle; -import org.meteoinfo.global.Extent; -import org.meteoinfo.layer.MapLayer; -import org.meteoinfo.layout.MapLayout; -import org.meteoinfo.legend.LineStyles; -import org.meteoinfo.legend.MapFrame; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import org.meteoinfo.map.MapView; - -/** - * - * @author yaqiang - */ -public class MeteoInfoData { - // - private List dataInfoList; - private MeteoDataInfo currentDataInfo; - - // - // - /** - * Constructor - */ - public MeteoInfoData() { - dataInfoList = new ArrayList(); - } - - // - // - // - // - // - /** - * Add a meteo data info - * - * @param aDataInfo The meteo data info - */ - public void addMeteoData(MeteoDataInfo aDataInfo) { - dataInfoList.add(aDataInfo); - currentDataInfo = aDataInfo; - } - - /** - * Open GrADS data file - * - * @param fileName GrADS data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openGrADSData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openGrADSData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open ARL data file - * - * @param fileName ARL data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openARLData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openARLData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open ASCII grid data file - * - * @param fileName ASCII grid data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openASCIIGridData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openASCIIGridData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open Surfer grid data file - * - * @param fileName Surfer grid data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openSurferGridData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openSurferGridData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT concentration data file - * - * @param fileName HYSPLIT concentration data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPLITConcData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITConcData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT particle data file - * - * @param fileName HYSPLIT particle data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPITPartData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITPartData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT trajectory data file - * - * @param fileName HYSPLIT trajectory data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPLITTrajData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITTrajData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - -// /** -// * Open HYSPLIT trajectory data files -// * -// * @param fileNames HYSPLIT trajectory data file names -// * @return MeteoDataInfo -// */ -// public MeteoDataInfo openHYSPLITTrajData(String[] fileNames) { -// MeteoDataInfo aDataInfo = new MeteoDataInfo(); -// aDataInfo.openHYSPLITTrajData(fileNames); -// addMeteoData(aDataInfo); -// -// return aDataInfo; -// } - - /** - * Open NetCDF, GRIB, HDF... data file - * - * @param fileName NetCDF, GRIB, HDF... data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openNetCDFData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openNetCDFData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open Lon/Lat station data file - * - * @param fileName Lon/Lat station data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openLonLatData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openLonLatData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MICAPS data file - * - * @param fileName MICAPS data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMICAPSData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMICAPSData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MM5 output data file - * - * @param fileName MM5 output data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMM5Data(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMM5Data(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MM5 intermedia data file - * - * @param fileName MM5 intermedia data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMM5IMData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMM5IMData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - // - // - /** - * Get grid data - * @param varName Variable name - * @return Grid data - */ - public GridData getGridData(String varName){ - return this.currentDataInfo.getGridData(varName); - } - // - // - /** - * Get line space data list - * @param min Minimum - * @param max Maximum - * @param n Number - * @return Data list - */ - public List linespace(double min, double max, int n){ - List values = new ArrayList(); - double delta = (max - min) / (n - 1); - for (int i = 0; i < n; i++){ - values.add(min + delta * i); - } - - return values; - } - - /** - * Get sine values - * @param values Input values - * @return Sine values - */ - public List sin(List values){ - List rvalues = new ArrayList(); - for (Double v : values){ - rvalues.add(Math.sin(v)); - } - - return rvalues; - } - // - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.script; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.data.GridData; +import org.meteoinfo.data.meteodata.MeteoDataInfo; + +/** + * + * @author yaqiang + */ +public class MeteoInfoData { + // + private List dataInfoList; + private MeteoDataInfo currentDataInfo; + + // + // + /** + * Constructor + */ + public MeteoInfoData() { + dataInfoList = new ArrayList(); + } + + // + // + // + // + // + /** + * Add a meteo data info + * + * @param aDataInfo The meteo data info + */ + public void addMeteoData(MeteoDataInfo aDataInfo) { + dataInfoList.add(aDataInfo); + currentDataInfo = aDataInfo; + } + + /** + * Open GrADS data file + * + * @param fileName GrADS data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openGrADSData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openGrADSData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open ARL data file + * + * @param fileName ARL data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openARLData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openARLData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open ASCII grid data file + * + * @param fileName ASCII grid data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openASCIIGridData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openASCIIGridData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open Surfer grid data file + * + * @param fileName Surfer grid data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openSurferGridData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openSurferGridData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT concentration data file + * + * @param fileName HYSPLIT concentration data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPLITConcData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITConcData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT particle data file + * + * @param fileName HYSPLIT particle data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPITPartData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITPartData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT trajectory data file + * + * @param fileName HYSPLIT trajectory data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPLITTrajData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITTrajData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + +// /** +// * Open HYSPLIT trajectory data files +// * +// * @param fileNames HYSPLIT trajectory data file names +// * @return MeteoDataInfo +// */ +// public MeteoDataInfo openHYSPLITTrajData(String[] fileNames) { +// MeteoDataInfo aDataInfo = new MeteoDataInfo(); +// aDataInfo.openHYSPLITTrajData(fileNames); +// addMeteoData(aDataInfo); +// +// return aDataInfo; +// } + + /** + * Open NetCDF, GRIB, HDF... data file + * + * @param fileName NetCDF, GRIB, HDF... data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openNetCDFData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openNetCDFData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open Lon/Lat station data file + * + * @param fileName Lon/Lat station data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openLonLatData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openLonLatData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MICAPS data file + * + * @param fileName MICAPS data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMICAPSData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMICAPSData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MM5 output data file + * + * @param fileName MM5 output data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMM5Data(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMM5Data(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MM5 intermedia data file + * + * @param fileName MM5 intermedia data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMM5IMData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMM5IMData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + // + // + /** + * Get grid data + * @param varName Variable name + * @return Grid data + */ + public GridData getGridData(String varName){ + return this.currentDataInfo.getGridData(varName); + } + // + // + /** + * Get line space data list + * @param min Minimum + * @param max Maximum + * @param n Number + * @return Data list + */ + public List linespace(double min, double max, int n){ + List values = new ArrayList(); + double delta = (max - min) / (n - 1); + for (int i = 0; i < n; i++){ + values.add(min + delta * i); + } + + return values; + } + + /** + * Get sine values + * @param values Input values + * @return Sine values + */ + public List sin(List values){ + List rvalues = new ArrayList(); + for (Double v : values){ + rvalues.add(Math.sin(v)); + } + + return rvalues; + } + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoPlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoPlot.java index fc01c42b..9d2ed5ce 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoPlot.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoPlot.java @@ -1,276 +1,276 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.script; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; -import javax.swing.WindowConstants; -import org.meteoinfo.chart.ChartPanel; -import org.meteoinfo.chart.plot.XY1DPlot; -import org.meteoinfo.legend.PointStyle; -import org.meteoinfo.global.Extent; -import org.meteoinfo.legend.LineStyles; - -/** - * - * @author yaqiang - */ -public class MeteoInfoPlot { - - // - private boolean batchMode; - private ChartPanel charPanel; - - // - // - /** - * Constructor - */ - public MeteoInfoPlot() { - this.batchMode = true; - this.charPanel = new ChartPanel(null); - } - - // - // - // - // - - // -// /** -// * Plot -// * -// * @param yValues Y values -// */ -// public void plot(List yValues) { -// List xValues = new ArrayList(); -// for (int i = 0; i < yValues.size(); i++) { -// xValues.add(i); -// } -// -// this.plot(xValues, yValues); -// } - -// /** -// * Plot -// * -// * @param xValues X values -// * @param yValues Y values -// */ -// public void plot(List xValues, List yValues) { -// this.plot(xValues, yValues, ""); -// } - -// /** -// * Plot -// * -// * @param xValues X values -// * @param yValues Y values -// * @param style Plot style -// */ -// public void plot(List xValues, List yValues, String style) { -// if (xValues.size() != yValues.size()) { -// System.out.println("The size of x and y values are not same!"); -// return; -// } -// -// XYArrayDataset dataset = new XYArrayDataset(xValues, yValues, "S_1"); -// XY1DPlot plot = new XY1DPlot(dataset); -// -// if (!style.isEmpty()) { -// Color color = this.getColor(style); -// PointStyle ps = this.getPointStyle(style); -// LineStyles ls = this.getLineStyle(style); -// if (ps != null) { -// if (ls == null){ -// plot.setChartPlotMethod(ChartPlotMethod.POINT); -// PointBreak pb = plot.getPointBreak(0); -// pb.setSize(8); -// pb.setStyle(this.getPointStyle(style)); -// if (color != null) { -// pb.setColor(color); -// } -// } else { -// plot.setChartPlotMethod(ChartPlotMethod.LINE_POINT); -// PolylineBreak plb = plot.getPolylineBreak(0); -// plb.setStyle(ls); -// plb.setDrawSymbol(true); -// plb.setSymbolStyle(ps); -// plb.setSymbolInterval(this.getSymbolInterval(xValues.size())); -// if (color != null) { -// plb.setColor(color); -// plb.setSymbolColor(color); -// } -// } -// } else { -// plot.setChartPlotMethod(ChartPlotMethod.LINE); -// PolylineBreak plb = plot.getPolylineBreak(0); -// if (color != null) { -// plb.setColor(color); -// } -// if (ls != null){ -// plb.setStyle(ls); -// } -// } -// } -// -// Chart chart = new Chart(plot); -// chart.setAntiAlias(true); -// this.charPanel.setChart(chart); -// this.charPanel.paintGraphics(); -// } - - private LineStyles getLineStyle(String style){ - LineStyles ls = null; - if (style.contains("--")){ - ls = LineStyles.DASH; - } else if (style.contains(":")){ - ls = LineStyles.DOT; - } else if (style.contains("-.")) { - ls = LineStyles.DASHDOT; - } else if (style.contains("-")) { - ls = LineStyles.SOLID; - } - - return ls; - } - - private PointStyle getPointStyle(String style) { - PointStyle ps = null; - if (style.contains("o")) { - ps = PointStyle.Circle; - } else if (style.contains("D")){ - ps = PointStyle.Diamond; - } else if (style.contains("+")){ - ps = PointStyle.Plus; - } else if (style.contains("s")){ - ps = PointStyle.Square; - } else if (style.contains("*")){ - ps = PointStyle.StarLines; - } else if (style.contains("^")){ - ps = PointStyle.UpTriangle; - } else if (style.contains("x")){ - ps = PointStyle.XCross; - } - - return ps; - } - - private Color getColor(String style) { - if (style.contains("r")) { - return Color.red; - } else if (style.contains("k")) { - return Color.black; - } else if (style.contains("b")) { - return Color.blue; - } else if (style.contains("g")) { - return Color.green; - } else if (style.contains("g")) { - return Color.white; - } else { - return null; - } - } - - private int getSymbolInterval(int n){ - int i; - int v = 20; - if (n < v) - i = 1; - else { - i = n / v; - } - - return i; - } - - /** - * Set axis limits - * @param limits Limits - */ - public void axis(List limits){ - if (limits.size() == 4){ - double xmin = Double.parseDouble(limits.get(0).toString()); - double xmax = Double.parseDouble(limits.get(1).toString()); - double ymin = Double.parseDouble(limits.get(2).toString()); - double ymax = Double.parseDouble(limits.get(3).toString()); - XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); - plot.setDrawExtent(new Extent(xmin, xmax, ymin, ymax)); - this.charPanel.paintGraphics(); - } - } - - /** - * Set y axis label - * @param label Y axis label - */ - public void ylabel(String label){ - XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); - plot.getYAxis().setLabel(label); - plot.getYAxis().setDrawLabel(true); - this.charPanel.paintGraphics(); - } - - /** - * Set y axis label - * @param label Y axis label - */ - public void xlabel(String label){ - XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); - plot.getXAxis().setLabel(label); - plot.getXAxis().setDrawLabel(true); - this.charPanel.paintGraphics(); - } - - // - // - /** - * Show figure form - */ - public void show() { - ChartForm form = new ChartForm(this.charPanel); - form.setSize(600, 500); - form.setLocationRelativeTo(null); - form.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - form.setVisible(true); - this.charPanel.paintGraphics(); - } - // - // - /** - * Get line space data list - * @param min Minimum - * @param max Maximum - * @param n Number - * @return Data list - */ - public List linespace(double min, double max, int n){ - List values = new ArrayList(); - double delta = (max - min) / (n - 1); - for (int i = 0; i < n; i++){ - values.add(min + delta * i); - } - - return values; - } - - /** - * Get sine values - * @param values Input values - * @return Sine values - */ - public List sin(List values){ - List rvalues = new ArrayList(); - for (Double v : values){ - rvalues.add(Math.sin(v)); - } - - return rvalues; - } - // - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.script; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; +import javax.swing.WindowConstants; +import org.meteoinfo.chart.ChartPanel; +import org.meteoinfo.chart.plot.XY1DPlot; +import org.meteoinfo.common.Extent; +import org.meteoinfo.legend.PointStyle; +import org.meteoinfo.legend.LineStyles; + +/** + * + * @author yaqiang + */ +public class MeteoInfoPlot { + + // + private boolean batchMode; + private ChartPanel charPanel; + + // + // + /** + * Constructor + */ + public MeteoInfoPlot() { + this.batchMode = true; + this.charPanel = new ChartPanel(null); + } + + // + // + // + // + + // +// /** +// * Plot +// * +// * @param yValues Y values +// */ +// public void plot(List yValues) { +// List xValues = new ArrayList(); +// for (int i = 0; i < yValues.size(); i++) { +// xValues.add(i); +// } +// +// this.plot(xValues, yValues); +// } + +// /** +// * Plot +// * +// * @param xValues X values +// * @param yValues Y values +// */ +// public void plot(List xValues, List yValues) { +// this.plot(xValues, yValues, ""); +// } + +// /** +// * Plot +// * +// * @param xValues X values +// * @param yValues Y values +// * @param style Plot style +// */ +// public void plot(List xValues, List yValues, String style) { +// if (xValues.size() != yValues.size()) { +// System.out.println("The size of x and y values are not same!"); +// return; +// } +// +// XYArrayDataset dataset = new XYArrayDataset(xValues, yValues, "S_1"); +// XY1DPlot plot = new XY1DPlot(dataset); +// +// if (!style.isEmpty()) { +// Color color = this.getColor(style); +// PointStyle ps = this.getPointStyle(style); +// LineStyles ls = this.getLineStyle(style); +// if (ps != null) { +// if (ls == null){ +// plot.setChartPlotMethod(ChartPlotMethod.POINT); +// PointBreak pb = plot.getPointBreak(0); +// pb.setSize(8); +// pb.setStyle(this.getPointStyle(style)); +// if (color != null) { +// pb.setColor(color); +// } +// } else { +// plot.setChartPlotMethod(ChartPlotMethod.LINE_POINT); +// PolylineBreak plb = plot.getPolylineBreak(0); +// plb.setStyle(ls); +// plb.setDrawSymbol(true); +// plb.setSymbolStyle(ps); +// plb.setSymbolInterval(this.getSymbolInterval(xValues.size())); +// if (color != null) { +// plb.setColor(color); +// plb.setSymbolColor(color); +// } +// } +// } else { +// plot.setChartPlotMethod(ChartPlotMethod.LINE); +// PolylineBreak plb = plot.getPolylineBreak(0); +// if (color != null) { +// plb.setColor(color); +// } +// if (ls != null){ +// plb.setStyle(ls); +// } +// } +// } +// +// Chart chart = new Chart(plot); +// chart.setAntiAlias(true); +// this.charPanel.setChart(chart); +// this.charPanel.paintGraphics(); +// } + + private LineStyles getLineStyle(String style){ + LineStyles ls = null; + if (style.contains("--")){ + ls = LineStyles.DASH; + } else if (style.contains(":")){ + ls = LineStyles.DOT; + } else if (style.contains("-.")) { + ls = LineStyles.DASHDOT; + } else if (style.contains("-")) { + ls = LineStyles.SOLID; + } + + return ls; + } + + private PointStyle getPointStyle(String style) { + PointStyle ps = null; + if (style.contains("o")) { + ps = PointStyle.Circle; + } else if (style.contains("D")){ + ps = PointStyle.Diamond; + } else if (style.contains("+")){ + ps = PointStyle.Plus; + } else if (style.contains("s")){ + ps = PointStyle.Square; + } else if (style.contains("*")){ + ps = PointStyle.StarLines; + } else if (style.contains("^")){ + ps = PointStyle.UpTriangle; + } else if (style.contains("x")){ + ps = PointStyle.XCross; + } + + return ps; + } + + private Color getColor(String style) { + if (style.contains("r")) { + return Color.red; + } else if (style.contains("k")) { + return Color.black; + } else if (style.contains("b")) { + return Color.blue; + } else if (style.contains("g")) { + return Color.green; + } else if (style.contains("g")) { + return Color.white; + } else { + return null; + } + } + + private int getSymbolInterval(int n){ + int i; + int v = 20; + if (n < v) + i = 1; + else { + i = n / v; + } + + return i; + } + + /** + * Set axis limits + * @param limits Limits + */ + public void axis(List limits){ + if (limits.size() == 4){ + double xmin = Double.parseDouble(limits.get(0).toString()); + double xmax = Double.parseDouble(limits.get(1).toString()); + double ymin = Double.parseDouble(limits.get(2).toString()); + double ymax = Double.parseDouble(limits.get(3).toString()); + XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); + plot.setDrawExtent(new Extent(xmin, xmax, ymin, ymax)); + this.charPanel.paintGraphics(); + } + } + + /** + * Set y axis label + * @param label Y axis label + */ + public void ylabel(String label){ + XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); + plot.getYAxis().setLabel(label); + plot.getYAxis().setDrawLabel(true); + this.charPanel.paintGraphics(); + } + + /** + * Set y axis label + * @param label Y axis label + */ + public void xlabel(String label){ + XY1DPlot plot = (XY1DPlot)this.charPanel.getChart().getPlot(); + plot.getXAxis().setLabel(label); + plot.getXAxis().setDrawLabel(true); + this.charPanel.paintGraphics(); + } + + // + // + /** + * Show figure form + */ + public void show() { + ChartForm form = new ChartForm(this.charPanel); + form.setSize(600, 500); + form.setLocationRelativeTo(null); + form.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + form.setVisible(true); + this.charPanel.paintGraphics(); + } + // + // + /** + * Get line space data list + * @param min Minimum + * @param max Maximum + * @param n Number + * @return Data list + */ + public List linespace(double min, double max, int n){ + List values = new ArrayList(); + double delta = (max - min) / (n - 1); + for (int i = 0; i < n; i++){ + values.add(min + delta * i); + } + + return values; + } + + /** + * Get sine values + * @param values Input values + * @return Sine values + */ + public List sin(List values){ + List rvalues = new ArrayList(); + for (Double v : values){ + rvalues.add(Math.sin(v)); + } + + return rvalues; + } + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoScript.java b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoScript.java index c813e171..95629950 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoScript.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/script/MeteoInfoScript.java @@ -1,624 +1,624 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.script; - -import java.awt.Color; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.WindowConstants; -import org.meteoinfo.chart.ChartPanel; -import org.meteoinfo.chart.ChartText; -import org.meteoinfo.chart.plot.XY1DPlot; -import org.meteoinfo.data.GridData; -import org.meteoinfo.data.mapdata.MapDataManage; -import org.meteoinfo.data.meteodata.DimensionSet; -import org.meteoinfo.data.meteodata.DrawMeteoData; -import org.meteoinfo.data.meteodata.DrawType2D; -import org.meteoinfo.data.meteodata.MeteoDataInfo; -import org.meteoinfo.data.meteodata.PlotDimension; -import org.meteoinfo.legend.PointStyle; -import org.meteoinfo.global.Extent; -import org.meteoinfo.layer.MapLayer; -import org.meteoinfo.layout.MapLayout; -import org.meteoinfo.legend.LineStyles; -import org.meteoinfo.legend.MapFrame; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.map.MapView; - -/** - * - * @author yaqiang - */ -public class MeteoInfoScript { - - // - private boolean batchMode; - private List dataInfoList; - private MeteoDataInfo currentDataInfo; - private MapLayout mapLayout; - private ChartPanel chartPanel; - private DrawType2D drawType2D; - private PlotDimension plotDimension; - private String startUpPath; - private boolean isMap; - private DimensionSet dimensionSet; - - // - // - /** - * Constructor - * @param path Start up path - */ - public MeteoInfoScript(String path) { - this.startUpPath = path; - this.batchMode = true; - this.mapLayout = new MapLayout(); - this.chartPanel = new ChartPanel(null); - dataInfoList = new ArrayList(); - drawType2D = DrawType2D.Contour; - this.plotDimension = PlotDimension.Lat_Lon; - this.isMap = true; - - //Add default map layer - //String fn = path + File.separator + "map" + File.separator + "country1.shp"; - String fn = "D:/Temp/map/country1.shp"; - if (new File(fn).exists()){ - try { - MapLayer layer = MapDataManage.loadLayer(fn); - PolygonBreak pgb = (PolygonBreak)layer.getLegendScheme().getLegendBreaks().get(0); - pgb.setDrawFill(false); - MapFrame mapFrame = mapLayout.getActiveMapFrame(); - MapView mapView = mapFrame.getMapView(); - mapView.setLockViewUpdate(true); - mapFrame.addLayer(layer); - mapFrame.setGridXDelt(60); - mapFrame.setGridYDelt(30); - mapLayout.getActiveLayoutMap().zoomToExtentLonLatEx(mapView.getLayersWholeExtent()); - mapView.setLockViewUpdate(false); - } catch (Exception ex) { - Logger.getLogger(MeteoInfoScript.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - // - // - // - // - // - /** - * Add a meteo data info - * - * @param aDataInfo The meteo data info - */ - public void addMeteoData(MeteoDataInfo aDataInfo) { - dataInfoList.add(aDataInfo); - currentDataInfo = aDataInfo; - } - - /** - * Open GrADS data file - * - * @param fileName GrADS data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openGrADSData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openGrADSData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open ARL data file - * - * @param fileName ARL data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openARLData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openARLData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open ASCII grid data file - * - * @param fileName ASCII grid data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openASCIIGridData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openASCIIGridData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open Surfer grid data file - * - * @param fileName Surfer grid data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openSurferGridData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openSurferGridData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT concentration data file - * - * @param fileName HYSPLIT concentration data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPLITConcData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITConcData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT particle data file - * - * @param fileName HYSPLIT particle data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPITPartData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITPartData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open HYSPLIT trajectory data file - * - * @param fileName HYSPLIT trajectory data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openHYSPLITTrajData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openHYSPLITTrajData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - -// /** -// * Open HYSPLIT trajectory data files -// * -// * @param fileNames HYSPLIT trajectory data file names -// * @return MeteoDataInfo -// */ -// public MeteoDataInfo openHYSPLITTrajData(String[] fileNames) { -// MeteoDataInfo aDataInfo = new MeteoDataInfo(); -// aDataInfo.openHYSPLITTrajData(fileNames); -// addMeteoData(aDataInfo); -// -// return aDataInfo; -// } - - /** - * Open NetCDF, GRIB, HDF... data file - * - * @param fileName NetCDF, GRIB, HDF... data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openNetCDFData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openNetCDFData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open Lon/Lat station data file - * - * @param fileName Lon/Lat station data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openLonLatData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openLonLatData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MICAPS data file - * - * @param fileName MICAPS data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMICAPSData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMICAPSData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MM5 output data file - * - * @param fileName MM5 output data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMM5Data(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMM5Data(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Open MM5 intermedia data file - * - * @param fileName MM5 intermedia data file name - * @return MeteoDataInfo - */ - public MeteoDataInfo openMM5IMData(String fileName) { - MeteoDataInfo aDataInfo = new MeteoDataInfo(); - aDataInfo.openMM5IMData(fileName); - addMeteoData(aDataInfo); - - return aDataInfo; - } - - /** - * Set plot dimension - * @param pdStr Plot dimension - */ - public void setPlotDimension(String pdStr){ - PlotDimension pd = null; - if (pdStr.equalsIgnoreCase("lat_lon")) - pd = PlotDimension.Lat_Lon; - - if (pd != null) - this.currentDataInfo.setDimensionSet(pd); - } - - // - // - public void title(String title){ - if (this.isMap){ - this.mapLayout.addText(title, 280, 20, 16); - this.mapLayout.paintGraphics(); - } else { - this.chartPanel.getChart().setTitle(new ChartText(title)); - this.chartPanel.paintGraphics(); - } - } - // - // - /** - * Dislay - * - * @param varName Variable name - */ - public void display(String varName) { - if (!this.isMap) - this.map(); - - if (currentDataInfo.isGridData()) { - GridData gdata = this.currentDataInfo.getGridData(varName); - MapLayer layer = DrawMeteoData.createContourLayer(gdata, varName, varName); - if (mapLayout == null) { - mapLayout = new MapLayout(); - } - - MapFrame mapFrame = mapLayout.getActiveMapFrame(); - MapView mapView = mapFrame.getMapView(); - mapView.setLockViewUpdate(true); - mapFrame.addLayer(layer); - mapLayout.getActiveLayoutMap().zoomToExtentLonLatEx(mapView.getMeteoLayersExtent()); - mapView.setLockViewUpdate(false); - mapLayout.paintGraphics(); - } - } - - // - // -// /** -// * Plot -// * -// * @param yValues Y values -// */ -// public void plot(List yValues) { -// List xValues = new ArrayList(); -// for (int i = 0; i < yValues.size(); i++) { -// xValues.add(i); -// } -// -// this.plot(xValues, yValues); -// } -// -// /** -// * Plot -// * -// * @param xValues X values -// * @param yValues Y values -// */ -// public void plot(List xValues, List yValues) { -// this.plot(xValues, yValues, ""); -// } -// -// /** -// * Plot -// * -// * @param xValues X values -// * @param yValues Y values -// * @param style Plot style -// */ -// public void plot(List xValues, List yValues, String style) { -// if (this.isMap) -// this.figure(); -// -// if (xValues.size() != yValues.size()) { -// System.out.println("The size of x and y values are not same!"); -// return; -// } -// -// XYArrayDataset dataset = new XYArrayDataset(xValues, yValues, "S_1"); -// XY1DPlot plot = new XY1DPlot(dataset); -// -// if (!style.isEmpty()) { -// Color color = this.getColor(style); -// PointStyle ps = this.getPointStyle(style); -// LineStyles ls = this.getLineStyle(style); -// if (ps != null) { -// if (ls == null){ -// plot.setChartPlotMethod(ChartPlotMethod.POINT); -// PointBreak pb = plot.getPointBreak(0); -// pb.setSize(8); -// pb.setStyle(ps); -// if (color != null) { -// pb.setColor(color); -// } -// } else { -// plot.setChartPlotMethod(ChartPlotMethod.LINE_POINT); -// PolylineBreak plb = plot.getPolylineBreak(0); -// plb.setStyle(ls); -// plb.setDrawSymbol(true); -// plb.setSymbolStyle(ps); -// plb.setSymbolInterval(this.getSymbolInterval(xValues.size())); -// if (color != null) { -// plb.setColor(color); -// plb.setSymbolColor(color); -// } -// } -// } else { -// plot.setChartPlotMethod(ChartPlotMethod.LINE); -// PolylineBreak plb = plot.getPolylineBreak(0); -// if (color != null) { -// plb.setColor(color); -// } -// if (ls != null){ -// plb.setStyle(ls); -// } -// } -// } -// -// Chart chart = new Chart(plot); -// chart.setAntiAlias(true); -// this.chartPanel.setChart(chart); -// this.chartPanel.paintGraphics(); -// } - - private LineStyles getLineStyle(String style){ - LineStyles ls = null; - if (style.contains("--")){ - ls = LineStyles.DASH; - } else if (style.contains(":")){ - ls = LineStyles.DOT; - } else if (style.contains("-.")) { - ls = LineStyles.DASHDOT; - } else if (style.contains("-")) { - ls = LineStyles.SOLID; - } - - return ls; - } - - private PointStyle getPointStyle(String style) { - PointStyle ps = null; - if (style.contains("o")) { - ps = PointStyle.Circle; - } else if (style.contains("D")){ - ps = PointStyle.Diamond; - } else if (style.contains("+")){ - ps = PointStyle.Plus; - } else if (style.contains("s")){ - ps = PointStyle.Square; - } else if (style.contains("*")){ - ps = PointStyle.StarLines; - } else if (style.contains("^")){ - ps = PointStyle.UpTriangle; - } else if (style.contains("x")){ - ps = PointStyle.XCross; - } - - return ps; - } - - private Color getColor(String style) { - if (style.contains("r")) { - return Color.red; - } else if (style.contains("k")) { - return Color.black; - } else if (style.contains("b")) { - return Color.blue; - } else if (style.contains("g")) { - return Color.green; - } else if (style.contains("w")) { - return Color.white; - } else { - return null; - } - } - - private int getSymbolInterval(int n){ - int i; - int v = 20; - if (n < v) - i = 1; - else { - i = n / v; - } - - return i; - } - - /** - * Set axis limits - * @param limits Limits - */ - public void axis(List limits){ - if (limits.size() == 4){ - double xmin = Double.parseDouble(limits.get(0).toString()); - double xmax = Double.parseDouble(limits.get(1).toString()); - double ymin = Double.parseDouble(limits.get(2).toString()); - double ymax = Double.parseDouble(limits.get(3).toString()); - XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); - plot.setDrawExtent(new Extent(xmin, xmax, ymin, ymax)); - this.chartPanel.paintGraphics(); - } - } - - /** - * Set y axis label - * @param label Y axis label - */ - public void ylabel(String label){ - XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); - plot.getYAxis().setLabel(label); - plot.getYAxis().setDrawLabel(true); - this.chartPanel.paintGraphics(); - } - - /** - * Set y axis label - * @param label Y axis label - */ - public void xlabel(String label){ - XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); - plot.getXAxis().setLabel(label); - plot.getXAxis().setDrawLabel(true); - this.chartPanel.paintGraphics(); - } - - // - // - /** - * Show figure form - */ - public void showfigure() { - ChartForm form = new ChartForm(this.chartPanel); - form.setSize(600, 500); - form.setLocationRelativeTo(null); - form.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - form.setVisible(true); - this.chartPanel.paintGraphics(); - } - - /** - * Show map form - */ - public void show(){ - if (this.isMap) - this.showmap(); - else - this.showfigure(); - } - - /** - * Show map or figure form - * @param i I - */ - public void show(int i){ - if (i == 0){ - this.showmap(); - } else - this.showfigure(); - } - - /** - * Switch to map mode - */ - public void map(){ - this.isMap = true; - System.out.println("Switch to map mode"); - } - - /** - * Switch to figure mode - */ - public void figure() { - this.isMap = false; - System.out.println("Switch to figure mode"); - } - - /** - * Create and show map figure form - */ - public void showmap() { - MapForm frame = new MapForm(this.mapLayout); - frame.setSize(750, 540); - frame.setLocationRelativeTo(null); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - frame.setVisible(true); - } - // - // - /** - * Get line space data list - * @param min Minimum - * @param max Maximum - * @param n Number - * @return Data list - */ - public List linespace(double min, double max, int n){ - List values = new ArrayList(); - double delta = (max - min) / (n - 1); - for (int i = 0; i < n; i++){ - values.add(min + delta * i); - } - - return values; - } - - /** - * Get sine values - * @param values Input values - * @return Sine values - */ - public List sin(List values){ - List rvalues = new ArrayList(); - for (Double v : values){ - rvalues.add(Math.sin(v)); - } - - return rvalues; - } - // - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.script; + +import java.awt.Color; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.WindowConstants; +import org.meteoinfo.chart.ChartPanel; +import org.meteoinfo.chart.ChartText; +import org.meteoinfo.chart.plot.XY1DPlot; +import org.meteoinfo.common.Extent; +import org.meteoinfo.data.GridData; +import org.meteoinfo.data.mapdata.MapDataManage; +import org.meteoinfo.data.meteodata.DimensionSet; +import org.meteoinfo.data.meteodata.DrawMeteoData; +import org.meteoinfo.data.meteodata.DrawType2D; +import org.meteoinfo.data.meteodata.MeteoDataInfo; +import org.meteoinfo.data.meteodata.PlotDimension; +import org.meteoinfo.legend.PointStyle; +import org.meteoinfo.layer.MapLayer; +import org.meteoinfo.layout.MapLayout; +import org.meteoinfo.legend.LineStyles; +import org.meteoinfo.legend.MapFrame; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.map.MapView; + +/** + * + * @author yaqiang + */ +public class MeteoInfoScript { + + // + private boolean batchMode; + private List dataInfoList; + private MeteoDataInfo currentDataInfo; + private MapLayout mapLayout; + private ChartPanel chartPanel; + private DrawType2D drawType2D; + private PlotDimension plotDimension; + private String startUpPath; + private boolean isMap; + private DimensionSet dimensionSet; + + // + // + /** + * Constructor + * @param path Start up path + */ + public MeteoInfoScript(String path) { + this.startUpPath = path; + this.batchMode = true; + this.mapLayout = new MapLayout(); + this.chartPanel = new ChartPanel(null); + dataInfoList = new ArrayList(); + drawType2D = DrawType2D.Contour; + this.plotDimension = PlotDimension.Lat_Lon; + this.isMap = true; + + //Add default map layer + //String fn = path + File.separator + "map" + File.separator + "country1.shp"; + String fn = "D:/Temp/map/country1.shp"; + if (new File(fn).exists()){ + try { + MapLayer layer = MapDataManage.loadLayer(fn); + PolygonBreak pgb = (PolygonBreak)layer.getLegendScheme().getLegendBreaks().get(0); + pgb.setDrawFill(false); + MapFrame mapFrame = mapLayout.getActiveMapFrame(); + MapView mapView = mapFrame.getMapView(); + mapView.setLockViewUpdate(true); + mapFrame.addLayer(layer); + mapFrame.setGridXDelt(60); + mapFrame.setGridYDelt(30); + mapLayout.getActiveLayoutMap().zoomToExtentLonLatEx(mapView.getLayersWholeExtent()); + mapView.setLockViewUpdate(false); + } catch (Exception ex) { + Logger.getLogger(MeteoInfoScript.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + // + // + // + // + // + /** + * Add a meteo data info + * + * @param aDataInfo The meteo data info + */ + public void addMeteoData(MeteoDataInfo aDataInfo) { + dataInfoList.add(aDataInfo); + currentDataInfo = aDataInfo; + } + + /** + * Open GrADS data file + * + * @param fileName GrADS data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openGrADSData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openGrADSData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open ARL data file + * + * @param fileName ARL data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openARLData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openARLData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open ASCII grid data file + * + * @param fileName ASCII grid data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openASCIIGridData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openASCIIGridData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open Surfer grid data file + * + * @param fileName Surfer grid data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openSurferGridData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openSurferGridData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT concentration data file + * + * @param fileName HYSPLIT concentration data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPLITConcData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITConcData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT particle data file + * + * @param fileName HYSPLIT particle data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPITPartData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITPartData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open HYSPLIT trajectory data file + * + * @param fileName HYSPLIT trajectory data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openHYSPLITTrajData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openHYSPLITTrajData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + +// /** +// * Open HYSPLIT trajectory data files +// * +// * @param fileNames HYSPLIT trajectory data file names +// * @return MeteoDataInfo +// */ +// public MeteoDataInfo openHYSPLITTrajData(String[] fileNames) { +// MeteoDataInfo aDataInfo = new MeteoDataInfo(); +// aDataInfo.openHYSPLITTrajData(fileNames); +// addMeteoData(aDataInfo); +// +// return aDataInfo; +// } + + /** + * Open NetCDF, GRIB, HDF... data file + * + * @param fileName NetCDF, GRIB, HDF... data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openNetCDFData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openNetCDFData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open Lon/Lat station data file + * + * @param fileName Lon/Lat station data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openLonLatData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openLonLatData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MICAPS data file + * + * @param fileName MICAPS data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMICAPSData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMICAPSData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MM5 output data file + * + * @param fileName MM5 output data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMM5Data(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMM5Data(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Open MM5 intermedia data file + * + * @param fileName MM5 intermedia data file name + * @return MeteoDataInfo + */ + public MeteoDataInfo openMM5IMData(String fileName) { + MeteoDataInfo aDataInfo = new MeteoDataInfo(); + aDataInfo.openMM5IMData(fileName); + addMeteoData(aDataInfo); + + return aDataInfo; + } + + /** + * Set plot dimension + * @param pdStr Plot dimension + */ + public void setPlotDimension(String pdStr){ + PlotDimension pd = null; + if (pdStr.equalsIgnoreCase("lat_lon")) + pd = PlotDimension.Lat_Lon; + + if (pd != null) + this.currentDataInfo.setDimensionSet(pd); + } + + // + // + public void title(String title){ + if (this.isMap){ + this.mapLayout.addText(title, 280, 20, 16); + this.mapLayout.paintGraphics(); + } else { + this.chartPanel.getChart().setTitle(new ChartText(title)); + this.chartPanel.paintGraphics(); + } + } + // + // + /** + * Dislay + * + * @param varName Variable name + */ + public void display(String varName) { + if (!this.isMap) + this.map(); + + if (currentDataInfo.isGridData()) { + GridData gdata = this.currentDataInfo.getGridData(varName); + MapLayer layer = DrawMeteoData.createContourLayer(gdata, varName, varName); + if (mapLayout == null) { + mapLayout = new MapLayout(); + } + + MapFrame mapFrame = mapLayout.getActiveMapFrame(); + MapView mapView = mapFrame.getMapView(); + mapView.setLockViewUpdate(true); + mapFrame.addLayer(layer); + mapLayout.getActiveLayoutMap().zoomToExtentLonLatEx(mapView.getMeteoLayersExtent()); + mapView.setLockViewUpdate(false); + mapLayout.paintGraphics(); + } + } + + // + // +// /** +// * Plot +// * +// * @param yValues Y values +// */ +// public void plot(List yValues) { +// List xValues = new ArrayList(); +// for (int i = 0; i < yValues.size(); i++) { +// xValues.add(i); +// } +// +// this.plot(xValues, yValues); +// } +// +// /** +// * Plot +// * +// * @param xValues X values +// * @param yValues Y values +// */ +// public void plot(List xValues, List yValues) { +// this.plot(xValues, yValues, ""); +// } +// +// /** +// * Plot +// * +// * @param xValues X values +// * @param yValues Y values +// * @param style Plot style +// */ +// public void plot(List xValues, List yValues, String style) { +// if (this.isMap) +// this.figure(); +// +// if (xValues.size() != yValues.size()) { +// System.out.println("The size of x and y values are not same!"); +// return; +// } +// +// XYArrayDataset dataset = new XYArrayDataset(xValues, yValues, "S_1"); +// XY1DPlot plot = new XY1DPlot(dataset); +// +// if (!style.isEmpty()) { +// Color color = this.getColor(style); +// PointStyle ps = this.getPointStyle(style); +// LineStyles ls = this.getLineStyle(style); +// if (ps != null) { +// if (ls == null){ +// plot.setChartPlotMethod(ChartPlotMethod.POINT); +// PointBreak pb = plot.getPointBreak(0); +// pb.setSize(8); +// pb.setStyle(ps); +// if (color != null) { +// pb.setColor(color); +// } +// } else { +// plot.setChartPlotMethod(ChartPlotMethod.LINE_POINT); +// PolylineBreak plb = plot.getPolylineBreak(0); +// plb.setStyle(ls); +// plb.setDrawSymbol(true); +// plb.setSymbolStyle(ps); +// plb.setSymbolInterval(this.getSymbolInterval(xValues.size())); +// if (color != null) { +// plb.setColor(color); +// plb.setSymbolColor(color); +// } +// } +// } else { +// plot.setChartPlotMethod(ChartPlotMethod.LINE); +// PolylineBreak plb = plot.getPolylineBreak(0); +// if (color != null) { +// plb.setColor(color); +// } +// if (ls != null){ +// plb.setStyle(ls); +// } +// } +// } +// +// Chart chart = new Chart(plot); +// chart.setAntiAlias(true); +// this.chartPanel.setChart(chart); +// this.chartPanel.paintGraphics(); +// } + + private LineStyles getLineStyle(String style){ + LineStyles ls = null; + if (style.contains("--")){ + ls = LineStyles.DASH; + } else if (style.contains(":")){ + ls = LineStyles.DOT; + } else if (style.contains("-.")) { + ls = LineStyles.DASHDOT; + } else if (style.contains("-")) { + ls = LineStyles.SOLID; + } + + return ls; + } + + private PointStyle getPointStyle(String style) { + PointStyle ps = null; + if (style.contains("o")) { + ps = PointStyle.Circle; + } else if (style.contains("D")){ + ps = PointStyle.Diamond; + } else if (style.contains("+")){ + ps = PointStyle.Plus; + } else if (style.contains("s")){ + ps = PointStyle.Square; + } else if (style.contains("*")){ + ps = PointStyle.StarLines; + } else if (style.contains("^")){ + ps = PointStyle.UpTriangle; + } else if (style.contains("x")){ + ps = PointStyle.XCross; + } + + return ps; + } + + private Color getColor(String style) { + if (style.contains("r")) { + return Color.red; + } else if (style.contains("k")) { + return Color.black; + } else if (style.contains("b")) { + return Color.blue; + } else if (style.contains("g")) { + return Color.green; + } else if (style.contains("w")) { + return Color.white; + } else { + return null; + } + } + + private int getSymbolInterval(int n){ + int i; + int v = 20; + if (n < v) + i = 1; + else { + i = n / v; + } + + return i; + } + + /** + * Set axis limits + * @param limits Limits + */ + public void axis(List limits){ + if (limits.size() == 4){ + double xmin = Double.parseDouble(limits.get(0).toString()); + double xmax = Double.parseDouble(limits.get(1).toString()); + double ymin = Double.parseDouble(limits.get(2).toString()); + double ymax = Double.parseDouble(limits.get(3).toString()); + XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); + plot.setDrawExtent(new Extent(xmin, xmax, ymin, ymax)); + this.chartPanel.paintGraphics(); + } + } + + /** + * Set y axis label + * @param label Y axis label + */ + public void ylabel(String label){ + XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); + plot.getYAxis().setLabel(label); + plot.getYAxis().setDrawLabel(true); + this.chartPanel.paintGraphics(); + } + + /** + * Set y axis label + * @param label Y axis label + */ + public void xlabel(String label){ + XY1DPlot plot = (XY1DPlot)this.chartPanel.getChart().getPlot(); + plot.getXAxis().setLabel(label); + plot.getXAxis().setDrawLabel(true); + this.chartPanel.paintGraphics(); + } + + // + // + /** + * Show figure form + */ + public void showfigure() { + ChartForm form = new ChartForm(this.chartPanel); + form.setSize(600, 500); + form.setLocationRelativeTo(null); + form.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + form.setVisible(true); + this.chartPanel.paintGraphics(); + } + + /** + * Show map form + */ + public void show(){ + if (this.isMap) + this.showmap(); + else + this.showfigure(); + } + + /** + * Show map or figure form + * @param i I + */ + public void show(int i){ + if (i == 0){ + this.showmap(); + } else + this.showfigure(); + } + + /** + * Switch to map mode + */ + public void map(){ + this.isMap = true; + System.out.println("Switch to map mode"); + } + + /** + * Switch to figure mode + */ + public void figure() { + this.isMap = false; + System.out.println("Switch to figure mode"); + } + + /** + * Create and show map figure form + */ + public void showmap() { + MapForm frame = new MapForm(this.mapLayout); + frame.setSize(750, 540); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.setVisible(true); + } + // + // + /** + * Get line space data list + * @param min Minimum + * @param max Maximum + * @param n Number + * @return Data list + */ + public List linespace(double min, double max, int n){ + List values = new ArrayList(); + double delta = (max - min) / (n - 1); + for (int i = 0; i < n; i++){ + values.add(min + delta * i); + } + + return values; + } + + /** + * Get sine values + * @param values Input values + * @return Sine values + */ + public List sin(List values){ + List rvalues = new ArrayList(); + for (Double v : values){ + rvalues.add(Math.sin(v)); + } + + return rvalues; + } + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ChartGraphic.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ChartGraphic.java index 288a6b7a..db70f604 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ChartGraphic.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ChartGraphic.java @@ -1,143 +1,143 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.PointD; -import org.meteoinfo.legend.ChartBreak; -import org.w3c.dom.Attr; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * - * @author Yaqiang Wang - */ -public class ChartGraphic extends Graphic { - - // - private PointD startPosition; - - // - // - /** - * Constructor - */ - public ChartGraphic() { - - } - - /** - * Constructor - * - * @param shape Point shape - * @param legend Chart break - */ - public ChartGraphic(PointShape shape, ChartBreak legend) { - super(shape, legend); - startPosition = (PointD) shape.getPoint().clone(); - } - - // - // - /** - * Get start position - * - * @return Start position - */ - public PointD getStartPosition() { - return startPosition; - } - - /** - * Set start postion - * - * @param value Start position - */ - public void setStartPosition(PointD value) { - startPosition = value; - } - - /** - * Set point shape - * - * @param aShape Point shape - */ - public void setShape(PointShape aShape) { - super.setShape(aShape); - startPosition = (PointD) aShape.getPoint().clone(); - } - - // - // - /** - * Export to XML document - * - * @param doc XML document - * @param parent Parent XML element - */ - @Override - public void exportToXML(Document doc, Element parent) { - Element graphic = doc.createElement("Graphic"); - this.addShape(doc, graphic, this.getShape()); - this.addLegend(doc, graphic, this.getLegend(), this.getShape().getShapeType()); - this.addStartPosition(doc, graphic, startPosition); - - parent.appendChild(graphic); - } - - private void addStartPosition(Document doc, Element parent, PointD pos) { - Element startPos = doc.createElement("StartPosition"); - - Attr xAttr = doc.createAttribute("X"); - Attr yAttr = doc.createAttribute("Y"); - - xAttr.setValue(String.valueOf(pos.X)); - yAttr.setValue(String.valueOf(pos.Y)); - - startPos.setAttributeNode(xAttr); - startPos.setAttributeNode(yAttr); - - parent.appendChild(startPos); - } - - /** - * Import from xml node - * - * @param graphicNode Graphic xml node - */ - @Override - public void importFromXML(Element graphicNode) { - Node shape = graphicNode.getElementsByTagName("Shape").item(0); - this.setShape((PointShape)loadShape(shape)); - - Node legend = graphicNode.getElementsByTagName("Legend").item(0); - this.setLegend(loadLegend(legend, this.getShape().getShapeType())); - - Node startPos = graphicNode.getElementsByTagName("StartPosition").item(0); - if (startPos != null) { - PointD sP = this.loadStartPosition(startPos); - if (sP != null) { - this.startPosition = sP; - } - } - } - - private PointD loadStartPosition(Node startPosNode) { - PointD sP = null; - try { - double x = Double.parseDouble(startPosNode.getAttributes().getNamedItem("X").getNodeValue()); - double y = Double.parseDouble(startPosNode.getAttributes().getNamedItem("Y").getNodeValue()); - sP = new PointD(x, y); - } catch (DOMException e) { - } catch (NumberFormatException e) { - } - - return sP; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.legend.ChartBreak; +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * + * @author Yaqiang Wang + */ +public class ChartGraphic extends Graphic { + + // + private PointD startPosition; + + // + // + /** + * Constructor + */ + public ChartGraphic() { + + } + + /** + * Constructor + * + * @param shape Point shape + * @param legend Chart break + */ + public ChartGraphic(PointShape shape, ChartBreak legend) { + super(shape, legend); + startPosition = (PointD) shape.getPoint().clone(); + } + + // + // + /** + * Get start position + * + * @return Start position + */ + public PointD getStartPosition() { + return startPosition; + } + + /** + * Set start postion + * + * @param value Start position + */ + public void setStartPosition(PointD value) { + startPosition = value; + } + + /** + * Set point shape + * + * @param aShape Point shape + */ + public void setShape(PointShape aShape) { + super.setShape(aShape); + startPosition = (PointD) aShape.getPoint().clone(); + } + + // + // + /** + * Export to XML document + * + * @param doc XML document + * @param parent Parent XML element + */ + @Override + public void exportToXML(Document doc, Element parent) { + Element graphic = doc.createElement("Graphic"); + this.addShape(doc, graphic, this.getShape()); + this.addLegend(doc, graphic, this.getLegend(), this.getShape().getShapeType()); + this.addStartPosition(doc, graphic, startPosition); + + parent.appendChild(graphic); + } + + private void addStartPosition(Document doc, Element parent, PointD pos) { + Element startPos = doc.createElement("StartPosition"); + + Attr xAttr = doc.createAttribute("X"); + Attr yAttr = doc.createAttribute("Y"); + + xAttr.setValue(String.valueOf(pos.X)); + yAttr.setValue(String.valueOf(pos.Y)); + + startPos.setAttributeNode(xAttr); + startPos.setAttributeNode(yAttr); + + parent.appendChild(startPos); + } + + /** + * Import from xml node + * + * @param graphicNode Graphic xml node + */ + @Override + public void importFromXML(Element graphicNode) { + Node shape = graphicNode.getElementsByTagName("Shape").item(0); + this.setShape((PointShape)loadShape(shape)); + + Node legend = graphicNode.getElementsByTagName("Legend").item(0); + this.setLegend(loadLegend(legend, this.getShape().getShapeType())); + + Node startPos = graphicNode.getElementsByTagName("StartPosition").item(0); + if (startPos != null) { + PointD sP = this.loadStartPosition(startPos); + if (sP != null) { + this.startPosition = sP; + } + } + } + + private PointD loadStartPosition(Node startPosNode) { + PointD sP = null; + try { + double x = Double.parseDouble(startPosNode.getAttributes().getNamedItem("X").getNodeValue()); + double y = Double.parseDouble(startPosNode.getAttributes().getNamedItem("Y").getNodeValue()); + sP = new PointD(x, y); + } catch (DOMException e) { + } catch (NumberFormatException e) { + } + + return sP; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CircleShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CircleShape.java index dbfa1ecc..c5267487 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CircleShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CircleShape.java @@ -15,10 +15,11 @@ package org.meteoinfo.shape; import java.util.ArrayList; import java.util.List; -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.PointD; -/** +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeoComputation; + + /** * Circle shape class * * @author Yaqiang Wang diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CloudCoverage.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CloudCoverage.java index aced7d3b..7f3b061e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CloudCoverage.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CloudCoverage.java @@ -13,9 +13,9 @@ */ package org.meteoinfo.shape; -import org.meteoinfo.global.PointD; + import org.meteoinfo.common.PointD; -/** + /** * Cloud coverage class * * @author Yaqiang Wang diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CubicShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CubicShape.java index bbf6ed45..ee74fc53 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CubicShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CubicShape.java @@ -2,8 +2,8 @@ package org.meteoinfo.shape; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeometryUtil; import java.util.ArrayList; import java.util.List; @@ -41,7 +41,7 @@ public class CubicShape extends Shape{ for (int i = 0; i < 8; i++) { this.points.add(new PointZ()); } - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } /** @@ -50,7 +50,7 @@ public class CubicShape extends Shape{ public CubicShape(List points) { super(); this.points = points; - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } @Override @@ -77,7 +77,7 @@ public class CubicShape extends Shape{ */ public void setPoints(List value) { this.points = (List)value; - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CylinderShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CylinderShape.java index 59e3044e..51f60966 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CylinderShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/CylinderShape.java @@ -2,8 +2,8 @@ package org.meteoinfo.shape; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeometryUtil; import java.util.ArrayList; import java.util.List; @@ -21,7 +21,7 @@ public class CylinderShape extends Shape { this.points = new ArrayList<>(); this.points.add(new PointZ()); this.points.add(new PointZ()); - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } /** @@ -33,7 +33,7 @@ public class CylinderShape extends Shape { super(); this.points = points; this.radius = radius; - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } /** @@ -48,7 +48,7 @@ public class CylinderShape extends Shape { this.points.add(p1); this.points.add(p2); this.radius = radius; - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } @Override @@ -84,7 +84,7 @@ public class CylinderShape extends Shape { */ public void setPoints(List value) { this.points = (List)value; - this.setExtent(MIMath.getPointsExtent(this.points)); + this.setExtent(GeometryUtil.getPointsExtent(this.points)); } /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Graphic.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Graphic.java index 5c3d1b95..04c74d6d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Graphic.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Graphic.java @@ -1,710 +1,711 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.legend.MarkerType; -import org.meteoinfo.legend.PointStyle; -import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.global.PointD; -import org.meteoinfo.layout.ResizeAbility; -import org.meteoinfo.legend.BreakTypes; -import org.meteoinfo.legend.ChartBreak; -import org.meteoinfo.legend.ChartTypes; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.LabelBreak; -import org.meteoinfo.legend.LineStyles; -import org.meteoinfo.legend.PointBreak; -import org.meteoinfo.legend.PolygonBreak; -import org.meteoinfo.legend.PolylineBreak; -import org.meteoinfo.legend.VectorBreak; -import java.awt.Color; -import java.awt.Font; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.Extent; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Graphic class - * - * @author Yaqiang Wang - */ -public class Graphic { - // - - private Shape _shape = null; - private ColorBreak _legend = null; - private ResizeAbility _resizeAbility = ResizeAbility.ResizeAll; - // - // - - /** - * Constructor - */ - public Graphic() { - } - - /** - * Constructor - * - * @param shape a shape - * @param legend a legend - */ - public Graphic(Shape shape, ColorBreak legend) { - _shape = shape; - _legend = legend; - updateResizeAbility(); - } - // - // - - /** - * Get shape - * - * @return Shape - */ - public Shape getShape() { - return _shape; - } - - /** - * Set shape - * - * @param aShape a shape - */ - public void setShape(Shape aShape) { - _shape = aShape; - updateResizeAbility(); - } - - /** - * Get legend - * - * @return Legend - */ - public ColorBreak getLegend() { - return _legend; - } - - public void setLegend(ColorBreak legend) { - _legend = legend; - updateResizeAbility(); - updateResizeAbility(); - } - - /** - * Get resize ability - * - * @return Resize ability - */ - public ResizeAbility getResizeAbility() { - return _resizeAbility; - } - - /** - * Get extent - * - * @return The extent - */ - public Extent getExtent() { - return this._shape.getExtent(); - } - - /** - * Set extent - * @param value The extent - */ - public void setExtent(Extent value){ - this._shape.setExtent(value); - } - - /** - * Get is single legend or not - * @return Boolean - */ - public boolean isSingleLegend(){ - return true; - } - - /** - * Get if is GraphicCollection - * @return Boolean - */ - public boolean isCollection(){ - return false; - } - - // - // - /** - * Get graphics number - * @return 1 - */ - public int getNumGraphics(){ - return 1; - } - - /** - * Get Graphic by index - * @param idx Index - * @return Graphic - */ - public Graphic getGraphicN(int idx){ - return this; - } - - /** - * Get graphic list - * @return Graphic list - */ - public List getGraphics(){ - List gs = new ArrayList<>(); - gs.add(this); - return gs; - } - - private void updateResizeAbility() { - if (_shape != null && _legend != null) { - switch (_shape.getShapeType()) { - case Point: - switch (_legend.getBreakType()) { - case PointBreak: - _resizeAbility = ResizeAbility.SameWidthHeight; - break; - case LabelBreak: - case ChartBreak: - _resizeAbility = ResizeAbility.None; - break; - } - break; - case Circle: - _resizeAbility = ResizeAbility.SameWidthHeight; - break; - default: - _resizeAbility = ResizeAbility.ResizeAll; - break; - } - } - } - - /** - * Vertice edited update - * - * @param vIdx Vertice index - * @param newX New X - * @param newY New Y - */ - public void verticeMoveUpdate(int vIdx, double newX, double newY) { - List points = (List)_shape.getPoints(); - switch (_shape.getShapeType()){ - case Polygon: - case CurvePolygon: - case Rectangle: - int last = points.size() - 1; - if (vIdx == 0) { - if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { - points.get(last).X = newX; - points.get(last).Y = newY; - } - } else if (vIdx == last){ - if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { - points.get(0).X = newX; - points.get(0).Y = newY; - } - } - break; - } - - PointD aP = points.get(vIdx); - aP.X = newX; - aP.Y = newY; - //points.set(vIdx, aP); - _shape.setPoints(points); - } - - /** - * Vertice edited update - * - * @param vIdx Vertice index - * @param point The add vertice - */ - public void verticeAddUpdate(int vIdx, PointD point) { - List points = (List)_shape.getPoints(); - points.add(vIdx, point); - _shape.setPoints(points); - } - - /** - * Vertice edited update - * - * @param vIdx Vertice index - */ - public void verticeRemoveUpdate(int vIdx) { - List points = (List)_shape.getPoints(); - points.remove(vIdx); - _shape.setPoints(points); - } - - /** - * Export to XML document - * @param doc XML document - * @param parent Parent XML element - */ - public void exportToXML(Document doc, Element parent) { - Element graphic = doc.createElement("Graphic"); - addShape(doc, graphic, _shape); - addLegend(doc, graphic, _legend, _shape.getShapeType()); - - parent.appendChild(graphic); - } - - /** - * Add shape to XML document - * @param doc XML document - * @param parent Parent XML element - * @param aShape The shape - */ - protected void addShape(Document doc, Element parent, Shape aShape) { - Element shape = doc.createElement("Shape"); - boolean hasAngle = aShape.getShapeType() == ShapeTypes.Ellipse; - - //Add general attribute - Attr shapeType = doc.createAttribute("ShapeType"); - Attr visible = doc.createAttribute("Visible"); - Attr selected = doc.createAttribute("Selected"); - - //shapeType.InnerText = Enum.GetName(typeof(ShapeTypes), aShape.ShapeType); - shapeType.setValue(aShape.getShapeType().toString()); - visible.setValue(String.valueOf(aShape.isVisible())); - selected.setValue(String.valueOf(aShape.isSelected())); - - shape.setAttributeNode(shapeType); - shape.setAttributeNode(visible); - shape.setAttributeNode(selected); - - if (hasAngle){ - Attr angle = doc.createAttribute("Angle"); - angle.setValue(String.valueOf(((EllipseShape)aShape).getAngle())); - shape.setAttributeNode(angle); - } - - //Add points - Element points = doc.createElement("Points"); - List pointList = (List)aShape.getPoints(); - for (PointD aPoint : pointList) { - Element point = doc.createElement("Point"); - Attr x = doc.createAttribute("X"); - Attr y = doc.createAttribute("Y"); - x.setValue(String.valueOf(aPoint.X)); - y.setValue(String.valueOf(aPoint.Y)); - point.setAttributeNode(x); - point.setAttributeNode(y); - - points.appendChild(point); - } - - shape.appendChild(points); - - parent.appendChild(shape); - } - - /** - * Add legend to XML document - * @param doc XML document - * @param parent Parent XML element - * @param aLegend The legend - * @param shapeType The shape type - */ - protected void addLegend(Document doc, Element parent, ColorBreak aLegend, ShapeTypes shapeType) { - Element legend = doc.createElement("Legend"); - Attr color = doc.createAttribute("Color"); - color.setValue(ColorUtil.toHexEncoding(aLegend.getColor())); - legend.setAttributeNode(color); - - Attr legendType = doc.createAttribute("LegendType"); - Attr size; - Attr style; - Attr outlineColor; - Attr drawOutline; - Attr drawFill; - legendType.setValue(aLegend.getBreakType().toString()); - switch (aLegend.getBreakType()) { - case PointBreak: - PointBreak aPB = (PointBreak) aLegend; - outlineColor = doc.createAttribute("OutlineColor"); - size = doc.createAttribute("Size"); - style = doc.createAttribute("Style"); - drawOutline = doc.createAttribute("DrawOutline"); - drawFill = doc.createAttribute("DrawFill"); - Attr markerType = doc.createAttribute("MarkerType"); - Attr fontName = doc.createAttribute("FontName"); - Attr charIndex = doc.createAttribute("CharIndex"); - Attr imagePath = doc.createAttribute("ImagePath"); - Attr angle = doc.createAttribute("Angle"); - - //legendType.InnerText = "PointBreak"; - outlineColor.setValue(ColorUtil.toHexEncoding(aPB.getOutlineColor())); - size.setValue(String.valueOf(aPB.getSize())); - style.setValue(aPB.getStyle().toString()); - drawOutline.setValue(String.valueOf(aPB.isDrawOutline())); - drawFill.setValue(String.valueOf(aPB.isDrawFill())); - markerType.setValue(aPB.getMarkerType().toString()); - fontName.setValue(aPB.getFontName()); - charIndex.setValue(String.valueOf(aPB.getCharIndex())); - imagePath.setValue(aPB.getImagePath()); - angle.setValue(String.valueOf(aPB.getAngle())); - - legend.setAttributeNode(legendType); - legend.setAttributeNode(outlineColor); - legend.setAttributeNode(size); - legend.setAttributeNode(style); - legend.setAttributeNode(drawOutline); - legend.setAttributeNode(drawFill); - legend.setAttributeNode(markerType); - legend.setAttributeNode(fontName); - legend.setAttributeNode(charIndex); - legend.setAttributeNode(imagePath); - legend.setAttributeNode(angle); - break; - case LabelBreak: - LabelBreak aLB = (LabelBreak) aLegend; - Attr text = doc.createAttribute("Text"); - angle = doc.createAttribute("Angle"); - fontName = doc.createAttribute("FontName"); - Attr fontSize = doc.createAttribute("FontSize"); - Attr fontBold = doc.createAttribute("FontBold"); - Attr yShift = doc.createAttribute("YShift"); - - //legendType.InnerText = "LabelBreak"; - text.setValue(aLB.getText()); - angle.setValue(String.valueOf(aLB.getAngle())); - fontName.setValue(aLB.getFont().getName()); - fontSize.setValue(String.valueOf(aLB.getFont().getSize())); - fontBold.setValue(String.valueOf(aLB.getFont().isBold())); - yShift.setValue(String.valueOf(aLB.getYShift())); - - legend.setAttributeNode(legendType); - legend.setAttributeNode(text); - legend.setAttributeNode(angle); - legend.setAttributeNode(fontName); - legend.setAttributeNode(fontSize); - legend.setAttributeNode(fontBold); - legend.setAttributeNode(yShift); - break; - case ChartBreak: - ChartBreak aChB = (ChartBreak) aLegend; - Attr shapeIndex = doc.createAttribute("ShapeIndex"); - Attr chartType = doc.createAttribute("ChartType"); - Attr chartData = doc.createAttribute("ChartData"); - Attr xShift = doc.createAttribute("XShift"); - yShift = doc.createAttribute("YShift"); - fontName = doc.createAttribute("FontName"); - fontSize = doc.createAttribute("FontSize"); - Attr labelColor = doc.createAttribute("LabelColor"); - - shapeIndex.setValue(String.valueOf(aChB.getShapeIndex())); - //legendType.InnerText = "ChartBreak"; - chartType.setValue(aChB.getChartType().toString()); - String cdata = ""; - for (int i = 0; i < aChB.getItemNum(); i++) { - if (i == 0) { - cdata = String.valueOf(aChB.getChartData().get(i)); - } else { - cdata += "," + String.valueOf(aChB.getChartData().get(i)); - } - } - chartData.setValue(cdata); - xShift.setValue(String.valueOf(aChB.getXShift())); - yShift.setValue(String.valueOf(aChB.getYShift())); - fontName.setValue(aChB.getLabelFont().getFontName()); - fontSize.setValue(String.valueOf(aChB.getLabelFont().getSize())); - labelColor.setValue(ColorUtil.toHexEncoding(aChB.getLabelColor())); - - legend.setAttributeNode(legendType); - legend.setAttributeNode(shapeIndex); - legend.setAttributeNode(chartType); - legend.setAttributeNode(chartData); - legend.setAttributeNode(xShift); - legend.setAttributeNode(yShift); - legend.setAttributeNode(fontName); - legend.setAttributeNode(fontSize); - legend.setAttributeNode(labelColor); - break; - case VectorBreak: - //legendType.InnerText = "VectorBreak"; - legend.setAttributeNode(legendType); - break; - case PolylineBreak: - PolylineBreak aPLB = (PolylineBreak) aLegend; - size = doc.createAttribute("Size"); - style = doc.createAttribute("Style"); - Attr drawSymbol = doc.createAttribute("DrawSymbol"); - Attr symbolSize = doc.createAttribute("SymbolSize"); - Attr symbolStyle = doc.createAttribute("SymbolStyle"); - Attr symbolColor = doc.createAttribute("SymbolColor"); - Attr symbolInterval = doc.createAttribute("SymbolInterval"); - - //legendType.InnerText = "PolylineBreak"; - size.setValue(String.valueOf(aPLB.getWidth())); - style.setValue(aPLB.getStyle().toString()); - drawSymbol.setValue(String.valueOf(aPLB.getDrawSymbol())); - symbolSize.setValue(String.valueOf(aPLB.getSymbolSize())); - symbolStyle.setValue(String.valueOf(aPLB.getSymbolStyle())); - symbolColor.setValue(ColorUtil.toHexEncoding(aPLB.getSymbolColor())); - symbolInterval.setValue(String.valueOf(aPLB.getSymbolInterval())); - - legend.setAttributeNode(legendType); - legend.setAttributeNode(size); - legend.setAttributeNode(style); - legend.setAttributeNode(drawSymbol); - legend.setAttributeNode(symbolSize); - legend.setAttributeNode(symbolStyle); - legend.setAttributeNode(symbolColor); - legend.setAttributeNode(symbolInterval); - break; - case PolygonBreak: - PolygonBreak aPGB = (PolygonBreak) aLegend; - outlineColor = doc.createAttribute("OutlineColor"); - drawOutline = doc.createAttribute("DrawOutline"); - drawFill = doc.createAttribute("DrawFill"); - Attr outlineSize = doc.createAttribute("OutlineSize"); - //Attr usingHatchStyle = doc.createAttribute("UsingHatchStyle"); - //style = doc.createAttribute("Style"); - Attr backColor = doc.createAttribute("BackColor"); - //Attr transparencyPer = doc.createAttribute("TransparencyPercent"); - Attr isMaskout = doc.createAttribute("IsMaskout"); - - //legendType.InnerText = "PolygonBreak"; - outlineColor.setValue(ColorUtil.toHexEncoding(aPGB.getOutlineColor())); - drawOutline.setValue(String.valueOf(aPGB.isDrawOutline())); - drawFill.setValue(String.valueOf(aPGB.isDrawFill())); - outlineSize.setValue(String.valueOf(aPGB.getOutlineSize())); - //usingHatchStyle.setValue(String.valueOf(aPGB.getUsingHatchStyle())); - //style.setValue(String.valueOf(aPGB.getStyle())); - backColor.setValue(ColorUtil.toHexEncoding(aPGB.getBackColor())); - //transparencyPer.InnerText = aPGB.TransparencyPercent.ToString(); - isMaskout.setValue(String.valueOf(aPGB.isMaskout())); - - legend.setAttributeNode(legendType); - legend.setAttributeNode(outlineColor); - legend.setAttributeNode(drawOutline); - legend.setAttributeNode(drawFill); - legend.setAttributeNode(outlineSize); - //legend.setAttributeNode(usingHatchStyle); - //legend.setAttributeNode(style); - legend.setAttributeNode(backColor); - //legend.setAttributeNode(transparencyPer); - legend.setAttributeNode(isMaskout); - break; - } - - parent.appendChild(legend); - } - - /** - * Import from xml node - * - * @param graphicNode Graphic xml node - */ - public void importFromXML(Element graphicNode) { - Node shape = graphicNode.getElementsByTagName("Shape").item(0); - _shape = loadShape(shape); - - Node legend = graphicNode.getElementsByTagName("Legend").item(0); - _legend = loadLegend(legend, _shape.getShapeType()); - - updateResizeAbility(); - } - - protected Shape loadShape(Node shapeNode) { - Shape aShape = null; - try { - ShapeTypes shapeType = ShapeTypes.valueOf(shapeNode.getAttributes().getNamedItem("ShapeType").getNodeValue()); - switch (shapeType) { - case Point: - aShape = new PointShape(); - break; - case WindArraw: - aShape = new WindArrow(); - break; - case Polyline: - aShape = new PolylineShape(); - break; - case CurveLine: - aShape = new CurveLineShape(); - break; - case Circle: - aShape = new CircleShape(); - break; - case Polygon: - case Rectangle: - aShape = new PolygonShape(); - break; - case CurvePolygon: - aShape = new CurvePolygonShape(); - break; - case Ellipse: - aShape = new EllipseShape(); - break; - } - - aShape.setVisible(Boolean.parseBoolean(shapeNode.getAttributes().getNamedItem("Visible").getNodeValue())); - aShape.setSelected(Boolean.parseBoolean(shapeNode.getAttributes().getNamedItem("Selected").getNodeValue())); - if (aShape.getShapeType() == ShapeTypes.Ellipse){ - Node angleNode = shapeNode.getAttributes().getNamedItem("Angle"); - if (angleNode != null) - ((EllipseShape)aShape).setAngle(Float.parseFloat(angleNode.getNodeValue())); - } - - List pointList = new ArrayList<>(); - Node pointsNode = ((Element)shapeNode).getElementsByTagName("Points").item(0); - NodeList nl = ((Element)pointsNode).getElementsByTagName("Point"); - for (int i = 0; i < nl.getLength(); i++) { - Node pNode = nl.item(i); - PointD aPoint = new PointD(Double.parseDouble(pNode.getAttributes().getNamedItem("X").getNodeValue()), - Double.parseDouble(pNode.getAttributes().getNamedItem("Y").getNodeValue())); - pointList.add(aPoint); - } - aShape.setPoints(pointList); - } catch (Exception e) { - } - - return aShape; - } - - protected ColorBreak loadLegend(Node legendNode, ShapeTypes shapeType) { - ColorBreak legend = new ColorBreak(); - try { - Color color = ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("Color").getNodeValue()); - String legendType = legendNode.getAttributes().getNamedItem("LegendType").getNodeValue(); - BreakTypes breakType = BreakTypes.valueOf(legendType); - switch (breakType) { - case PointBreak: - PointBreak aPB = new PointBreak(); - try { - aPB.setColor(color); - aPB.setDrawFill(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawFill").getNodeValue())); - aPB.setDrawOutline(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawOutline").getNodeValue())); - aPB.setOutlineColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("OutlineColor").getNodeValue())); - aPB.setSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("Size").getNodeValue())); - aPB.setStyle(PointStyle.valueOf(legendNode.getAttributes().getNamedItem("Style").getNodeValue())); - aPB.setMarkerType(MarkerType.valueOf(legendNode.getAttributes().getNamedItem("MarkerType").getNodeValue())); - aPB.setFontName(legendNode.getAttributes().getNamedItem("FontName").getNodeValue()); - aPB.setCharIndex(Integer.parseInt(legendNode.getAttributes().getNamedItem("CharIndex").getNodeValue())); - aPB.setImagePath(legendNode.getAttributes().getNamedItem("ImagePath").getNodeValue()); - aPB.setAngle(Float.parseFloat(legendNode.getAttributes().getNamedItem("Angle").getNodeValue())); - } catch (Exception e) { - } finally { - legend = aPB; - } - break; - case LabelBreak: - LabelBreak aLB = new LabelBreak(); - try { - aLB.setColor(color); - aLB.setAngle(Float.parseFloat(legendNode.getAttributes().getNamedItem("Angle").getNodeValue())); - aLB.setText(legendNode.getAttributes().getNamedItem("Text").getNodeValue()); - String fontName = legendNode.getAttributes().getNamedItem("FontName").getNodeValue(); - float fontSize = Float.parseFloat(legendNode.getAttributes().getNamedItem("FontSize").getNodeValue()); - boolean fontBold = Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("FontBold").getNodeValue()); - if (fontBold) { - aLB.setFont(new Font(fontName, Font.BOLD, (int) fontSize)); - } else { - aLB.setFont(new Font(fontName, Font.PLAIN, (int) fontSize)); - } - - aLB.setYShift(Float.parseFloat(legendNode.getAttributes().getNamedItem("YShift").getNodeValue())); - } catch (Exception e) { - } finally { - legend = aLB; - } - break; - case ChartBreak: - ChartBreak aChB = new ChartBreak(ChartTypes.BarChart); - try { - ChartTypes chartType = ChartTypes.valueOf(legendNode.getAttributes().getNamedItem("ChartType").getNodeValue()); - aChB = new ChartBreak(chartType); - aChB.setShapeIndex(Integer.parseInt(legendNode.getAttributes().getNamedItem("ShapeIndex").getNodeValue())); - List cData = new ArrayList(); - String[] cDataStr = legendNode.getAttributes().getNamedItem("ChartData").getNodeValue().split(","); - for (int i = 0; i < cDataStr.length; i++) { - cData.add(Float.parseFloat(cDataStr[i])); - } - - aChB.setChartData(cData); - aChB.setXShift(Integer.parseInt(legendNode.getAttributes().getNamedItem("XShift").getNodeValue())); - aChB.setYShift(Integer.parseInt(legendNode.getAttributes().getNamedItem("YShift").getNodeValue())); - String fontName = legendNode.getAttributes().getNamedItem("FontName").getNodeValue(); - float fontSize = Float.parseFloat(legendNode.getAttributes().getNamedItem("FontSize").getNodeValue()); - aChB.setLabelFont(new Font(fontName, Font.PLAIN, (int)fontSize)); - aChB.setLabelColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("LabelColor").getNodeValue())); - } catch (Exception e) { - } finally { - legend = aChB; - } - break; - case VectorBreak: - VectorBreak aVB = new VectorBreak(); - try { - aVB.setColor(color); - } catch (Exception e) { - } finally { - legend = aVB; - } - break; - case PolylineBreak: - PolylineBreak aPLB = new PolylineBreak(); - try { - aPLB.setColor(color); - aPLB.setWidth(Float.parseFloat(legendNode.getAttributes().getNamedItem("Size").getNodeValue())); - aPLB.setStyle(LineStyles.valueOf(legendNode.getAttributes().getNamedItem("Style").getNodeValue())); - aPLB.setDrawSymbol(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawSymbol").getNodeValue())); - aPLB.setSymbolSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("SymbolSize").getNodeValue())); - aPLB.setSymbolStyle(PointStyle.valueOf(legendNode.getAttributes().getNamedItem("SymbolStyle").getNodeValue())); - aPLB.setSymbolColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("SymbolColor").getNodeValue())); - aPLB.setSymbolInterval(Integer.parseInt(legendNode.getAttributes().getNamedItem("SymbolInterval").getNodeValue())); - } catch (Exception e) { - } finally { - legend = aPLB; - } - break; - case PolygonBreak: - PolygonBreak aPGB = new PolygonBreak(); - try { - aPGB.setColor(color); - aPGB.setDrawFill(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawFill").getNodeValue())); - aPGB.setDrawOutline(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawOutline").getNodeValue())); - aPGB.setOutlineSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("OutlineSize").getNodeValue())); - aPGB.setOutlineColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("OutlineColor").getNodeValue())); - //aPGB.UsingHatchStyle = bool.Parse(legendNode.Attributes["UsingHatchStyle"].InnerText); - //aPGB.Style = (HatchStyle)Enum.Parse(typeof(HatchStyle), legendNode.Attributes["Style"].InnerText, true); - aPGB.setBackColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("BackColor").getNodeValue())); - //aPGB.TransparencyPercent = int.Parse(legendNode.Attributes["TransparencyPercent"].InnerText); - aPGB.setMaskout(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("IsMaskout").getNodeValue())); - } catch (Exception e) { - } { - legend = aPGB; - } - break; - } - } catch (Exception e) { - } - return legend; - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.legend.MarkerType; +import org.meteoinfo.legend.PointStyle; +import org.meteoinfo.global.colors.ColorUtil; +import org.meteoinfo.layout.ResizeAbility; +import org.meteoinfo.legend.BreakTypes; +import org.meteoinfo.legend.ChartBreak; +import org.meteoinfo.legend.ChartTypes; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.LabelBreak; +import org.meteoinfo.legend.LineStyles; +import org.meteoinfo.legend.PointBreak; +import org.meteoinfo.legend.PolygonBreak; +import org.meteoinfo.legend.PolylineBreak; +import org.meteoinfo.legend.VectorBreak; +import java.awt.Color; +import java.awt.Font; +import java.util.ArrayList; +import java.util.List; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Graphic class + * + * @author Yaqiang Wang + */ +public class Graphic { + // + + private Shape _shape = null; + private ColorBreak _legend = null; + private ResizeAbility _resizeAbility = ResizeAbility.ResizeAll; + // + // + + /** + * Constructor + */ + public Graphic() { + } + + /** + * Constructor + * + * @param shape a shape + * @param legend a legend + */ + public Graphic(Shape shape, ColorBreak legend) { + _shape = shape; + _legend = legend; + updateResizeAbility(); + } + // + // + + /** + * Get shape + * + * @return Shape + */ + public Shape getShape() { + return _shape; + } + + /** + * Set shape + * + * @param aShape a shape + */ + public void setShape(Shape aShape) { + _shape = aShape; + updateResizeAbility(); + } + + /** + * Get legend + * + * @return Legend + */ + public ColorBreak getLegend() { + return _legend; + } + + public void setLegend(ColorBreak legend) { + _legend = legend; + updateResizeAbility(); + updateResizeAbility(); + } + + /** + * Get resize ability + * + * @return Resize ability + */ + public ResizeAbility getResizeAbility() { + return _resizeAbility; + } + + /** + * Get extent + * + * @return The extent + */ + public Extent getExtent() { + return this._shape.getExtent(); + } + + /** + * Set extent + * @param value The extent + */ + public void setExtent(Extent value){ + this._shape.setExtent(value); + } + + /** + * Get is single legend or not + * @return Boolean + */ + public boolean isSingleLegend(){ + return true; + } + + /** + * Get if is GraphicCollection + * @return Boolean + */ + public boolean isCollection(){ + return false; + } + + // + // + /** + * Get graphics number + * @return 1 + */ + public int getNumGraphics(){ + return 1; + } + + /** + * Get Graphic by index + * @param idx Index + * @return Graphic + */ + public Graphic getGraphicN(int idx){ + return this; + } + + /** + * Get graphic list + * @return Graphic list + */ + public List getGraphics(){ + List gs = new ArrayList<>(); + gs.add(this); + return gs; + } + + private void updateResizeAbility() { + if (_shape != null && _legend != null) { + switch (_shape.getShapeType()) { + case Point: + switch (_legend.getBreakType()) { + case PointBreak: + _resizeAbility = ResizeAbility.SameWidthHeight; + break; + case LabelBreak: + case ChartBreak: + _resizeAbility = ResizeAbility.None; + break; + } + break; + case Circle: + _resizeAbility = ResizeAbility.SameWidthHeight; + break; + default: + _resizeAbility = ResizeAbility.ResizeAll; + break; + } + } + } + + /** + * Vertice edited update + * + * @param vIdx Vertice index + * @param newX New X + * @param newY New Y + */ + public void verticeMoveUpdate(int vIdx, double newX, double newY) { + List points = (List)_shape.getPoints(); + switch (_shape.getShapeType()){ + case Polygon: + case CurvePolygon: + case Rectangle: + int last = points.size() - 1; + if (vIdx == 0) { + if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { + points.get(last).X = newX; + points.get(last).Y = newY; + } + } else if (vIdx == last){ + if (points.get(0).X == points.get(last).X && points.get(0).Y == points.get(last).Y) { + points.get(0).X = newX; + points.get(0).Y = newY; + } + } + break; + } + + PointD aP = points.get(vIdx); + aP.X = newX; + aP.Y = newY; + //points.set(vIdx, aP); + _shape.setPoints(points); + } + + /** + * Vertice edited update + * + * @param vIdx Vertice index + * @param point The add vertice + */ + public void verticeAddUpdate(int vIdx, PointD point) { + List points = (List)_shape.getPoints(); + points.add(vIdx, point); + _shape.setPoints(points); + } + + /** + * Vertice edited update + * + * @param vIdx Vertice index + */ + public void verticeRemoveUpdate(int vIdx) { + List points = (List)_shape.getPoints(); + points.remove(vIdx); + _shape.setPoints(points); + } + + /** + * Export to XML document + * @param doc XML document + * @param parent Parent XML element + */ + public void exportToXML(Document doc, Element parent) { + Element graphic = doc.createElement("Graphic"); + addShape(doc, graphic, _shape); + addLegend(doc, graphic, _legend, _shape.getShapeType()); + + parent.appendChild(graphic); + } + + /** + * Add shape to XML document + * @param doc XML document + * @param parent Parent XML element + * @param aShape The shape + */ + protected void addShape(Document doc, Element parent, Shape aShape) { + Element shape = doc.createElement("Shape"); + boolean hasAngle = aShape.getShapeType() == ShapeTypes.Ellipse; + + //Add general attribute + Attr shapeType = doc.createAttribute("ShapeType"); + Attr visible = doc.createAttribute("Visible"); + Attr selected = doc.createAttribute("Selected"); + + //shapeType.InnerText = Enum.GetName(typeof(ShapeTypes), aShape.ShapeType); + shapeType.setValue(aShape.getShapeType().toString()); + visible.setValue(String.valueOf(aShape.isVisible())); + selected.setValue(String.valueOf(aShape.isSelected())); + + shape.setAttributeNode(shapeType); + shape.setAttributeNode(visible); + shape.setAttributeNode(selected); + + if (hasAngle){ + Attr angle = doc.createAttribute("Angle"); + angle.setValue(String.valueOf(((EllipseShape)aShape).getAngle())); + shape.setAttributeNode(angle); + } + + //Add points + Element points = doc.createElement("Points"); + List pointList = (List)aShape.getPoints(); + for (PointD aPoint : pointList) { + Element point = doc.createElement("Point"); + Attr x = doc.createAttribute("X"); + Attr y = doc.createAttribute("Y"); + x.setValue(String.valueOf(aPoint.X)); + y.setValue(String.valueOf(aPoint.Y)); + point.setAttributeNode(x); + point.setAttributeNode(y); + + points.appendChild(point); + } + + shape.appendChild(points); + + parent.appendChild(shape); + } + + /** + * Add legend to XML document + * @param doc XML document + * @param parent Parent XML element + * @param aLegend The legend + * @param shapeType The shape type + */ + protected void addLegend(Document doc, Element parent, ColorBreak aLegend, ShapeTypes shapeType) { + Element legend = doc.createElement("Legend"); + Attr color = doc.createAttribute("Color"); + color.setValue(ColorUtil.toHexEncoding(aLegend.getColor())); + legend.setAttributeNode(color); + + Attr legendType = doc.createAttribute("LegendType"); + Attr size; + Attr style; + Attr outlineColor; + Attr drawOutline; + Attr drawFill; + legendType.setValue(aLegend.getBreakType().toString()); + switch (aLegend.getBreakType()) { + case PointBreak: + PointBreak aPB = (PointBreak) aLegend; + outlineColor = doc.createAttribute("OutlineColor"); + size = doc.createAttribute("Size"); + style = doc.createAttribute("Style"); + drawOutline = doc.createAttribute("DrawOutline"); + drawFill = doc.createAttribute("DrawFill"); + Attr markerType = doc.createAttribute("MarkerType"); + Attr fontName = doc.createAttribute("FontName"); + Attr charIndex = doc.createAttribute("CharIndex"); + Attr imagePath = doc.createAttribute("ImagePath"); + Attr angle = doc.createAttribute("Angle"); + + //legendType.InnerText = "PointBreak"; + outlineColor.setValue(ColorUtil.toHexEncoding(aPB.getOutlineColor())); + size.setValue(String.valueOf(aPB.getSize())); + style.setValue(aPB.getStyle().toString()); + drawOutline.setValue(String.valueOf(aPB.isDrawOutline())); + drawFill.setValue(String.valueOf(aPB.isDrawFill())); + markerType.setValue(aPB.getMarkerType().toString()); + fontName.setValue(aPB.getFontName()); + charIndex.setValue(String.valueOf(aPB.getCharIndex())); + imagePath.setValue(aPB.getImagePath()); + angle.setValue(String.valueOf(aPB.getAngle())); + + legend.setAttributeNode(legendType); + legend.setAttributeNode(outlineColor); + legend.setAttributeNode(size); + legend.setAttributeNode(style); + legend.setAttributeNode(drawOutline); + legend.setAttributeNode(drawFill); + legend.setAttributeNode(markerType); + legend.setAttributeNode(fontName); + legend.setAttributeNode(charIndex); + legend.setAttributeNode(imagePath); + legend.setAttributeNode(angle); + break; + case LabelBreak: + LabelBreak aLB = (LabelBreak) aLegend; + Attr text = doc.createAttribute("Text"); + angle = doc.createAttribute("Angle"); + fontName = doc.createAttribute("FontName"); + Attr fontSize = doc.createAttribute("FontSize"); + Attr fontBold = doc.createAttribute("FontBold"); + Attr yShift = doc.createAttribute("YShift"); + + //legendType.InnerText = "LabelBreak"; + text.setValue(aLB.getText()); + angle.setValue(String.valueOf(aLB.getAngle())); + fontName.setValue(aLB.getFont().getName()); + fontSize.setValue(String.valueOf(aLB.getFont().getSize())); + fontBold.setValue(String.valueOf(aLB.getFont().isBold())); + yShift.setValue(String.valueOf(aLB.getYShift())); + + legend.setAttributeNode(legendType); + legend.setAttributeNode(text); + legend.setAttributeNode(angle); + legend.setAttributeNode(fontName); + legend.setAttributeNode(fontSize); + legend.setAttributeNode(fontBold); + legend.setAttributeNode(yShift); + break; + case ChartBreak: + ChartBreak aChB = (ChartBreak) aLegend; + Attr shapeIndex = doc.createAttribute("ShapeIndex"); + Attr chartType = doc.createAttribute("ChartType"); + Attr chartData = doc.createAttribute("ChartData"); + Attr xShift = doc.createAttribute("XShift"); + yShift = doc.createAttribute("YShift"); + fontName = doc.createAttribute("FontName"); + fontSize = doc.createAttribute("FontSize"); + Attr labelColor = doc.createAttribute("LabelColor"); + + shapeIndex.setValue(String.valueOf(aChB.getShapeIndex())); + //legendType.InnerText = "ChartBreak"; + chartType.setValue(aChB.getChartType().toString()); + String cdata = ""; + for (int i = 0; i < aChB.getItemNum(); i++) { + if (i == 0) { + cdata = String.valueOf(aChB.getChartData().get(i)); + } else { + cdata += "," + String.valueOf(aChB.getChartData().get(i)); + } + } + chartData.setValue(cdata); + xShift.setValue(String.valueOf(aChB.getXShift())); + yShift.setValue(String.valueOf(aChB.getYShift())); + fontName.setValue(aChB.getLabelFont().getFontName()); + fontSize.setValue(String.valueOf(aChB.getLabelFont().getSize())); + labelColor.setValue(ColorUtil.toHexEncoding(aChB.getLabelColor())); + + legend.setAttributeNode(legendType); + legend.setAttributeNode(shapeIndex); + legend.setAttributeNode(chartType); + legend.setAttributeNode(chartData); + legend.setAttributeNode(xShift); + legend.setAttributeNode(yShift); + legend.setAttributeNode(fontName); + legend.setAttributeNode(fontSize); + legend.setAttributeNode(labelColor); + break; + case VectorBreak: + //legendType.InnerText = "VectorBreak"; + legend.setAttributeNode(legendType); + break; + case PolylineBreak: + PolylineBreak aPLB = (PolylineBreak) aLegend; + size = doc.createAttribute("Size"); + style = doc.createAttribute("Style"); + Attr drawSymbol = doc.createAttribute("DrawSymbol"); + Attr symbolSize = doc.createAttribute("SymbolSize"); + Attr symbolStyle = doc.createAttribute("SymbolStyle"); + Attr symbolColor = doc.createAttribute("SymbolColor"); + Attr symbolInterval = doc.createAttribute("SymbolInterval"); + + //legendType.InnerText = "PolylineBreak"; + size.setValue(String.valueOf(aPLB.getWidth())); + style.setValue(aPLB.getStyle().toString()); + drawSymbol.setValue(String.valueOf(aPLB.getDrawSymbol())); + symbolSize.setValue(String.valueOf(aPLB.getSymbolSize())); + symbolStyle.setValue(String.valueOf(aPLB.getSymbolStyle())); + symbolColor.setValue(ColorUtil.toHexEncoding(aPLB.getSymbolColor())); + symbolInterval.setValue(String.valueOf(aPLB.getSymbolInterval())); + + legend.setAttributeNode(legendType); + legend.setAttributeNode(size); + legend.setAttributeNode(style); + legend.setAttributeNode(drawSymbol); + legend.setAttributeNode(symbolSize); + legend.setAttributeNode(symbolStyle); + legend.setAttributeNode(symbolColor); + legend.setAttributeNode(symbolInterval); + break; + case PolygonBreak: + PolygonBreak aPGB = (PolygonBreak) aLegend; + outlineColor = doc.createAttribute("OutlineColor"); + drawOutline = doc.createAttribute("DrawOutline"); + drawFill = doc.createAttribute("DrawFill"); + Attr outlineSize = doc.createAttribute("OutlineSize"); + //Attr usingHatchStyle = doc.createAttribute("UsingHatchStyle"); + //style = doc.createAttribute("Style"); + Attr backColor = doc.createAttribute("BackColor"); + //Attr transparencyPer = doc.createAttribute("TransparencyPercent"); + Attr isMaskout = doc.createAttribute("IsMaskout"); + + //legendType.InnerText = "PolygonBreak"; + outlineColor.setValue(ColorUtil.toHexEncoding(aPGB.getOutlineColor())); + drawOutline.setValue(String.valueOf(aPGB.isDrawOutline())); + drawFill.setValue(String.valueOf(aPGB.isDrawFill())); + outlineSize.setValue(String.valueOf(aPGB.getOutlineSize())); + //usingHatchStyle.setValue(String.valueOf(aPGB.getUsingHatchStyle())); + //style.setValue(String.valueOf(aPGB.getStyle())); + backColor.setValue(ColorUtil.toHexEncoding(aPGB.getBackColor())); + //transparencyPer.InnerText = aPGB.TransparencyPercent.ToString(); + isMaskout.setValue(String.valueOf(aPGB.isMaskout())); + + legend.setAttributeNode(legendType); + legend.setAttributeNode(outlineColor); + legend.setAttributeNode(drawOutline); + legend.setAttributeNode(drawFill); + legend.setAttributeNode(outlineSize); + //legend.setAttributeNode(usingHatchStyle); + //legend.setAttributeNode(style); + legend.setAttributeNode(backColor); + //legend.setAttributeNode(transparencyPer); + legend.setAttributeNode(isMaskout); + break; + } + + parent.appendChild(legend); + } + + /** + * Import from xml node + * + * @param graphicNode Graphic xml node + */ + public void importFromXML(Element graphicNode) { + Node shape = graphicNode.getElementsByTagName("Shape").item(0); + _shape = loadShape(shape); + + Node legend = graphicNode.getElementsByTagName("Legend").item(0); + _legend = loadLegend(legend, _shape.getShapeType()); + + updateResizeAbility(); + } + + protected Shape loadShape(Node shapeNode) { + Shape aShape = null; + try { + ShapeTypes shapeType = ShapeTypes.valueOf(shapeNode.getAttributes().getNamedItem("ShapeType").getNodeValue()); + switch (shapeType) { + case Point: + aShape = new PointShape(); + break; + case WindArraw: + aShape = new WindArrow(); + break; + case Polyline: + aShape = new PolylineShape(); + break; + case CurveLine: + aShape = new CurveLineShape(); + break; + case Circle: + aShape = new CircleShape(); + break; + case Polygon: + case Rectangle: + aShape = new PolygonShape(); + break; + case CurvePolygon: + aShape = new CurvePolygonShape(); + break; + case Ellipse: + aShape = new EllipseShape(); + break; + } + + aShape.setVisible(Boolean.parseBoolean(shapeNode.getAttributes().getNamedItem("Visible").getNodeValue())); + aShape.setSelected(Boolean.parseBoolean(shapeNode.getAttributes().getNamedItem("Selected").getNodeValue())); + if (aShape.getShapeType() == ShapeTypes.Ellipse){ + Node angleNode = shapeNode.getAttributes().getNamedItem("Angle"); + if (angleNode != null) + ((EllipseShape)aShape).setAngle(Float.parseFloat(angleNode.getNodeValue())); + } + + List pointList = new ArrayList<>(); + Node pointsNode = ((Element)shapeNode).getElementsByTagName("Points").item(0); + NodeList nl = ((Element)pointsNode).getElementsByTagName("Point"); + for (int i = 0; i < nl.getLength(); i++) { + Node pNode = nl.item(i); + PointD aPoint = new PointD(Double.parseDouble(pNode.getAttributes().getNamedItem("X").getNodeValue()), + Double.parseDouble(pNode.getAttributes().getNamedItem("Y").getNodeValue())); + pointList.add(aPoint); + } + aShape.setPoints(pointList); + } catch (Exception e) { + } + + return aShape; + } + + protected ColorBreak loadLegend(Node legendNode, ShapeTypes shapeType) { + ColorBreak legend = new ColorBreak(); + try { + Color color = ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("Color").getNodeValue()); + String legendType = legendNode.getAttributes().getNamedItem("LegendType").getNodeValue(); + BreakTypes breakType = BreakTypes.valueOf(legendType); + switch (breakType) { + case PointBreak: + PointBreak aPB = new PointBreak(); + try { + aPB.setColor(color); + aPB.setDrawFill(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawFill").getNodeValue())); + aPB.setDrawOutline(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawOutline").getNodeValue())); + aPB.setOutlineColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("OutlineColor").getNodeValue())); + aPB.setSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("Size").getNodeValue())); + aPB.setStyle(PointStyle.valueOf(legendNode.getAttributes().getNamedItem("Style").getNodeValue())); + aPB.setMarkerType(MarkerType.valueOf(legendNode.getAttributes().getNamedItem("MarkerType").getNodeValue())); + aPB.setFontName(legendNode.getAttributes().getNamedItem("FontName").getNodeValue()); + aPB.setCharIndex(Integer.parseInt(legendNode.getAttributes().getNamedItem("CharIndex").getNodeValue())); + aPB.setImagePath(legendNode.getAttributes().getNamedItem("ImagePath").getNodeValue()); + aPB.setAngle(Float.parseFloat(legendNode.getAttributes().getNamedItem("Angle").getNodeValue())); + } catch (Exception e) { + } finally { + legend = aPB; + } + break; + case LabelBreak: + LabelBreak aLB = new LabelBreak(); + try { + aLB.setColor(color); + aLB.setAngle(Float.parseFloat(legendNode.getAttributes().getNamedItem("Angle").getNodeValue())); + aLB.setText(legendNode.getAttributes().getNamedItem("Text").getNodeValue()); + String fontName = legendNode.getAttributes().getNamedItem("FontName").getNodeValue(); + float fontSize = Float.parseFloat(legendNode.getAttributes().getNamedItem("FontSize").getNodeValue()); + boolean fontBold = Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("FontBold").getNodeValue()); + if (fontBold) { + aLB.setFont(new Font(fontName, Font.BOLD, (int) fontSize)); + } else { + aLB.setFont(new Font(fontName, Font.PLAIN, (int) fontSize)); + } + + aLB.setYShift(Float.parseFloat(legendNode.getAttributes().getNamedItem("YShift").getNodeValue())); + } catch (Exception e) { + } finally { + legend = aLB; + } + break; + case ChartBreak: + ChartBreak aChB = new ChartBreak(ChartTypes.BarChart); + try { + ChartTypes chartType = ChartTypes.valueOf(legendNode.getAttributes().getNamedItem("ChartType").getNodeValue()); + aChB = new ChartBreak(chartType); + aChB.setShapeIndex(Integer.parseInt(legendNode.getAttributes().getNamedItem("ShapeIndex").getNodeValue())); + List cData = new ArrayList(); + String[] cDataStr = legendNode.getAttributes().getNamedItem("ChartData").getNodeValue().split(","); + for (int i = 0; i < cDataStr.length; i++) { + cData.add(Float.parseFloat(cDataStr[i])); + } + + aChB.setChartData(cData); + aChB.setXShift(Integer.parseInt(legendNode.getAttributes().getNamedItem("XShift").getNodeValue())); + aChB.setYShift(Integer.parseInt(legendNode.getAttributes().getNamedItem("YShift").getNodeValue())); + String fontName = legendNode.getAttributes().getNamedItem("FontName").getNodeValue(); + float fontSize = Float.parseFloat(legendNode.getAttributes().getNamedItem("FontSize").getNodeValue()); + aChB.setLabelFont(new Font(fontName, Font.PLAIN, (int)fontSize)); + aChB.setLabelColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("LabelColor").getNodeValue())); + } catch (Exception e) { + } finally { + legend = aChB; + } + break; + case VectorBreak: + VectorBreak aVB = new VectorBreak(); + try { + aVB.setColor(color); + } catch (Exception e) { + } finally { + legend = aVB; + } + break; + case PolylineBreak: + PolylineBreak aPLB = new PolylineBreak(); + try { + aPLB.setColor(color); + aPLB.setWidth(Float.parseFloat(legendNode.getAttributes().getNamedItem("Size").getNodeValue())); + aPLB.setStyle(LineStyles.valueOf(legendNode.getAttributes().getNamedItem("Style").getNodeValue())); + aPLB.setDrawSymbol(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawSymbol").getNodeValue())); + aPLB.setSymbolSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("SymbolSize").getNodeValue())); + aPLB.setSymbolStyle(PointStyle.valueOf(legendNode.getAttributes().getNamedItem("SymbolStyle").getNodeValue())); + aPLB.setSymbolColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("SymbolColor").getNodeValue())); + aPLB.setSymbolInterval(Integer.parseInt(legendNode.getAttributes().getNamedItem("SymbolInterval").getNodeValue())); + } catch (Exception e) { + } finally { + legend = aPLB; + } + break; + case PolygonBreak: + PolygonBreak aPGB = new PolygonBreak(); + try { + aPGB.setColor(color); + aPGB.setDrawFill(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawFill").getNodeValue())); + aPGB.setDrawOutline(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("DrawOutline").getNodeValue())); + aPGB.setOutlineSize(Float.parseFloat(legendNode.getAttributes().getNamedItem("OutlineSize").getNodeValue())); + aPGB.setOutlineColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("OutlineColor").getNodeValue())); + //aPGB.UsingHatchStyle = bool.Parse(legendNode.Attributes["UsingHatchStyle"].InnerText); + //aPGB.Style = (HatchStyle)Enum.Parse(typeof(HatchStyle), legendNode.Attributes["Style"].InnerText, true); + aPGB.setBackColor(ColorUtil.parseToColor(legendNode.getAttributes().getNamedItem("BackColor").getNodeValue())); + //aPGB.TransparencyPercent = int.Parse(legendNode.Attributes["TransparencyPercent"].InnerText); + aPGB.setMaskout(Boolean.parseBoolean(legendNode.getAttributes().getNamedItem("IsMaskout").getNodeValue())); + } catch (Exception e) { + } { + legend = aPGB; + } + break; + } + } catch (Exception e) { + } + return legend; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/GraphicCollection.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/GraphicCollection.java index 0cdfa515..292f482a 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/GraphicCollection.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/GraphicCollection.java @@ -1,688 +1,689 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import org.meteoinfo.layer.LabelSet; -import org.meteoinfo.legend.BreakTypes; -import org.meteoinfo.legend.ColorBreak; -import org.meteoinfo.legend.LabelBreak; -import org.meteoinfo.legend.LegendScheme; -import org.meteoinfo.legend.PointBreak; - -/** - * - * @author Yaqiang Wang - */ -public class GraphicCollection extends Graphic implements Iterator { - - // - private List graphics = new ArrayList<>(); - private Extent _extent = new Extent(); - protected boolean singleLegend = true; - private int index; - private LabelSet labelSet; - private List labelPoints; - protected LegendScheme legendScheme; - protected ColorBreak legendBreak; - // - // - - /** - * Constructor - */ - public GraphicCollection() { - this.index = 0; - labelSet = new LabelSet(); - labelPoints = new ArrayList<>(); - } - - // - // - /** - * Get graphic list - * - * @return Graphic list - */ - @Override - public List getGraphics() { - return this.graphics; - } - - /** - * Set graphic list - * - * @param value Graphic list - */ - public void setGraphics(List value) { - this.graphics = value; - } - - /** - * Get extent - * - * @return The extent - */ - @Override - public Extent getExtent() { - return _extent; - } - - /** - * Set extent - * - * @param value Extent - */ - @Override - public void setExtent(Extent value) { - this._extent = value; - } - - /** - * Get is single legend or not - * - * @return Boolean - */ - @Override - public boolean isSingleLegend() { - return this.singleLegend; - } - - /** - * Set is single legend or not - * - * @param value Boolean - */ - public void setSingleLegend(boolean value) { - this.singleLegend = value; - } - - /** - * Get label set - * - * @return Label set - */ - public LabelSet getLabelSet() { - return labelSet; - } - - /** - * Set label set - * - * @param ls Label set - */ - public void setLabelSet(LabelSet ls) { - labelSet = ls; - } - - /** - * Get label points - * - * @return The lable points - */ - public List getLabelPoints() { - return this.labelPoints; - } - - /** - * Set label points - * - * @param lps The lable points - */ - public void setLabelPoints(List lps) { - this.labelPoints = lps; - } - - /** - * Get legend scheme - * - * @return Legend scheme - */ - public LegendScheme getLegendScheme() { - return this.legendScheme; - } - - /** - * Set legend scheme - * - * @param value Legend scheme - */ - public void setLegendScheme(LegendScheme value) { - this.legendScheme = value; - } - - /** - * Get legend break - * - * @return Legend break - */ - public ColorBreak getLegendBreak() { - return this.legendBreak; - } - - /** - * Set legend break - * - * @param value Legend break - */ - public void setLegendBreak(ColorBreak value) { - this.legendBreak = value; - } - - /** - * Get is 3D or not - * - * @return Boolean - */ - public boolean is3D() { - return false; - } - - /** - * Get if is GraphicCollection - * - * @return Boolean - */ - @Override - public boolean isCollection() { - return true; - } - - // - // - /** - * Update extent - */ - public void updateExtent() { - int i = 0; - Extent extent; - for (Graphic g : this.graphics) { - if (g instanceof GraphicCollection) { - extent = g.getExtent(); - } else { - extent = g.getShape().getExtent(); - } - if (i == 0) { - _extent = extent; - } else { - _extent = MIMath.getLagerExtent(_extent, extent); - } - - i += 1; - } - } - - /** - * Add a graphic - * - * @param aGraphic The graphic - * @return Boolean - */ - public boolean add(Graphic aGraphic) { - boolean istrue = this.graphics.add(aGraphic); - - //Update extent - if (this.graphics.size() == 1) { - _extent = aGraphic.getExtent(); - } else { - _extent = MIMath.getLagerExtent(_extent, aGraphic.getExtent()); - } - - return istrue; - } - - /** - * Inset a graphic - * - * @param index Index - * @param aGraphic The graphic - */ - public void add(int index, Graphic aGraphic) { - this.graphics.add(index, aGraphic); - - //Update extent - if (this.graphics.size() == 1) { - _extent = aGraphic.getShape().getExtent(); - } else { - _extent = MIMath.getLagerExtent(_extent, aGraphic.getShape().getExtent()); - } - } - - /** - * Get a graphic by index - * - * @param idx Index - * @return Graphic - */ - public Graphic get(int idx) { - return this.graphics.get(idx); - } - - /** - * Index of - * - * @param g Graphic - * @return Index - */ - public int indexOf(Graphic g) { - return this.graphics.indexOf(g); - } - - /** - * Contains or not - * - * @param g Graphic - * @return Boolean - */ - public boolean contains(Graphic g) { - return this.graphics.contains(g); - } - - /** - * Get graphic list size - * - * @return Gaphic list size - */ - public int size() { - return this.graphics.size(); - } - - /** - * Get is empty or not - * - * @return Boolean - */ - public boolean isEmpty() { - return this.graphics.isEmpty(); - } - - /** - * Get graphics number - * - * @return 1 - */ - @Override - public int getNumGraphics() { - return this.size(); - } - - /** - * Get Graphic by index - * - * @param idx Index - * @return Graphic - */ - @Override - public Graphic getGraphicN(int idx) { - return this.get(idx); - } - - /** - * Remove a graphic - * - * @param aGraphic The graphic - * @return Boolean - */ - public boolean remove(Graphic aGraphic) { - boolean istrue = this.graphics.remove(aGraphic); - this.updateExtent(); - - return istrue; - } - - /** - * Remove a graphic by index - * - * @param index The index - * @return The removed graphic - */ - public Graphic remove(int index) { - Graphic ag = this.graphics.remove(index); - this.updateExtent(); - - return ag; - } - - /** - * Clear graphics - */ - public void clear() { - this.graphics.clear(); - } - - /** - * Add all - * - * @param gs Graphic list - */ - public void addAll(List gs) { - this.graphics.addAll(gs); - } - - /** - * Join this graphics with other graphics - * - * @param graphic Other graphics - */ - public void join(Graphic graphic) { - if (graphic.isCollection()) { - //Update extent - if (this.isEmpty()) { - _extent = graphic.getExtent(); - } else { - _extent = MIMath.getLagerExtent(_extent, graphic.getExtent()); - } - for (int i = 0; i < graphic.getNumGraphics(); i++) { - this.graphics.add(graphic.getGraphicN(i)); - } - } else { - this.add(graphic); - } - } - - /** - * Remove all - * - * @param gs Graphic list - */ - public void removeAll(List gs) { - this.graphics.removeAll(gs); - } - - /** - * Get legend - * - * @return Legend - */ - @Override - public ColorBreak getLegend() { - if (this.legendBreak != null) { - return this.legendBreak; - } else { - return this.graphics.get(0).getLegend(); - } - } - - /** - * Select graphics by an extent - * - * @param aExtent The extent - * @return Selected graphics - */ - public GraphicCollection selectGraphics(Extent aExtent) { - GraphicCollection selectedGraphics = new GraphicCollection(); - int i, j; - PointD aPoint = new PointD(); - aPoint.X = (aExtent.minX + aExtent.maxX) / 2; - aPoint.Y = (aExtent.minY + aExtent.maxY) / 2; - - for (Graphic aGraphic : this.graphics) { - switch (aGraphic.getShape().getShapeType()) { - case Point: - PointShape aPS = (PointShape) aGraphic.getShape(); - if (MIMath.pointInExtent(aPS.getPoint(), aExtent)) { - selectedGraphics.add(aGraphic); - } - break; - case Polyline: - case PolylineZ: - PolylineShape aPLS = (PolylineShape) aGraphic.getShape(); - if (MIMath.isExtentCross(aExtent, aPLS.getExtent())) { - for (j = 0; j < aPLS.getPoints().size(); j++) { - aPoint = aPLS.getPoints().get(j); - if (MIMath.pointInExtent(aPoint, aExtent)) { - selectedGraphics.add(aGraphic); - break; - } - } - } - break; - case Polygon: - case Rectangle: - PolygonShape aPGS = (PolygonShape) aGraphic.getShape(); - if (!(aPGS.getPartNum() > 1)) { - if (GeoComputation.pointInPolygon((List) aPGS.getPoints(), aPoint)) { - selectedGraphics.add(aGraphic); - } - } else { - for (int p = 0; p < aPGS.getPartNum(); p++) { - ArrayList pList = new ArrayList(); - if (p == aPGS.getPartNum() - 1) { - for (int pp = aPGS.parts[p]; pp < aPGS.getPointNum(); pp++) { - pList.add(aPGS.getPoints().get(pp)); - } - } else { - for (int pp = aPGS.parts[p]; pp < aPGS.parts[p + 1]; pp++) { - pList.add(aPGS.getPoints().get(pp)); - } - } - if (GeoComputation.pointInPolygon(pList, aPoint)) { - selectedGraphics.add(aGraphic); - break; - } - } - } - break; - } - } - - return selectedGraphics; - } - - @Override - public boolean hasNext() { - return index <= this.size() - 1; - } - - @Override - public Object next() { - if (index >= this.size()) { - throw new NoSuchElementException(); - } - - return this.get(index++); - } - - /** - * Add labels - */ - public void addLabels() { - addLabelsByColor(); - - labelSet.setDrawLabels(true); - } - - /** - * Get shapes - * - * @return Shapes - */ - public List getShapes() { - List shapes = new ArrayList<>(); - for (Graphic g : this.graphics) { - shapes.add(g.getShape()); - } - return shapes; - } - - /** - * Get shape type - * - * @return Shape type - */ - public ShapeTypes getShapeType() { - return this.graphics.get(0).getShape().getShapeType(); - } - - private double getMinValue() { - double min = Double.MAX_VALUE; - for (Graphic graphic : this.graphics) { - Shape shape = graphic.getShape(); - if (min > shape.getValue()) { - min = shape.getValue(); - } - } - return min; - } - - /** - * Add labels - */ - private void addLabelsByColor() { - if (labelSet.isAutoDecimal()) { - double min = getMinValue(); - labelSet.setDecimalDigits(MIMath.getDecimalNum(min)); - } - String dFormat = "%1$." + String.valueOf(labelSet.getDecimalDigits()) + "f"; - PointD aPoint; - for (Graphic graphic : this.graphics) { - ColorBreak cb = graphic.getLegend(); - Shape shape = graphic.getShape(); - PointShape aPS = new PointShape(); - switch (shape.getShapeType()) { - case Point: - case PointM: - case PointZ: - aPS.setPoint((PointD) ((PointShape) shape).getPoint().clone()); - break; - case Polyline: - case PolylineM: - case PolylineZ: - int pIdx = ((PolylineShape) shape).getPoints().size() / 2; - aPS.setPoint((PointD) ((PolylineShape) shape).getPoints().get(pIdx - 1).clone()); - break; - case Polygon: - case PolygonM: - Extent aExtent = shape.getExtent(); - aPoint = new PointD(); - aPoint.X = ((aExtent.minX + aExtent.maxX) / 2); - aPoint.Y = ((aExtent.minY + aExtent.maxY) / 2); - aPS.setPoint(aPoint); - break; - } - - LabelBreak aLP = new LabelBreak(); - //aLP.setText(DataConvert.removeTailingZeros(String.valueOf(shape.getValue()))); - aLP.setText(String.format(dFormat, shape.getValue())); - if (labelSet.isColorByLegend()) { - aLP.setColor(cb.getColor()); - } else { - aLP.setColor(labelSet.getLabelColor()); - } - aLP.setFont(labelSet.getLabelFont()); - aLP.setAlignType(labelSet.getLabelAlignType()); - aLP.setYShift(labelSet.getYOffset()); - aLP.setXShift(labelSet.getXOffset()); - Graphic aGraphic = new Graphic(aPS, aLP); - addLabel(aGraphic); - } - } - - /** - * Add label point - * - * @param aLP Label point - */ - public void addLabel(Graphic aLP) { - labelPoints.add(aLP); - } - - /** - * Add labels of contour layer dynamicly - * - * @param sExtent View extent of MapView - */ - public void addLabelsContourDynamic(Extent sExtent) { - if (labelSet.isAutoDecimal()) { - double min = getMinValue(); - labelSet.setDecimalDigits(MIMath.getDecimalNum(min)); - } - String dFormat = "%1$." + String.valueOf(labelSet.getDecimalDigits()) + "f"; - String text; - for (Graphic graphic : this.graphics) { - Shape shape = graphic.getShape(); - ColorBreak cb = graphic.getLegend(); - PolylineShape aPLS = (PolylineShape) shape; - Extent IExtent = aPLS.getExtent(); - if (IExtent.maxX - IExtent.minX > (sExtent.maxX - sExtent.minX) / 10 - || IExtent.maxY - IExtent.minY > (sExtent.maxY - sExtent.minY) / 10) { - LabelBreak aLP = new LabelBreak(); - int pIdx = aPLS.getPoints().size() / 2; - //PointF aPoint = new PointF(0, 0); - PointShape aPS = new PointShape(); - aPS.setPoint(aPLS.getPoints().get(pIdx - 1)); - //text = DataConvert.removeTailingZeros(String.valueOf(aPLS.getValue())); - text = String.format(dFormat, aPLS.getValue()); - aLP.setText(text); - aLP.setFont(labelSet.getLabelFont()); - aLP.setAlignType(labelSet.getLabelAlignType()); - aLP.setYShift(labelSet.getYOffset()); - if (labelSet.isColorByLegend()) { - aLP.setColor(cb.getColor()); - } else { - aLP.setColor(labelSet.getLabelColor()); - } - Graphic aGraphic = new Graphic(aPS, aLP); - addLabel(aGraphic); - } - } - - labelSet.setDrawLabels(true); - } - - /** - * Get arrow zoom - * - * @return Arrow zoom - */ - public float getArrowZoom() { - if (this.getLegend().getBreakType() == BreakTypes.PointBreak) { - float size = ((PointBreak) this.getLegend()).getSize(); - return size / 10; - } - - return 1.0f; - } - - /** - * Clip - * - * @param clipPolys Clipping polygons - * @return Clipped graphics - */ - public GraphicCollection clip(List clipPolys) { - GraphicCollection cgraphics = new GraphicCollection(); - for (PolygonShape aPGS : clipPolys) { - for (int i = 0; i < this.graphics.size(); i++) { - Shape bShape = this.graphics.get(i).getShape(); - Shape clipShape = bShape.intersection(aPGS); - if (clipShape != null) { - cgraphics.add(new Graphic(clipShape, this.graphics.get(i).getLegend())); - } - } - } - cgraphics.setSingleLegend(this.singleLegend); - cgraphics.setLegendScheme((LegendScheme) this.getLegendScheme().clone()); - - return cgraphics; - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeoComputation; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import org.meteoinfo.layer.LabelSet; +import org.meteoinfo.legend.BreakTypes; +import org.meteoinfo.legend.ColorBreak; +import org.meteoinfo.legend.LabelBreak; +import org.meteoinfo.legend.LegendScheme; +import org.meteoinfo.legend.PointBreak; + +/** + * + * @author Yaqiang Wang + */ +public class GraphicCollection extends Graphic implements Iterator { + + // + private List graphics = new ArrayList<>(); + private Extent _extent = new Extent(); + protected boolean singleLegend = true; + private int index; + private LabelSet labelSet; + private List labelPoints; + protected LegendScheme legendScheme; + protected ColorBreak legendBreak; + // + // + + /** + * Constructor + */ + public GraphicCollection() { + this.index = 0; + labelSet = new LabelSet(); + labelPoints = new ArrayList<>(); + } + + // + // + /** + * Get graphic list + * + * @return Graphic list + */ + @Override + public List getGraphics() { + return this.graphics; + } + + /** + * Set graphic list + * + * @param value Graphic list + */ + public void setGraphics(List value) { + this.graphics = value; + } + + /** + * Get extent + * + * @return The extent + */ + @Override + public Extent getExtent() { + return _extent; + } + + /** + * Set extent + * + * @param value Extent + */ + @Override + public void setExtent(Extent value) { + this._extent = value; + } + + /** + * Get is single legend or not + * + * @return Boolean + */ + @Override + public boolean isSingleLegend() { + return this.singleLegend; + } + + /** + * Set is single legend or not + * + * @param value Boolean + */ + public void setSingleLegend(boolean value) { + this.singleLegend = value; + } + + /** + * Get label set + * + * @return Label set + */ + public LabelSet getLabelSet() { + return labelSet; + } + + /** + * Set label set + * + * @param ls Label set + */ + public void setLabelSet(LabelSet ls) { + labelSet = ls; + } + + /** + * Get label points + * + * @return The lable points + */ + public List getLabelPoints() { + return this.labelPoints; + } + + /** + * Set label points + * + * @param lps The lable points + */ + public void setLabelPoints(List lps) { + this.labelPoints = lps; + } + + /** + * Get legend scheme + * + * @return Legend scheme + */ + public LegendScheme getLegendScheme() { + return this.legendScheme; + } + + /** + * Set legend scheme + * + * @param value Legend scheme + */ + public void setLegendScheme(LegendScheme value) { + this.legendScheme = value; + } + + /** + * Get legend break + * + * @return Legend break + */ + public ColorBreak getLegendBreak() { + return this.legendBreak; + } + + /** + * Set legend break + * + * @param value Legend break + */ + public void setLegendBreak(ColorBreak value) { + this.legendBreak = value; + } + + /** + * Get is 3D or not + * + * @return Boolean + */ + public boolean is3D() { + return false; + } + + /** + * Get if is GraphicCollection + * + * @return Boolean + */ + @Override + public boolean isCollection() { + return true; + } + + // + // + /** + * Update extent + */ + public void updateExtent() { + int i = 0; + Extent extent; + for (Graphic g : this.graphics) { + if (g instanceof GraphicCollection) { + extent = g.getExtent(); + } else { + extent = g.getShape().getExtent(); + } + if (i == 0) { + _extent = extent; + } else { + _extent = MIMath.getLagerExtent(_extent, extent); + } + + i += 1; + } + } + + /** + * Add a graphic + * + * @param aGraphic The graphic + * @return Boolean + */ + public boolean add(Graphic aGraphic) { + boolean istrue = this.graphics.add(aGraphic); + + //Update extent + if (this.graphics.size() == 1) { + _extent = aGraphic.getExtent(); + } else { + _extent = MIMath.getLagerExtent(_extent, aGraphic.getExtent()); + } + + return istrue; + } + + /** + * Inset a graphic + * + * @param index Index + * @param aGraphic The graphic + */ + public void add(int index, Graphic aGraphic) { + this.graphics.add(index, aGraphic); + + //Update extent + if (this.graphics.size() == 1) { + _extent = aGraphic.getShape().getExtent(); + } else { + _extent = MIMath.getLagerExtent(_extent, aGraphic.getShape().getExtent()); + } + } + + /** + * Get a graphic by index + * + * @param idx Index + * @return Graphic + */ + public Graphic get(int idx) { + return this.graphics.get(idx); + } + + /** + * Index of + * + * @param g Graphic + * @return Index + */ + public int indexOf(Graphic g) { + return this.graphics.indexOf(g); + } + + /** + * Contains or not + * + * @param g Graphic + * @return Boolean + */ + public boolean contains(Graphic g) { + return this.graphics.contains(g); + } + + /** + * Get graphic list size + * + * @return Gaphic list size + */ + public int size() { + return this.graphics.size(); + } + + /** + * Get is empty or not + * + * @return Boolean + */ + public boolean isEmpty() { + return this.graphics.isEmpty(); + } + + /** + * Get graphics number + * + * @return 1 + */ + @Override + public int getNumGraphics() { + return this.size(); + } + + /** + * Get Graphic by index + * + * @param idx Index + * @return Graphic + */ + @Override + public Graphic getGraphicN(int idx) { + return this.get(idx); + } + + /** + * Remove a graphic + * + * @param aGraphic The graphic + * @return Boolean + */ + public boolean remove(Graphic aGraphic) { + boolean istrue = this.graphics.remove(aGraphic); + this.updateExtent(); + + return istrue; + } + + /** + * Remove a graphic by index + * + * @param index The index + * @return The removed graphic + */ + public Graphic remove(int index) { + Graphic ag = this.graphics.remove(index); + this.updateExtent(); + + return ag; + } + + /** + * Clear graphics + */ + public void clear() { + this.graphics.clear(); + } + + /** + * Add all + * + * @param gs Graphic list + */ + public void addAll(List gs) { + this.graphics.addAll(gs); + } + + /** + * Join this graphics with other graphics + * + * @param graphic Other graphics + */ + public void join(Graphic graphic) { + if (graphic.isCollection()) { + //Update extent + if (this.isEmpty()) { + _extent = graphic.getExtent(); + } else { + _extent = MIMath.getLagerExtent(_extent, graphic.getExtent()); + } + for (int i = 0; i < graphic.getNumGraphics(); i++) { + this.graphics.add(graphic.getGraphicN(i)); + } + } else { + this.add(graphic); + } + } + + /** + * Remove all + * + * @param gs Graphic list + */ + public void removeAll(List gs) { + this.graphics.removeAll(gs); + } + + /** + * Get legend + * + * @return Legend + */ + @Override + public ColorBreak getLegend() { + if (this.legendBreak != null) { + return this.legendBreak; + } else { + return this.graphics.get(0).getLegend(); + } + } + + /** + * Select graphics by an extent + * + * @param aExtent The extent + * @return Selected graphics + */ + public GraphicCollection selectGraphics(Extent aExtent) { + GraphicCollection selectedGraphics = new GraphicCollection(); + int i, j; + PointD aPoint = new PointD(); + aPoint.X = (aExtent.minX + aExtent.maxX) / 2; + aPoint.Y = (aExtent.minY + aExtent.maxY) / 2; + + for (Graphic aGraphic : this.graphics) { + switch (aGraphic.getShape().getShapeType()) { + case Point: + PointShape aPS = (PointShape) aGraphic.getShape(); + if (MIMath.pointInExtent(aPS.getPoint(), aExtent)) { + selectedGraphics.add(aGraphic); + } + break; + case Polyline: + case PolylineZ: + PolylineShape aPLS = (PolylineShape) aGraphic.getShape(); + if (MIMath.isExtentCross(aExtent, aPLS.getExtent())) { + for (j = 0; j < aPLS.getPoints().size(); j++) { + aPoint = aPLS.getPoints().get(j); + if (MIMath.pointInExtent(aPoint, aExtent)) { + selectedGraphics.add(aGraphic); + break; + } + } + } + break; + case Polygon: + case Rectangle: + PolygonShape aPGS = (PolygonShape) aGraphic.getShape(); + if (!(aPGS.getPartNum() > 1)) { + if (GeoComputation.pointInPolygon((List) aPGS.getPoints(), aPoint)) { + selectedGraphics.add(aGraphic); + } + } else { + for (int p = 0; p < aPGS.getPartNum(); p++) { + ArrayList pList = new ArrayList(); + if (p == aPGS.getPartNum() - 1) { + for (int pp = aPGS.parts[p]; pp < aPGS.getPointNum(); pp++) { + pList.add(aPGS.getPoints().get(pp)); + } + } else { + for (int pp = aPGS.parts[p]; pp < aPGS.parts[p + 1]; pp++) { + pList.add(aPGS.getPoints().get(pp)); + } + } + if (GeoComputation.pointInPolygon(pList, aPoint)) { + selectedGraphics.add(aGraphic); + break; + } + } + } + break; + } + } + + return selectedGraphics; + } + + @Override + public boolean hasNext() { + return index <= this.size() - 1; + } + + @Override + public Object next() { + if (index >= this.size()) { + throw new NoSuchElementException(); + } + + return this.get(index++); + } + + /** + * Add labels + */ + public void addLabels() { + addLabelsByColor(); + + labelSet.setDrawLabels(true); + } + + /** + * Get shapes + * + * @return Shapes + */ + public List getShapes() { + List shapes = new ArrayList<>(); + for (Graphic g : this.graphics) { + shapes.add(g.getShape()); + } + return shapes; + } + + /** + * Get shape type + * + * @return Shape type + */ + public ShapeTypes getShapeType() { + return this.graphics.get(0).getShape().getShapeType(); + } + + private double getMinValue() { + double min = Double.MAX_VALUE; + for (Graphic graphic : this.graphics) { + Shape shape = graphic.getShape(); + if (min > shape.getValue()) { + min = shape.getValue(); + } + } + return min; + } + + /** + * Add labels + */ + private void addLabelsByColor() { + if (labelSet.isAutoDecimal()) { + double min = getMinValue(); + labelSet.setDecimalDigits(MIMath.getDecimalNum(min)); + } + String dFormat = "%1$." + String.valueOf(labelSet.getDecimalDigits()) + "f"; + PointD aPoint; + for (Graphic graphic : this.graphics) { + ColorBreak cb = graphic.getLegend(); + Shape shape = graphic.getShape(); + PointShape aPS = new PointShape(); + switch (shape.getShapeType()) { + case Point: + case PointM: + case PointZ: + aPS.setPoint((PointD) ((PointShape) shape).getPoint().clone()); + break; + case Polyline: + case PolylineM: + case PolylineZ: + int pIdx = ((PolylineShape) shape).getPoints().size() / 2; + aPS.setPoint((PointD) ((PolylineShape) shape).getPoints().get(pIdx - 1).clone()); + break; + case Polygon: + case PolygonM: + Extent aExtent = shape.getExtent(); + aPoint = new PointD(); + aPoint.X = ((aExtent.minX + aExtent.maxX) / 2); + aPoint.Y = ((aExtent.minY + aExtent.maxY) / 2); + aPS.setPoint(aPoint); + break; + } + + LabelBreak aLP = new LabelBreak(); + //aLP.setText(DataConvert.removeTailingZeros(String.valueOf(shape.getValue()))); + aLP.setText(String.format(dFormat, shape.getValue())); + if (labelSet.isColorByLegend()) { + aLP.setColor(cb.getColor()); + } else { + aLP.setColor(labelSet.getLabelColor()); + } + aLP.setFont(labelSet.getLabelFont()); + aLP.setAlignType(labelSet.getLabelAlignType()); + aLP.setYShift(labelSet.getYOffset()); + aLP.setXShift(labelSet.getXOffset()); + Graphic aGraphic = new Graphic(aPS, aLP); + addLabel(aGraphic); + } + } + + /** + * Add label point + * + * @param aLP Label point + */ + public void addLabel(Graphic aLP) { + labelPoints.add(aLP); + } + + /** + * Add labels of contour layer dynamicly + * + * @param sExtent View extent of MapView + */ + public void addLabelsContourDynamic(Extent sExtent) { + if (labelSet.isAutoDecimal()) { + double min = getMinValue(); + labelSet.setDecimalDigits(MIMath.getDecimalNum(min)); + } + String dFormat = "%1$." + String.valueOf(labelSet.getDecimalDigits()) + "f"; + String text; + for (Graphic graphic : this.graphics) { + Shape shape = graphic.getShape(); + ColorBreak cb = graphic.getLegend(); + PolylineShape aPLS = (PolylineShape) shape; + Extent IExtent = aPLS.getExtent(); + if (IExtent.maxX - IExtent.minX > (sExtent.maxX - sExtent.minX) / 10 + || IExtent.maxY - IExtent.minY > (sExtent.maxY - sExtent.minY) / 10) { + LabelBreak aLP = new LabelBreak(); + int pIdx = aPLS.getPoints().size() / 2; + //PointF aPoint = new PointF(0, 0); + PointShape aPS = new PointShape(); + aPS.setPoint(aPLS.getPoints().get(pIdx - 1)); + //text = DataConvert.removeTailingZeros(String.valueOf(aPLS.getValue())); + text = String.format(dFormat, aPLS.getValue()); + aLP.setText(text); + aLP.setFont(labelSet.getLabelFont()); + aLP.setAlignType(labelSet.getLabelAlignType()); + aLP.setYShift(labelSet.getYOffset()); + if (labelSet.isColorByLegend()) { + aLP.setColor(cb.getColor()); + } else { + aLP.setColor(labelSet.getLabelColor()); + } + Graphic aGraphic = new Graphic(aPS, aLP); + addLabel(aGraphic); + } + } + + labelSet.setDrawLabels(true); + } + + /** + * Get arrow zoom + * + * @return Arrow zoom + */ + public float getArrowZoom() { + if (this.getLegend().getBreakType() == BreakTypes.PointBreak) { + float size = ((PointBreak) this.getLegend()).getSize(); + return size / 10; + } + + return 1.0f; + } + + /** + * Clip + * + * @param clipPolys Clipping polygons + * @return Clipped graphics + */ + public GraphicCollection clip(List clipPolys) { + GraphicCollection cgraphics = new GraphicCollection(); + for (PolygonShape aPGS : clipPolys) { + for (int i = 0; i < this.graphics.size(); i++) { + Shape bShape = this.graphics.get(i).getShape(); + Shape clipShape = bShape.intersection(aPGS); + if (clipShape != null) { + cgraphics.add(new Graphic(clipShape, this.graphics.get(i).getLegend())); + } + } + } + cgraphics.setSingleLegend(this.singleLegend); + cgraphics.setLegendScheme((LegendScheme) this.getLegendScheme().clone()); + + return cgraphics; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Line.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Line.java index df83830d..6e5874bc 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Line.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Line.java @@ -1,49 +1,49 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; - -/** - * - * @author Yaqiang Wang - */ -public class Line { - /// - /// Point 1 - /// - - public PointD P1 = new PointD(); - /// - /// Point 2 - /// - public PointD P2 = new PointD(); - - /** - * Determine if the line is horizontal - * @return Boolean - */ - public boolean isHorizontal(){ - return (MIMath.doubleEquals(P1.Y, P2.Y)); - } - - /** - * Determine if the line is vertical - * @return Boolean - */ - public boolean isVertical(){ - return (MIMath.doubleEquals(P1.X, P2.X)); - } -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + + import org.meteoinfo.common.MIMath; + import org.meteoinfo.common.PointD; + + /** + * + * @author Yaqiang Wang + */ +public class Line { + /// + /// Point 1 + /// + + public PointD P1 = new PointD(); + /// + /// Point 2 + /// + public PointD P2 = new PointD(); + + /** + * Determine if the line is horizontal + * @return Boolean + */ + public boolean isHorizontal(){ + return (MIMath.doubleEquals(P1.Y, P2.Y)); + } + + /** + * Determine if the line is vertical + * @return Boolean + */ + public boolean isVertical(){ + return (MIMath.doubleEquals(P1.X, P2.X)); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointM.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointM.java index 71a0740b..ef6bfe18 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointM.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointM.java @@ -1,63 +1,63 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.PointD; - -/** - * - * @author yaqiang - */ -public class PointM extends PointD { - // - /** - * Measure - */ - public double M; - // - // - - /** - * Constructor - */ - public PointM() { - } - - /** - * Constructor - * - * @param x X - * @param y Y - * @param m M - */ - public PointM(double x, double y, double m) { - X = x; - Y = y; - M = m; - } - // - // - // - // - - /** - * Convert to PointD - * - * @return PointD - */ - public PointD toPointD() { - return new PointD(X, Y); - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.PointD; + +/** + * + * @author yaqiang + */ +public class PointM extends PointD { + // + /** + * Measure + */ + public double M; + // + // + + /** + * Constructor + */ + public PointM() { + } + + /** + * Constructor + * + * @param x X + * @param y Y + * @param m M + */ + public PointM(double x, double y, double m) { + X = x; + Y = y; + M = m; + } + // + // + // + // + + /** + * Convert to PointD + * + * @return PointD + */ + public PointD toPointD() { + return new PointD(X, Y); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointShape.java index 1ae87684..2e2c5090 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointShape.java @@ -14,13 +14,13 @@ */ package org.meteoinfo.shape; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; import java.util.ArrayList; import java.util.List; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; /** * Point shape class diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZ.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZ.java index e8745408..1fbd25d0 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZ.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZ.java @@ -1,111 +1,111 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.PointD; - -/** - * - * @author yaqiang - */ -public class PointZ extends PointD implements Cloneable{ - // - - /** - * Z coordinate - */ - public double Z; - /** - * Measure - */ - public double M; - // - // - - /** - * Constructor - */ - public PointZ() { - } - - /** - * Constructor - * - * @param x X - * @param y Y - * @param z Z - */ - public PointZ(double x, double y, double z) { - X = x; - Y = y; - Z = z; - } - - /** - * Constructor - * @param coord Coordinate array - */ - public PointZ(double[] coord) { - X = coord[0]; - Y = coord[1]; - Z = coord[2]; - } - - /** - * Constructor - * - * @param x X - * @param y Y - * @param z Z - * @param m M - */ - public PointZ(double x, double y, double z, double m) { - X = x; - Y = y; - Z = z; - M = m; - } - // - // - // - // - - /** - * Convert to PointD - * - * @return PointD - */ - public PointD toPointD() { - return new PointD(X, Y); - } - - /** - * To double array - * @return Double array - */ - public double[] toArray() { - return new double[]{X, Y, Z}; - } - - /** - * Clone - * - * @return PointZ object - */ - @Override - public Object clone() { - return (PointZ)super.clone(); - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.PointD; + +/** + * + * @author yaqiang + */ +public class PointZ extends PointD implements Cloneable{ + // + + /** + * Z coordinate + */ + public double Z; + /** + * Measure + */ + public double M; + // + // + + /** + * Constructor + */ + public PointZ() { + } + + /** + * Constructor + * + * @param x X + * @param y Y + * @param z Z + */ + public PointZ(double x, double y, double z) { + X = x; + Y = y; + Z = z; + } + + /** + * Constructor + * @param coord Coordinate array + */ + public PointZ(double[] coord) { + X = coord[0]; + Y = coord[1]; + Z = coord[2]; + } + + /** + * Constructor + * + * @param x X + * @param y Y + * @param z Z + * @param m M + */ + public PointZ(double x, double y, double z, double m) { + X = x; + Y = y; + Z = z; + M = m; + } + // + // + // + // + + /** + * Convert to PointD + * + * @return PointD + */ + public PointD toPointD() { + return new PointD(X, Y); + } + + /** + * To double array + * @return Double array + */ + public double[] toArray() { + return new double[]{X, Y, Z}; + } + + /** + * Clone + * + * @return PointZ object + */ + @Override + public Object clone() { + return (PointZ)super.clone(); + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZShape.java index 470bc40d..ab4c1936 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PointZShape.java @@ -1,155 +1,155 @@ -/* - * Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.Extent3D; -import org.meteoinfo.global.PointD; -import org.locationtech.jts.geom.CoordinateXYZM; -import org.locationtech.jts.geom.Geometry; - -/** - * - * @author yaqiang - */ -public class PointZShape extends PointShape { - // - - //private PointZ _point = new PointZ(); - //private double z; - //private double m; - // - // - /** - * Constructor - */ - public PointZShape(){ - this.point = new PointZ(); - this.updateExtent((PointZ)this.point); - } - - /** - * Constructor - * @param geometry Geometry - */ - public PointZShape(Geometry geometry) { - CoordinateXYZM c = (CoordinateXYZM)geometry.getCoordinate(); - this.setPoint(new PointZ(c.x, c.y, c.getZ(), c.getM())); - } - // - // - - @Override - public ShapeTypes getShapeType(){ - return ShapeTypes.PointZ; - } - -// /** -// * Get point -// * -// * @return Point -// */ -// @Override -// public PointZ getPoint() { -// return _point; -// } -// -// /** -// * Set point -// * -// * @param point Point -// */ -// public void setPoint(PointZ point) { -// _point = point; -// } - - // - // - /** - * Set point - * - * @param aPoint point - */ - @Override - public void setPoint(PointD aPoint) { - if (aPoint instanceof PointZ){ - this.point = aPoint; - } else { - this.point.X = aPoint.X; - this.point.Y = aPoint.Y; - } - this.updateExtent((PointZ)this.point); - } - - /** - * Set point - * @param p PointZ - */ - public void setPoint(PointZ p){ - this.point = p; - this.updateExtent(p); - } - - /** - * Update extent - * @param p PointZ - */ - public void updateExtent(PointZ p){ - Extent3D aExtent = new Extent3D(); - aExtent.minX = p.X; - aExtent.maxX = p.X; - aExtent.minY = p.Y; - aExtent.maxY = p.Y; - aExtent.minZ = p.Z; - aExtent.maxZ = p.Z; - this.setExtent(aExtent); - } - - /** - * Get M value - * @return M value - */ - public double getM(){ - return ((PointZ)this.getPoint()).M; - } - - /** - * Get Z value - * @return Z value - */ - public double getZ(){ - return ((PointZ)this.getPoint()).Z; - } - - /** - * Clone - * - * @return PolylineZShape object - */ - @Override - public Object clone() { - PointZShape aPS = new PointZShape(); - //aPS = (PointZShape)base.Clone(); - aPS.setPoint((PointZ)this.getPoint().clone()); - //aPS.Z = Z; - //aPS.M = M; - aPS.setValue(getValue()); - aPS.setVisible(this.isVisible()); - aPS.setSelected(this.isSelected()); - aPS.setLegendIndex(this.getLegendIndex()); - - return aPS; - } - // -} +/* + * Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.locationtech.jts.geom.CoordinateXYZM; +import org.locationtech.jts.geom.Geometry; +import org.meteoinfo.common.Extent3D; +import org.meteoinfo.common.PointD; + +/** + * + * @author yaqiang + */ +public class PointZShape extends PointShape { + // + + //private PointZ _point = new PointZ(); + //private double z; + //private double m; + // + // + /** + * Constructor + */ + public PointZShape(){ + this.point = new PointZ(); + this.updateExtent((PointZ)this.point); + } + + /** + * Constructor + * @param geometry Geometry + */ + public PointZShape(Geometry geometry) { + CoordinateXYZM c = (CoordinateXYZM)geometry.getCoordinate(); + this.setPoint(new PointZ(c.x, c.y, c.getZ(), c.getM())); + } + // + // + + @Override + public ShapeTypes getShapeType(){ + return ShapeTypes.PointZ; + } + +// /** +// * Get point +// * +// * @return Point +// */ +// @Override +// public PointZ getPoint() { +// return _point; +// } +// +// /** +// * Set point +// * +// * @param point Point +// */ +// public void setPoint(PointZ point) { +// _point = point; +// } + + // + // + /** + * Set point + * + * @param aPoint point + */ + @Override + public void setPoint(PointD aPoint) { + if (aPoint instanceof PointZ){ + this.point = aPoint; + } else { + this.point.X = aPoint.X; + this.point.Y = aPoint.Y; + } + this.updateExtent((PointZ)this.point); + } + + /** + * Set point + * @param p PointZ + */ + public void setPoint(PointZ p){ + this.point = p; + this.updateExtent(p); + } + + /** + * Update extent + * @param p PointZ + */ + public void updateExtent(PointZ p){ + Extent3D aExtent = new Extent3D(); + aExtent.minX = p.X; + aExtent.maxX = p.X; + aExtent.minY = p.Y; + aExtent.maxY = p.Y; + aExtent.minZ = p.Z; + aExtent.maxZ = p.Z; + this.setExtent(aExtent); + } + + /** + * Get M value + * @return M value + */ + public double getM(){ + return ((PointZ)this.getPoint()).M; + } + + /** + * Get Z value + * @return Z value + */ + public double getZ(){ + return ((PointZ)this.getPoint()).Z; + } + + /** + * Clone + * + * @return PolylineZShape object + */ + @Override + public Object clone() { + PointZShape aPS = new PointZShape(); + //aPS = (PointZShape)base.Clone(); + aPS.setPoint((PointZ)this.getPoint().clone()); + //aPS.Z = Z; + //aPS.M = M; + aPS.setValue(getValue()); + aPS.setVisible(this.isVisible()); + aPS.setSelected(this.isSelected()); + aPS.setLegendIndex(this.getLegendIndex()); + + return aPS; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polygon.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polygon.java index 7eaaed7c..c561cbb8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polygon.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polygon.java @@ -13,13 +13,15 @@ */ package org.meteoinfo.shape; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; + import java.util.ArrayList; import java.util.Collections; import java.util.List; + +import org.meteoinfo.geoprocess.GeometryUtil; import org.meteoinfo.global.DataConvert; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; @@ -63,7 +65,7 @@ public class Polygon { */ public void setOutLine(List outLine) { _outLine = outLine; - _extent = MIMath.getPointsExtent(outLine); + _extent = GeometryUtil.getPointsExtent(outLine); } /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonMShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonMShape.java index b73d311f..9b25640e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonMShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonMShape.java @@ -1,74 +1,75 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.shape; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.MIMath; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.CoordinateXYM; -import org.locationtech.jts.geom.Geometry; - -/** - * - * @author yaqiang - */ -public class PolygonMShape extends PolygonShape{ - // - // - // - /** - * Constructor - */ - public PolygonMShape(){ - super(); - } - - /** - * Constructor - * @param geometry Geometry - */ - public PolygonMShape(Geometry geometry) { - Coordinate[] cs = geometry.getCoordinates(); - List points = new ArrayList(); - for (Coordinate c1 : cs) { - CoordinateXYM c = (CoordinateXYM) c1; - points.add(new PointZ(c.x, c.y, c.getZ(), c.getM())); - } - this.setPoints(points); - } - // - // - @Override - public ShapeTypes getShapeType(){ - return ShapeTypes.PolygonM; - } - - /** - * Get M Array - * - * @return M value array - */ - public double[] getMArray() { - double[] mArray = new double[this.getPoints().size()]; - for (int i = 0; i < this.getPoints().size(); i++) { - mArray[i] = ((PointM)this.getPoints().get(i)).M; - } - - return mArray; - } - - /** - * Get M range - min, max - * - * @return M min, max - */ - public double[] getMRange() { - return MIMath.arrayMinMax(getMArray()); - } - // - // - // -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.shape; + +import java.util.ArrayList; +import java.util.List; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.CoordinateXYM; +import org.locationtech.jts.geom.Geometry; +import org.meteoinfo.common.MIMath; + +/** + * + * @author yaqiang + */ +public class PolygonMShape extends PolygonShape{ + // + // + // + /** + * Constructor + */ + public PolygonMShape(){ + super(); + } + + /** + * Constructor + * @param geometry Geometry + */ + public PolygonMShape(Geometry geometry) { + Coordinate[] cs = geometry.getCoordinates(); + List points = new ArrayList(); + for (Coordinate c1 : cs) { + CoordinateXYM c = (CoordinateXYM) c1; + points.add(new PointZ(c.x, c.y, c.getZ(), c.getM())); + } + this.setPoints(points); + } + // + // + @Override + public ShapeTypes getShapeType(){ + return ShapeTypes.PolygonM; + } + + /** + * Get M Array + * + * @return M value array + */ + public double[] getMArray() { + double[] mArray = new double[this.getPoints().size()]; + for (int i = 0; i < this.getPoints().size(); i++) { + mArray[i] = ((PointM)this.getPoints().get(i)).M; + } + + return mArray; + } + + /** + * Get M range - min, max + * + * @return M min, max + */ + public double[] getMRange() { + return MIMath.arrayMinMax(getMArray()); + } + // + // + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonShape.java index 150a3aa9..66c65644 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonShape.java @@ -13,18 +13,21 @@ */ package org.meteoinfo.shape; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.meteoinfo.global.PointF; + import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.MultiPolygon; +import org.meteoinfo.geoprocess.GeometryUtil; /** * PolygonShape class @@ -137,7 +140,7 @@ public class PolygonShape extends Shape implements Cloneable { ((List)this._polygons).add(polygon); break; } - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); } // // @@ -184,7 +187,7 @@ public class PolygonShape extends Shape implements Cloneable { @Override public void setPoints(List points) { _points = points; - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); updatePolygons(); } @@ -198,7 +201,7 @@ public class PolygonShape extends Shape implements Cloneable { ps.add(new PointD(points[i].X, points[i].Y)); } _points = ps; - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); updatePolygons_keep(); } @@ -390,7 +393,7 @@ public class PolygonShape extends Shape implements Cloneable { parts[i] = partList.get(i); } if (_points.size() > 0) - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); } /** @@ -462,7 +465,7 @@ public class PolygonShape extends Shape implements Cloneable { } ((List) _points).add(vIdx, vertice); - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); this.updatePolygons(); } @@ -479,7 +482,7 @@ public class PolygonShape extends Shape implements Cloneable { } ((List) _points).remove(vIdx); - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); this.updatePolygons(); } diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonZShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonZShape.java index 7972f04e..7fd00ed8 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonZShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolygonZShape.java @@ -1,112 +1,113 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.shape; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.MIMath; - -/** - * - * @author Yaqiang Wang - */ -public class PolygonZShape extends PolygonShape{ - @Override - public ShapeTypes getShapeType(){ - return ShapeTypes.PolygonZ; - } - - /** - * Get Z Array - * - * @return Z value array - */ - public double[] getZArray() { - double[] zArray = new double[this.getPoints().size()]; - for (int i = 0; i < this.getPoints().size(); i++) { - zArray[i] = ((PointZ)this.getPoints().get(i)).Z; - } - - return zArray; - } - - /** - * Get Z range - min, max - * - * @return Z min, max - */ - public double[] getZRange() { - return MIMath.arrayMinMax(getZArray()); - } - - /** - * Get M Array - * - * @return M value array - */ - public double[] getMArray() { - double[] mArray = new double[this.getPoints().size()]; - for (int i = 0; i < this.getPoints().size(); i++) { - mArray[i] = ((PointZ)this.getPoints().get(i)).M; - } - - return mArray; - } - - /** - * Get M range - min, max - * - * @return M min, max - */ - public double[] getMRange() { - return MIMath.arrayMinMax(getMArray()); - } - - @Override - protected void updatePolygons() { - _polygons = new ArrayList<>(); - if (_numParts == 1) { - PolygonZ aPolygon = new PolygonZ(); - aPolygon.setOutLine(_points); - ((List)_polygons).add(aPolygon); - } else { - PointZ[] Pointps; - PolygonZ aPolygon = null; - int numPoints = this.getPointNum(); - for (int p = 0; p < _numParts; p++) { - if (p == _numParts - 1) { - Pointps = new PointZ[numPoints - parts[p]]; - for (int pp = parts[p]; pp < numPoints; pp++) { - Pointps[pp - parts[p]] = (PointZ)_points.get(pp); - } - } else { - Pointps = new PointZ[parts[p + 1] - parts[p]]; - for (int pp = parts[p]; pp < parts[p + 1]; pp++) { - Pointps[pp - parts[p]] = (PointZ)_points.get(pp); - } - } - - if (GeoComputation.isClockwise(Pointps)) { - if (p > 0) { - ((List)_polygons).add(aPolygon); - } - - aPolygon = new PolygonZ(); - aPolygon.setOutLine(Arrays.asList(Pointps)); - } else if (aPolygon == null) { - MIMath.arrayReverse(Pointps); - aPolygon = new PolygonZ(); - aPolygon.setOutLine(Arrays.asList(Pointps)); - } else { - aPolygon.addHole(Arrays.asList(Pointps)); - } - } - ((List)_polygons).add(aPolygon); - } - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.shape; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.geoprocess.GeoComputation; + +/** + * + * @author Yaqiang Wang + */ +public class PolygonZShape extends PolygonShape{ + @Override + public ShapeTypes getShapeType(){ + return ShapeTypes.PolygonZ; + } + + /** + * Get Z Array + * + * @return Z value array + */ + public double[] getZArray() { + double[] zArray = new double[this.getPoints().size()]; + for (int i = 0; i < this.getPoints().size(); i++) { + zArray[i] = ((PointZ)this.getPoints().get(i)).Z; + } + + return zArray; + } + + /** + * Get Z range - min, max + * + * @return Z min, max + */ + public double[] getZRange() { + return MIMath.arrayMinMax(getZArray()); + } + + /** + * Get M Array + * + * @return M value array + */ + public double[] getMArray() { + double[] mArray = new double[this.getPoints().size()]; + for (int i = 0; i < this.getPoints().size(); i++) { + mArray[i] = ((PointZ)this.getPoints().get(i)).M; + } + + return mArray; + } + + /** + * Get M range - min, max + * + * @return M min, max + */ + public double[] getMRange() { + return MIMath.arrayMinMax(getMArray()); + } + + @Override + protected void updatePolygons() { + _polygons = new ArrayList<>(); + if (_numParts == 1) { + PolygonZ aPolygon = new PolygonZ(); + aPolygon.setOutLine(_points); + ((List)_polygons).add(aPolygon); + } else { + PointZ[] Pointps; + PolygonZ aPolygon = null; + int numPoints = this.getPointNum(); + for (int p = 0; p < _numParts; p++) { + if (p == _numParts - 1) { + Pointps = new PointZ[numPoints - parts[p]]; + for (int pp = parts[p]; pp < numPoints; pp++) { + Pointps[pp - parts[p]] = (PointZ)_points.get(pp); + } + } else { + Pointps = new PointZ[parts[p + 1] - parts[p]]; + for (int pp = parts[p]; pp < parts[p + 1]; pp++) { + Pointps[pp - parts[p]] = (PointZ)_points.get(pp); + } + } + + if (GeoComputation.isClockwise(Pointps)) { + if (p > 0) { + ((List)_polygons).add(aPolygon); + } + + aPolygon = new PolygonZ(); + aPolygon.setOutLine(Arrays.asList(Pointps)); + } else if (aPolygon == null) { + MIMath.arrayReverse(Pointps); + aPolygon = new PolygonZ(); + aPolygon.setOutLine(Arrays.asList(Pointps)); + } else { + aPolygon.addHole(Arrays.asList(Pointps)); + } + } + ((List)_polygons).add(aPolygon); + } + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polyline.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polyline.java index cf5dc10f..4c7ee00e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polyline.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Polyline.java @@ -14,10 +14,12 @@ */ package org.meteoinfo.shape; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; +import org.meteoinfo.geoprocess.GeometryUtil; + import java.util.ArrayList; import java.util.List; @@ -55,7 +57,7 @@ public class Polyline { */ public void setPointList(List points) { _pointList = points; - _extent = MIMath.getPointsExtent(_pointList); + _extent = GeometryUtil.getPointsExtent(_pointList); } /** @@ -80,7 +82,7 @@ public class Polyline { } _pointList = pointList; - _extent = MIMath.getPointsExtent(_pointList); + _extent = GeometryUtil.getPointsExtent(_pointList); } /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineShape.java index 2b6b57cc..05479d89 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineShape.java @@ -13,8 +13,6 @@ */ package org.meteoinfo.shape; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -24,6 +22,9 @@ import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.MultiLineString; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.geoprocess.GeometryUtil; /** * Poyline shape class @@ -93,7 +94,7 @@ public class PolylineShape extends Shape implements Cloneable { for (int i = 0; i < parts.length; i++) { parts[i] = partlist.get(i); } - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); break; default: this.setPoints(points); @@ -160,7 +161,7 @@ public class PolylineShape extends Shape implements Cloneable { @Override public void setPoints(List points) { _points = points; - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); updatePolyLines(); } @@ -274,7 +275,7 @@ public class PolylineShape extends Shape implements Cloneable { for (int i = 0; i < partList.size(); i++) { parts[i] = partList.get(i); } - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); } /** @@ -310,7 +311,7 @@ public class PolylineShape extends Shape implements Cloneable { } ((List) _points).add(vIdx, vertice); - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); updatePolyLines(); } @@ -327,7 +328,7 @@ public class PolylineShape extends Shape implements Cloneable { } ((List) _points).remove(vIdx); - this.setExtent(MIMath.getPointsExtent(_points)); + this.setExtent(GeometryUtil.getPointsExtent(_points)); updatePolyLines(); } diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZ.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZ.java index cf104f83..65d0a0af 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZ.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZ.java @@ -1,99 +1,93 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author yaqiang - */ -public class PolylineZ extends Polyline{ - // - - //private Extent _extent; - //private List _pointList; - // - // - - /** - * Constructor - */ - public PolylineZ() { - super(); - //_extent = new Extent(); - //_pointList = new ArrayList<>(); - } - // - // - -// /** -// * Get points -// * -// * @return Point list -// */ -// public List getPoints() { -// return _pointList; -// } -// -// /** -// * Set points -// * -// * @param points Point list -// */ -// public void setPoints(List points) { -// _pointList = points; -// _extent = MIMath.getPointsExtent((getPointDList())); -// } -// -// /** -// * Get extent -// * -// * @return Extent -// */ -// public Extent getExtent() { -// return _extent; -// } -// -// // -// // -// private List getPointDList() { -// List pList = new ArrayList<>(); -// for (PointZ aP : _pointList) { -// pList.add(aP.toPointD()); -// } -// -// return pList; -// } - -// /** -// * Determine if the polyline is closed -// * -// * @return Boolean -// */ -// public boolean isClosed() { -// PointZ sPoint = _pointList.get(0); -// PointZ ePoint = _pointList.get(_pointList.size() - 1); -// if (MIMath.doubleEquals(sPoint.X, ePoint.X) && MIMath.doubleEquals(sPoint.Y, ePoint.Y)) { -// return true; -// } else { -// return false; -// } -// } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +/** + * + * @author yaqiang + */ +public class PolylineZ extends Polyline{ + // + + //private Extent _extent; + //private List _pointList; + // + // + + /** + * Constructor + */ + public PolylineZ() { + super(); + //_extent = new Extent(); + //_pointList = new ArrayList<>(); + } + // + // + +// /** +// * Get points +// * +// * @return Point list +// */ +// public List getPoints() { +// return _pointList; +// } +// +// /** +// * Set points +// * +// * @param points Point list +// */ +// public void setPoints(List points) { +// _pointList = points; +// _extent = MIMath.getPointsExtent((getPointDList())); +// } +// +// /** +// * Get extent +// * +// * @return Extent +// */ +// public Extent getExtent() { +// return _extent; +// } +// +// // +// // +// private List getPointDList() { +// List pList = new ArrayList<>(); +// for (PointZ aP : _pointList) { +// pList.add(aP.toPointD()); +// } +// +// return pList; +// } + +// /** +// * Determine if the polyline is closed +// * +// * @return Boolean +// */ +// public boolean isClosed() { +// PointZ sPoint = _pointList.get(0); +// PointZ ePoint = _pointList.get(_pointList.size() - 1); +// if (MIMath.doubleEquals(sPoint.X, ePoint.X) && MIMath.doubleEquals(sPoint.Y, ePoint.Y)) { +// return true; +// } else { +// return false; +// } +// } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZShape.java index 45489a24..44ff5dad 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/PolylineZShape.java @@ -1,167 +1,168 @@ - /* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import org.meteoinfo.global.MIMath; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.Extent; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.CoordinateXYZM; -import org.locationtech.jts.geom.Geometry; - -/** - * PolylineZ shape class - * - * @author yaqiang - */ -public class PolylineZShape extends PolylineShape { - // - - //private List _points = new ArrayList(); - //private List _polylines = new ArrayList(); - // - // - - /** - * Constructor - */ - public PolylineZShape() { - super(); - } - - /** - * Constructor - * @param geometry Geometry - */ - public PolylineZShape(Geometry geometry) { - Coordinate[] cs = geometry.getCoordinates(); - List points = new ArrayList(); - for (Coordinate c1 : cs) { - CoordinateXYZM c = (CoordinateXYZM) c1; - points.add(new PointZ(c.x, c.y, c.getZ(), c.getM())); - } - this.setPoints(points); - } - // - // - - @Override - public ShapeTypes getShapeType(){ - return ShapeTypes.PolylineZ; - } - - /** - * Get Z Array - * - * @return Z array - */ - public double[] getZArray() { - double[] zArray = new double[this.getPoints().size()]; - for (int i = 0; i < this.getPoints().size(); i++) { - zArray[i] = ((PointZ)this.getPoints().get(i)).Z; - } - - return zArray; - } - - /** - * Get Z Array - * - * @return Z value array - */ - public double[] getMArray() { - double[] mArray = new double[this.getPoints().size()]; - for (int i = 0; i < this.getPoints().size(); i++) { - mArray[i] = ((PointZ)this.getPoints().get(i)).M; - } - - return mArray; - } - - /** - * Get Z range - min, max - * - * @return Z min, max - */ - public double[] getZRange() { - return MIMath.arrayMinMax(getZArray()); - } - - /** - * Get M range - min, max - * - * @return M min, max - */ - public double[] getMRange() { - return MIMath.arrayMinMax(getMArray()); - } - - //@Override - public Object clone_back(){ - PolylineZShape o = (PolylineZShape)super.clone(); -// List points = new ArrayList<>(); -// for (PointZ point : (List)this.getPoints()){ -// points.add((PointZ)point.clone()); -// } -// o.setPoints(points); - - return o; - } - - /** - * Clone - * - * @return PolylineZShape object - */ - @Override - public Object clone() { - PolylineZShape aPLS = new PolylineZShape(); - aPLS.setValue(this.getValue()); - aPLS.setExtent((Extent)this.getExtent().clone()); - aPLS.setPartNum(this.getPartNum()); - aPLS.parts = (int[]) parts.clone(); - List points = new ArrayList<>(); - for (PointZ point : (List)this.getPoints()){ - points.add((PointZ)point.clone()); - } - aPLS.setPoints(points); - aPLS.setVisible(this.isVisible()); - aPLS.setSelected(this.isSelected()); - aPLS.setLegendIndex(this.getLegendIndex()); - //aPLS.ZRange = (double[])ZRange.Clone(); - //aPLS.MRange = (double[])MRange.Clone(); - //aPLS.ZArray = (double[])ZArray.Clone(); - //aPLS.MArray = (double[])MArray.Clone(); - - return aPLS; - } - - /** - * Value clone - * - * @return PolylineZShape object - */ - @Override - public Object valueClone() { - PolylineZShape aPLS = new PolylineZShape(); - aPLS.setValue(this.getValue()); - aPLS.setVisible(this.isVisible()); - aPLS.setSelected(this.isSelected()); - aPLS.setLegendIndex(this.getLegendIndex()); - - return aPLS; - } - // -} + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import java.util.ArrayList; +import java.util.List; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.CoordinateXYZM; +import org.locationtech.jts.geom.Geometry; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; + + /** + * PolylineZ shape class + * + * @author yaqiang + */ +public class PolylineZShape extends PolylineShape { + // + + //private List _points = new ArrayList(); + //private List _polylines = new ArrayList(); + // + // + + /** + * Constructor + */ + public PolylineZShape() { + super(); + } + + /** + * Constructor + * @param geometry Geometry + */ + public PolylineZShape(Geometry geometry) { + Coordinate[] cs = geometry.getCoordinates(); + List points = new ArrayList(); + for (Coordinate c1 : cs) { + CoordinateXYZM c = (CoordinateXYZM) c1; + points.add(new PointZ(c.x, c.y, c.getZ(), c.getM())); + } + this.setPoints(points); + } + // + // + + @Override + public ShapeTypes getShapeType(){ + return ShapeTypes.PolylineZ; + } + + /** + * Get Z Array + * + * @return Z array + */ + public double[] getZArray() { + double[] zArray = new double[this.getPoints().size()]; + for (int i = 0; i < this.getPoints().size(); i++) { + zArray[i] = ((PointZ)this.getPoints().get(i)).Z; + } + + return zArray; + } + + /** + * Get Z Array + * + * @return Z value array + */ + public double[] getMArray() { + double[] mArray = new double[this.getPoints().size()]; + for (int i = 0; i < this.getPoints().size(); i++) { + mArray[i] = ((PointZ)this.getPoints().get(i)).M; + } + + return mArray; + } + + /** + * Get Z range - min, max + * + * @return Z min, max + */ + public double[] getZRange() { + return MIMath.arrayMinMax(getZArray()); + } + + /** + * Get M range - min, max + * + * @return M min, max + */ + public double[] getMRange() { + return MIMath.arrayMinMax(getMArray()); + } + + //@Override + public Object clone_back(){ + PolylineZShape o = (PolylineZShape)super.clone(); +// List points = new ArrayList<>(); +// for (PointZ point : (List)this.getPoints()){ +// points.add((PointZ)point.clone()); +// } +// o.setPoints(points); + + return o; + } + + /** + * Clone + * + * @return PolylineZShape object + */ + @Override + public Object clone() { + PolylineZShape aPLS = new PolylineZShape(); + aPLS.setValue(this.getValue()); + aPLS.setExtent((Extent)this.getExtent().clone()); + aPLS.setPartNum(this.getPartNum()); + aPLS.parts = (int[]) parts.clone(); + List points = new ArrayList<>(); + for (PointZ point : (List)this.getPoints()){ + points.add((PointZ)point.clone()); + } + aPLS.setPoints(points); + aPLS.setVisible(this.isVisible()); + aPLS.setSelected(this.isSelected()); + aPLS.setLegendIndex(this.getLegendIndex()); + //aPLS.ZRange = (double[])ZRange.Clone(); + //aPLS.MRange = (double[])MRange.Clone(); + //aPLS.ZArray = (double[])ZArray.Clone(); + //aPLS.MArray = (double[])MArray.Clone(); + + return aPLS; + } + + /** + * Value clone + * + * @return PolylineZShape object + */ + @Override + public Object valueClone() { + PolylineZShape aPLS = new PolylineZShape(); + aPLS.setValue(this.getValue()); + aPLS.setVisible(this.isVisible()); + aPLS.setSelected(this.isSelected()); + aPLS.setLegendIndex(this.getLegendIndex()); + + return aPLS; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/RectangleShape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/RectangleShape.java index 7c1ce496..4ec2f790 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/RectangleShape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/RectangleShape.java @@ -1,124 +1,125 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.shape; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; - -/** - * - * @author yaqiang - */ -public class RectangleShape extends PolygonShape { - // - private boolean round = false; - private double roundX = 0; - private double roundY = 0; - // - // - /** - * Constructor - */ - public RectangleShape(){ - super(); - } - - /** - * Constructor - * @param x X - * @param y Y - * @param width Width - * @param height Height - */ - public RectangleShape(double x, double y, double width, double height){ - super(); - List points = new ArrayList<>(); - points.add(new PointD(x, y)); - points.add(new PointD(x, y + height)); - points.add(new PointD(x + width, y + height)); - points.add(new PointD(x + width, y)); - this.setPoints(points); - } - // - // - @Override - public ShapeTypes getShapeType(){ - return ShapeTypes.Rectangle; - } - - /** - * Get is round or not - * @return Boolean - */ - public boolean isRound(){ - return this.round; - } - - /** - * Get round x - * @return Round x - */ - public double getRoundX(){ - return this.roundX; - } - - /** - * Set round y - * @param value Round y - */ - public void setRoundX(double value){ - this.roundX = value; - this.round = true; - } - - /** - * Get round y - * @return Round y - */ - public double getRoundY(){ - return this.roundY; - } - - /** - * Set round y - * @param value Round y - */ - public void setRoundY(double value){ - this.roundY = value; - this.round = true; - } - // - // - - /** - * Clone - * - * @return RectangleShape object - */ - @Override - public Object clone() { - RectangleShape aPGS = new RectangleShape(); - aPGS.setExtent(this.getExtent()); - aPGS.setPoints(new ArrayList<>(this.getPoints())); - aPGS.setVisible(this.isVisible()); - aPGS.setSelected(this.isSelected()); - aPGS.round = this.round; - aPGS.roundX = this.roundX; - aPGS.roundY = this.roundY; - - return aPGS; - } - // -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.shape; + +import org.meteoinfo.common.PointD; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author yaqiang + */ +public class RectangleShape extends PolygonShape { + // + private boolean round = false; + private double roundX = 0; + private double roundY = 0; + // + // + /** + * Constructor + */ + public RectangleShape(){ + super(); + } + + /** + * Constructor + * @param x X + * @param y Y + * @param width Width + * @param height Height + */ + public RectangleShape(double x, double y, double width, double height){ + super(); + List points = new ArrayList<>(); + points.add(new PointD(x, y)); + points.add(new PointD(x, y + height)); + points.add(new PointD(x + width, y + height)); + points.add(new PointD(x + width, y)); + this.setPoints(points); + } + // + // + @Override + public ShapeTypes getShapeType(){ + return ShapeTypes.Rectangle; + } + + /** + * Get is round or not + * @return Boolean + */ + public boolean isRound(){ + return this.round; + } + + /** + * Get round x + * @return Round x + */ + public double getRoundX(){ + return this.roundX; + } + + /** + * Set round y + * @param value Round y + */ + public void setRoundX(double value){ + this.roundX = value; + this.round = true; + } + + /** + * Get round y + * @return Round y + */ + public double getRoundY(){ + return this.roundY; + } + + /** + * Set round y + * @param value Round y + */ + public void setRoundY(double value){ + this.roundY = value; + this.round = true; + } + // + // + + /** + * Clone + * + * @return RectangleShape object + */ + @Override + public Object clone() { + RectangleShape aPGS = new RectangleShape(); + aPGS.setExtent(this.getExtent()); + aPGS.setPoints(new ArrayList<>(this.getPoints())); + aPGS.setVisible(this.isVisible()); + aPGS.setSelected(this.isSelected()); + aPGS.round = this.round; + aPGS.roundX = this.roundX; + aPGS.roundY = this.roundY; + + return aPGS; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Shape.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Shape.java index 503ea286..c5a7980f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Shape.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/Shape.java @@ -15,8 +15,7 @@ package org.meteoinfo.shape; import java.util.ArrayList; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; + import java.util.List; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; @@ -25,6 +24,8 @@ import org.locationtech.jts.geom.LinearRing; import org.locationtech.jts.operation.polygonize.Polygonizer; import org.locationtech.jts.operation.union.CascadedPolygonUnion; import org.locationtech.jts.operation.union.UnaryUnionOp; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; /** * Shape class diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ShapeUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ShapeUtil.java index 50f2d18a..f2aaa57d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ShapeUtil.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/shape/ShapeUtil.java @@ -1,323 +1,324 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.shape; - -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.PointD; -import org.meteoinfo.ndarray.Array; - -/** - * - * @author wyq - */ -public class ShapeUtil { - - /** - * Create point shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Point shapes - */ - public static List createPointShapes(List x, List y) { - double xx, yy; - PointShape ps; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.size(); i++) { - ps = new PointShape(); - xx = x.get(i).doubleValue(); - yy = y.get(i).doubleValue(); - ps.setPoint(new PointD(xx, yy)); - shapes.add(ps); - } - return shapes; - } - - /** - * Create point shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Point shapes - */ - public static List createPointShapes(Array x, Array y) { - double xx, yy; - PointShape ps; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.getSize(); i++) { - ps = new PointShape(); - xx = x.getDouble(i); - yy = y.getDouble(i); - ps.setPoint(new PointD(xx, yy)); - shapes.add(ps); - } - return shapes; - } - - /** - * Create PointZ shapes - * - * @param x X coordinates - * @param y Y coordinates - * @param z Z coordinates - * @param m M coordinates - * @return PointZ shapes - */ - public static List createPointShapes(Array x, Array y, Array z, Array m) { - double xx, yy; - PointZShape ps; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.getSize(); i++) { - ps = new PointZShape(); - xx = x.getDouble(i); - yy = y.getDouble(i); - - ps.setPoint(new PointZ(xx, yy, z.getDouble(i), m.getDouble(i))); - shapes.add(ps); - } - return shapes; - } - - /** - * Create polyline shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Polyline shapes - */ - public static List createPolylineShapes(List x, List y) { - double xx, yy; - List points = new ArrayList<>(); - PolylineShape pls; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.size(); i++) { - xx = x.get(i).doubleValue(); - yy = y.get(i).doubleValue(); - if (Double.isNaN(xx)) { - if (points.size() >= 2) { - pls = new PolylineShape(); - pls.setPoints(points); - shapes.add(pls); - } - points = new ArrayList<>(); - } else { - points.add(new PointD(xx, yy)); - } - } - if (points.size() >= 2) { - pls = new PolylineShape(); - pls.setPoints(points); - shapes.add(pls); - } - - return shapes; - } - - /** - * Create polyline shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Polyline shapes - */ - public static List createPolylineShapes(Array x, Array y) { - double xx, yy; - List points = new ArrayList<>(); - PolylineShape pls; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.getSize(); i++) { - xx = x.getDouble(i); - yy = y.getDouble(i); - if (Double.isNaN(xx)) { - if (points.size() >= 2) { - pls = new PolylineShape(); - pls.setPoints(points); - shapes.add(pls); - } - points = new ArrayList<>(); - } else { - points.add(new PointD(xx, yy)); - } - } - if (points.size() >= 2) { - pls = new PolylineShape(); - pls.setPoints(points); - shapes.add(pls); - } - - return shapes; - } - - /** - * Create polylineZ shapes - * - * @param x X coordinates - * @param y Y coordinates - * @param z Z coordinates - * @param m M coordinates - * @return PolylineZ shapes - */ - public static List createPolylineShapes(Array x, Array y, Array z, Array m) { - double xx, yy; - List points = new ArrayList<>(); - PolylineZShape pls; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.getSize(); i++) { - xx = x.getDouble(i); - yy = y.getDouble(i); - if (Double.isNaN(xx)) { - if (points.size() >= 2) { - pls = new PolylineZShape(); - pls.setPoints(points); - shapes.add(pls); - } - points = new ArrayList<>(); - } else { - points.add(new PointZ(xx, yy, z.getDouble(i), m.getDouble(i))); - } - } - if (points.size() >= 2) { - pls = new PolylineZShape(); - pls.setPoints(points); - shapes.add(pls); - } - - return shapes; - } - - /** - * Create polygon shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Polygon shapes - */ - public static List createPolygonShapes(List x, List y) { - double xx, yy; - List points = new ArrayList<>(); - PolygonShape pls; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.size(); i++) { - xx = x.get(i).doubleValue(); - yy = y.get(i).doubleValue(); - if (Double.isNaN(xx)) { - if (points.size() > 2) { - pls = new PolygonShape(); - pls.setPoints(points); - shapes.add(pls); - } - points = new ArrayList<>(); - } else { - points.add(new PointD(xx, yy)); - } - } - if (points.size() > 2) { - pls = new PolygonShape(); - pls.setPoints(points); - shapes.add(pls); - } - - return shapes; - } - - /** - * Create polygon shapes - * - * @param x X coordinates - * @param y Y coordinates - * @return Polygon shapes - */ - public static List createPolygonShapes(Array x, Array y) { - double xx, yy; - List points = new ArrayList<>(); - PolygonShape pls; - List shapes = new ArrayList<>(); - for (int i = 0; i < x.getSize(); i++) { - xx = x.getDouble(i); - yy = y.getDouble(i); - if (Double.isNaN(xx)) { - if (points.size() > 2) { - pls = new PolygonShape(); - pls.setPoints(points); - shapes.add(pls); - } - points = new ArrayList<>(); - } else { - points.add(new PointD(xx, yy)); - } - } - if (points.size() > 2) { - pls = new PolygonShape(); - pls.setPoints(points); - shapes.add(pls); - } - - return shapes; - } - - /** - * Create polygon shape - * - * @param x_p X coordinate list - * @param y_p Y coordinate list - * @return Polygon shape - */ - public static PolygonShape createPolygonShape(List x_p, List y_p) { - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - for (int i = 0; i < x_p.size(); i++) { - points.add(new PointD(x_p.get(i).doubleValue(), y_p.get(i).doubleValue())); - } - if (!points.get(points.size() - 1).equals(points.get(0))) { - points.add((PointD) points.get(0).clone()); - } - ps.setPoints(points); - - return ps; - } - - /** - * Create polygon shape - * - * @param xy X/Y coordinates - * @return Polygon shape - */ - public static PolygonShape createPolygonShape(List> xy) { - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - for (List xy1 : xy) { - points.add(new PointD(xy1.get(0).doubleValue(), xy1.get(1).doubleValue())); - } - if (!points.get(points.size() - 1).equals(points.get(0))) { - points.add((PointD) points.get(0).clone()); - } - ps.setPoints(points); - - return ps; - } - - /** - * Add a circle - * - * @param x Center x - * @param y Center y - * @param radius - * @return Graphic - */ - public static CircleShape createCircleShape(float x, float y, float radius) { - List points = new ArrayList<>(); - points.add(new PointD(x - radius, y)); - points.add(new PointD(x, y - radius)); - points.add(new PointD(x + radius, y)); - points.add(new PointD(x, y + radius)); - - CircleShape aPGS = new CircleShape(); - aPGS.setPoints(points); - - return aPGS; - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.shape; + +import java.util.ArrayList; +import java.util.List; + +import org.meteoinfo.common.PointD; +import org.meteoinfo.ndarray.Array; + +/** + * + * @author wyq + */ +public class ShapeUtil { + + /** + * Create point shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Point shapes + */ + public static List createPointShapes(List x, List y) { + double xx, yy; + PointShape ps; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.size(); i++) { + ps = new PointShape(); + xx = x.get(i).doubleValue(); + yy = y.get(i).doubleValue(); + ps.setPoint(new PointD(xx, yy)); + shapes.add(ps); + } + return shapes; + } + + /** + * Create point shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Point shapes + */ + public static List createPointShapes(Array x, Array y) { + double xx, yy; + PointShape ps; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.getSize(); i++) { + ps = new PointShape(); + xx = x.getDouble(i); + yy = y.getDouble(i); + ps.setPoint(new PointD(xx, yy)); + shapes.add(ps); + } + return shapes; + } + + /** + * Create PointZ shapes + * + * @param x X coordinates + * @param y Y coordinates + * @param z Z coordinates + * @param m M coordinates + * @return PointZ shapes + */ + public static List createPointShapes(Array x, Array y, Array z, Array m) { + double xx, yy; + PointZShape ps; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.getSize(); i++) { + ps = new PointZShape(); + xx = x.getDouble(i); + yy = y.getDouble(i); + + ps.setPoint(new PointZ(xx, yy, z.getDouble(i), m.getDouble(i))); + shapes.add(ps); + } + return shapes; + } + + /** + * Create polyline shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Polyline shapes + */ + public static List createPolylineShapes(List x, List y) { + double xx, yy; + List points = new ArrayList<>(); + PolylineShape pls; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.size(); i++) { + xx = x.get(i).doubleValue(); + yy = y.get(i).doubleValue(); + if (Double.isNaN(xx)) { + if (points.size() >= 2) { + pls = new PolylineShape(); + pls.setPoints(points); + shapes.add(pls); + } + points = new ArrayList<>(); + } else { + points.add(new PointD(xx, yy)); + } + } + if (points.size() >= 2) { + pls = new PolylineShape(); + pls.setPoints(points); + shapes.add(pls); + } + + return shapes; + } + + /** + * Create polyline shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Polyline shapes + */ + public static List createPolylineShapes(Array x, Array y) { + double xx, yy; + List points = new ArrayList<>(); + PolylineShape pls; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.getSize(); i++) { + xx = x.getDouble(i); + yy = y.getDouble(i); + if (Double.isNaN(xx)) { + if (points.size() >= 2) { + pls = new PolylineShape(); + pls.setPoints(points); + shapes.add(pls); + } + points = new ArrayList<>(); + } else { + points.add(new PointD(xx, yy)); + } + } + if (points.size() >= 2) { + pls = new PolylineShape(); + pls.setPoints(points); + shapes.add(pls); + } + + return shapes; + } + + /** + * Create polylineZ shapes + * + * @param x X coordinates + * @param y Y coordinates + * @param z Z coordinates + * @param m M coordinates + * @return PolylineZ shapes + */ + public static List createPolylineShapes(Array x, Array y, Array z, Array m) { + double xx, yy; + List points = new ArrayList<>(); + PolylineZShape pls; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.getSize(); i++) { + xx = x.getDouble(i); + yy = y.getDouble(i); + if (Double.isNaN(xx)) { + if (points.size() >= 2) { + pls = new PolylineZShape(); + pls.setPoints(points); + shapes.add(pls); + } + points = new ArrayList<>(); + } else { + points.add(new PointZ(xx, yy, z.getDouble(i), m.getDouble(i))); + } + } + if (points.size() >= 2) { + pls = new PolylineZShape(); + pls.setPoints(points); + shapes.add(pls); + } + + return shapes; + } + + /** + * Create polygon shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Polygon shapes + */ + public static List createPolygonShapes(List x, List y) { + double xx, yy; + List points = new ArrayList<>(); + PolygonShape pls; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.size(); i++) { + xx = x.get(i).doubleValue(); + yy = y.get(i).doubleValue(); + if (Double.isNaN(xx)) { + if (points.size() > 2) { + pls = new PolygonShape(); + pls.setPoints(points); + shapes.add(pls); + } + points = new ArrayList<>(); + } else { + points.add(new PointD(xx, yy)); + } + } + if (points.size() > 2) { + pls = new PolygonShape(); + pls.setPoints(points); + shapes.add(pls); + } + + return shapes; + } + + /** + * Create polygon shapes + * + * @param x X coordinates + * @param y Y coordinates + * @return Polygon shapes + */ + public static List createPolygonShapes(Array x, Array y) { + double xx, yy; + List points = new ArrayList<>(); + PolygonShape pls; + List shapes = new ArrayList<>(); + for (int i = 0; i < x.getSize(); i++) { + xx = x.getDouble(i); + yy = y.getDouble(i); + if (Double.isNaN(xx)) { + if (points.size() > 2) { + pls = new PolygonShape(); + pls.setPoints(points); + shapes.add(pls); + } + points = new ArrayList<>(); + } else { + points.add(new PointD(xx, yy)); + } + } + if (points.size() > 2) { + pls = new PolygonShape(); + pls.setPoints(points); + shapes.add(pls); + } + + return shapes; + } + + /** + * Create polygon shape + * + * @param x_p X coordinate list + * @param y_p Y coordinate list + * @return Polygon shape + */ + public static PolygonShape createPolygonShape(List x_p, List y_p) { + PolygonShape ps = new PolygonShape(); + List points = new ArrayList<>(); + for (int i = 0; i < x_p.size(); i++) { + points.add(new PointD(x_p.get(i).doubleValue(), y_p.get(i).doubleValue())); + } + if (!points.get(points.size() - 1).equals(points.get(0))) { + points.add((PointD) points.get(0).clone()); + } + ps.setPoints(points); + + return ps; + } + + /** + * Create polygon shape + * + * @param xy X/Y coordinates + * @return Polygon shape + */ + public static PolygonShape createPolygonShape(List> xy) { + PolygonShape ps = new PolygonShape(); + List points = new ArrayList<>(); + for (List xy1 : xy) { + points.add(new PointD(xy1.get(0).doubleValue(), xy1.get(1).doubleValue())); + } + if (!points.get(points.size() - 1).equals(points.get(0))) { + points.add((PointD) points.get(0).clone()); + } + ps.setPoints(points); + + return ps; + } + + /** + * Add a circle + * + * @param x Center x + * @param y Center y + * @param radius + * @return Graphic + */ + public static CircleShape createCircleShape(float x, float y, float radius) { + List points = new ArrayList<>(); + points.add(new PointD(x - radius, y)); + points.add(new PointD(x, y - radius)); + points.add(new PointD(x + radius, y)); + points.add(new PointD(x, y + radius)); + + CircleShape aPGS = new CircleShape(); + aPGS.setPoints(points); + + return aPGS; + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/table/ColumnData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/table/ColumnData.java index 3cc453d3..4faf74f4 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/table/ColumnData.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/table/ColumnData.java @@ -1,1196 +1,1196 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.table; - -import org.meteoinfo.ndarray.DataType; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import org.meteoinfo.global.util.JDateUtil; - -/** - * - * @author yaqiang - */ -public class ColumnData { - - // - private DataColumn dataColumn; - private List data; - - // - // - /** - * Constructor - * - * @param col The data column - */ - public ColumnData(DataColumn col) { - dataColumn = col; - switch (col.getDataType()) { - case INT: - data = new ArrayList(); - break; - case FLOAT: - data = new ArrayList(); - break; - case DOUBLE: - data = new ArrayList(); - break; - case STRING: - data = new ArrayList(); - break; - case DATE: - data = new ArrayList(); - break; - case BOOLEAN: - data = new ArrayList(); - break; - } - } - - /** - * Constructor - * - * @param colName Data column name - * @param type Data type - */ - public ColumnData(String colName, DataType type) { - this(new DataColumn(colName, type)); - } - - // - // - /** - * Get data column - * - * @return Data column - */ - public DataColumn getDataColumn() { - return this.dataColumn; - } - - /** - * Set data column - * - * @param value Data column - */ - public void setDataColumn(DataColumn value) { - dataColumn = value; - } - - /** - * Get data list - * - * @return Data list - */ - public List getData() { - return data; - } - - /** - * Set data list - * - * @param value Data list - */ - public void setData(List value) { - data = value; - } - - /** - * Get data type - * - * @return Data type - */ - public DataType getDataType() { - return dataColumn.getDataType(); - } - - // - // - /** - * Get size of the data - * - * @return Size of the data - */ - public int size() { - return data.size(); - } - - /** - * Add a object data - * - * @param value Data value - */ - public void addData(Object value) { - switch (dataColumn.getDataType()) { - case INT: - this.addData((Integer) value); - break; - case FLOAT: - this.addData((Float) value); - break; - case DOUBLE: - this.addData((Double) value); - break; - case STRING: - this.addData((String) value); - break; - case DATE: - this.addData((LocalDateTime) value); - break; - case BOOLEAN: - this.addData((Boolean) value); - break; - } - } - - /** - * Add a double data value - * - * @param value Data value - */ - public void addData(Double value) { - ((List) data).add(value); - } - - /** - * Add a float data value - * - * @param value Data value - */ - public void addData(Float value) { - ((List) data).add(value); - } - - /** - * Add a integer data value - * - * @param value Data value - */ - public void addData(Integer value) { - ((List) data).add(value); - } - - /** - * Add a string data value - * - * @param value Data value - */ - public void addData(String value) { - ((List) data).add(value); - } - - /** - * Add a date data value - * - * @param value Data value - */ - public void addData(LocalDateTime value) { - ((List) data).add(value); - } - - /** - * Add a boolean data value - * - * @param value Data value - */ - public void addData(boolean value) { - ((List) data).add(value); - } - - /** - * Get data value - * - * @param idx Data index - * @return Data value - */ - public Object getValue(int idx) { - switch (dataColumn.getDataType()) { - case INT: - return (Integer) data.get(idx); - case FLOAT: - return (Float) data.get(idx); - case DOUBLE: - return (Double) data.get(idx); - case STRING: - return (String) data.get(idx); - case DATE: - return (LocalDateTime) data.get(idx); - case BOOLEAN: - return (Boolean) data.get(idx); - } - - return null; - } - - /** - * Get string data list - * @return String data list - */ - public List getDataStrings(){ - List r = new ArrayList<>(); - for (Object v : data){ - r.add(v.toString()); - } - - return r; - } - - /** - * Get number data list - * - * @return Number data list - */ - public List getDataValues() { - if (dataColumn.getDataType() == DataType.DOUBLE) { - return ((List) data); - } else { - List values = new ArrayList<>(); - switch (dataColumn.getDataType()) { - case INT: - for (int v : (List) data) { - values.add(v); - } - break; - case FLOAT: - for (Object v : (List) data) { - if (v == null){ - values.add(Float.NaN); - } else { - values.add((float)v); - } - } - break; - case STRING: - for (String v : (List)data){ - if (v.isEmpty()) - values.add(Double.NaN); - else - values.add(Double.parseDouble(v)); - } - break; - case DATE: - for (LocalDateTime v : (List)data){ - values.add(JDateUtil.toOADate(v)); - } - break; - } - return values; - } - } - - /** - * Get valid number data list - * @return Number data list - */ - public List getValidDataValues(){ - List values = this.getDataValues(); - for (int i = 0, len = values.size(); i < len; i++) { - if (Double.isNaN(values.get(i).doubleValue())) { - values.remove(i); - len--; - i--; - } - } - - return values; - } - - /** - * Contains function - * - * @param value The object value - * @return Is contains or not - */ - public boolean contains(Object value) { - return data.contains(value); - } - - /** - * Mean function - * - * @return Mean value - */ - public Double mean() { - double mean = 0.0; - int n = 0; - switch (dataColumn.getDataType()) { - case INT: - for (int v : (List) data) { - mean += v; - n++; - } - break; - case FLOAT: - for (float v : (List) data) { - if (v != Float.NaN) { - mean += v; - n++; - } - } - break; - case DOUBLE: - for (double v : (List) data) { - if (v != Double.NaN) { - mean += v; - n++; - } - } - break; - } - - if (n > 0) { - mean = mean / n; - return mean; - } else { - return Double.NaN; - } - } - - /** - * Add function - * - * @param value The object value to add - * @param colName New column data name - * @return Result column data - */ - public ColumnData add(Object value, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = this.getDataType(value); - if (!inType.isNumeric()){ - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - rColData.addData((float)(Integer) this.getValue(i) + (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) + (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) + (Double) value); - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) + (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) + (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) + (Double) value); - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) + (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) + (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) + (Double) value); - } - break; - } - break; - } - - return rColData; - } - - /** - * Add function - * - * @param colData Anorther column data - * @param colName New column data name - * @return Result column data - */ - public ColumnData add(ColumnData colData, String colName) { - DataType thisType = dataColumn.getDataType(); - if (thisType == DataType.DATE || thisType == DataType.BOOLEAN) { - return null; - } - - DataType inType = colData.getDataType(); - if (inType == DataType.DATE || inType == DataType.BOOLEAN) { - return null; - } - - if (thisType == DataType.STRING && inType != DataType.STRING) { - return null; - } - - if (inType == DataType.STRING && thisType != DataType.STRING) { - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) + (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) + (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) + (Double) colData.getValue(i)); - } - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) + (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) + (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) + (Double) colData.getValue(i)); - } - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) + (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) + (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) + (Double) colData.getValue(i)); - } - } - break; - } - break; - case STRING: - rColData = new ColumnData(colName, DataType.STRING); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((String) this.getValue(i) + (String) colData.getValue(i)); - } - } - break; - } - - return rColData; - } - - /** - * Subtract function - * - * @param value The object value to subtract - * @param colName New column data name - * @return Result column data - */ - public ColumnData sub(Object value, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = this.getDataType(value); - if (!inType.isNumeric()){ - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - rColData.addData((float)(Integer) this.getValue(i) - (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) - (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) - (Double) value); - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) - (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) - (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) - (Double) value); - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) - (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) - (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) - (Double) value); - } - break; - } - break; - } - - return rColData; - } - - /** - * Subtract function - * - * @param colData Anorther column data - * @param colName New column data name - * @return Result column data - */ - public ColumnData sub(ColumnData colData, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = colData.getDataType(); - if (!inType.isNumeric()) { - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) - (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) - (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) - (Double) colData.getValue(i)); - } - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) - (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) - (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) - (Double) colData.getValue(i)); - } - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) - (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) - (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) - (Double) colData.getValue(i)); - } - } - break; - } - break; - } - - return rColData; - } - - /** - * Multiply function - * - * @param value The object value to multiply - * @param colName New column data name - * @return Result column data - */ - public ColumnData mul(Object value, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = this.getDataType(value); - if (!inType.isNumeric()){ - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - rColData.addData((float)(Integer) this.getValue(i) * (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) * (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) * (Double) value); - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) * (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) * (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) * (Double) value); - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) * (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) * (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) * (Double) value); - } - break; - } - break; - } - - return rColData; - } - - /** - * Multiply function - * - * @param colData Anorther column data - * @param colName New column data name - * @return Result column data - */ - public ColumnData mul(ColumnData colData, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = colData.getDataType(); - if (!inType.isNumeric()) { - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.INT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) * (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) * (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) * (Double) colData.getValue(i)); - } - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) * (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) * (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) * (Double) colData.getValue(i)); - } - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) * (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) * (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) * (Double) colData.getValue(i)); - } - } - break; - } - break; - } - - return rColData; - } - - /** - * Divide function - * - * @param colData Anorther column data - * @param colName New column data name - * @return Result column data - */ - public ColumnData div(ColumnData colData, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = colData.getDataType(); - if (!inType.isNumeric()) { - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((float)(Integer) this.getValue(i) / (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) / (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Integer) this.getValue(i) / (Double) colData.getValue(i)); - } - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) / (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) / (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Float) this.getValue(i) / (Double) colData.getValue(i)); - } - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) / (Integer) colData.getValue(i)); - } - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) / (Float) colData.getValue(i)); - } - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - if (i < colData.size()) { - rColData.addData((Double) this.getValue(i) / (Double) colData.getValue(i)); - } - } - break; - } - break; - } - - return rColData; - } - - /** - * Divide function - * - * @param value The object value to divide - * @param colName New column data name - * @return Result column data - */ - public ColumnData div(Object value, String colName) { - DataType thisType = dataColumn.getDataType(); - if (!thisType.isNumeric()) { - return null; - } - - DataType inType = this.getDataType(value); - if (!inType.isNumeric()){ - return null; - } - - ColumnData rColData = null; - int i; - switch (thisType) { - case INT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((float)(Integer) this.getValue(i) / (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) / (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Integer) this.getValue(i) / (Double) value); - } - break; - } - break; - case FLOAT: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) / (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.FLOAT); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) / (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Float) this.getValue(i) / (Double) value); - } - break; - } - break; - case DOUBLE: - switch (inType) { - case INT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) / (Integer) value); - } - break; - case FLOAT: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) / (Float) value); - } - break; - case DOUBLE: - rColData = new ColumnData(colName, DataType.DOUBLE); - for (i = 0; i < data.size(); i++) { - rColData.addData((Double) this.getValue(i) / (Double) value); - } - break; - } - break; - } - - return rColData; - } - - private DataType getDataType(Object value){ - if (value instanceof Integer) - return DataType.INT; - else if (value instanceof Float) - return DataType.FLOAT; - else if (value instanceof Double) - return DataType.DOUBLE; - else if (value instanceof Boolean) - return DataType.BOOLEAN; - else if (value instanceof String) - return DataType.STRING; - else if (value instanceof LocalDateTime) - return DataType.DATE; - else - return null; - } - // -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.table; + +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.ndarray.DataType; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author yaqiang + */ +public class ColumnData { + + // + private DataColumn dataColumn; + private List data; + + // + // + /** + * Constructor + * + * @param col The data column + */ + public ColumnData(DataColumn col) { + dataColumn = col; + switch (col.getDataType()) { + case INT: + data = new ArrayList(); + break; + case FLOAT: + data = new ArrayList(); + break; + case DOUBLE: + data = new ArrayList(); + break; + case STRING: + data = new ArrayList(); + break; + case DATE: + data = new ArrayList(); + break; + case BOOLEAN: + data = new ArrayList(); + break; + } + } + + /** + * Constructor + * + * @param colName Data column name + * @param type Data type + */ + public ColumnData(String colName, DataType type) { + this(new DataColumn(colName, type)); + } + + // + // + /** + * Get data column + * + * @return Data column + */ + public DataColumn getDataColumn() { + return this.dataColumn; + } + + /** + * Set data column + * + * @param value Data column + */ + public void setDataColumn(DataColumn value) { + dataColumn = value; + } + + /** + * Get data list + * + * @return Data list + */ + public List getData() { + return data; + } + + /** + * Set data list + * + * @param value Data list + */ + public void setData(List value) { + data = value; + } + + /** + * Get data type + * + * @return Data type + */ + public DataType getDataType() { + return dataColumn.getDataType(); + } + + // + // + /** + * Get size of the data + * + * @return Size of the data + */ + public int size() { + return data.size(); + } + + /** + * Add a object data + * + * @param value Data value + */ + public void addData(Object value) { + switch (dataColumn.getDataType()) { + case INT: + this.addData((Integer) value); + break; + case FLOAT: + this.addData((Float) value); + break; + case DOUBLE: + this.addData((Double) value); + break; + case STRING: + this.addData((String) value); + break; + case DATE: + this.addData((LocalDateTime) value); + break; + case BOOLEAN: + this.addData((Boolean) value); + break; + } + } + + /** + * Add a double data value + * + * @param value Data value + */ + public void addData(Double value) { + ((List) data).add(value); + } + + /** + * Add a float data value + * + * @param value Data value + */ + public void addData(Float value) { + ((List) data).add(value); + } + + /** + * Add a integer data value + * + * @param value Data value + */ + public void addData(Integer value) { + ((List) data).add(value); + } + + /** + * Add a string data value + * + * @param value Data value + */ + public void addData(String value) { + ((List) data).add(value); + } + + /** + * Add a date data value + * + * @param value Data value + */ + public void addData(LocalDateTime value) { + ((List) data).add(value); + } + + /** + * Add a boolean data value + * + * @param value Data value + */ + public void addData(boolean value) { + ((List) data).add(value); + } + + /** + * Get data value + * + * @param idx Data index + * @return Data value + */ + public Object getValue(int idx) { + switch (dataColumn.getDataType()) { + case INT: + return (Integer) data.get(idx); + case FLOAT: + return (Float) data.get(idx); + case DOUBLE: + return (Double) data.get(idx); + case STRING: + return (String) data.get(idx); + case DATE: + return (LocalDateTime) data.get(idx); + case BOOLEAN: + return (Boolean) data.get(idx); + } + + return null; + } + + /** + * Get string data list + * @return String data list + */ + public List getDataStrings(){ + List r = new ArrayList<>(); + for (Object v : data){ + r.add(v.toString()); + } + + return r; + } + + /** + * Get number data list + * + * @return Number data list + */ + public List getDataValues() { + if (dataColumn.getDataType() == DataType.DOUBLE) { + return ((List) data); + } else { + List values = new ArrayList<>(); + switch (dataColumn.getDataType()) { + case INT: + for (int v : (List) data) { + values.add(v); + } + break; + case FLOAT: + for (Object v : (List) data) { + if (v == null){ + values.add(Float.NaN); + } else { + values.add((float)v); + } + } + break; + case STRING: + for (String v : (List)data){ + if (v.isEmpty()) + values.add(Double.NaN); + else + values.add(Double.parseDouble(v)); + } + break; + case DATE: + for (LocalDateTime v : (List)data){ + values.add(JDateUtil.toOADate(v)); + } + break; + } + return values; + } + } + + /** + * Get valid number data list + * @return Number data list + */ + public List getValidDataValues(){ + List values = this.getDataValues(); + for (int i = 0, len = values.size(); i < len; i++) { + if (Double.isNaN(values.get(i).doubleValue())) { + values.remove(i); + len--; + i--; + } + } + + return values; + } + + /** + * Contains function + * + * @param value The object value + * @return Is contains or not + */ + public boolean contains(Object value) { + return data.contains(value); + } + + /** + * Mean function + * + * @return Mean value + */ + public Double mean() { + double mean = 0.0; + int n = 0; + switch (dataColumn.getDataType()) { + case INT: + for (int v : (List) data) { + mean += v; + n++; + } + break; + case FLOAT: + for (float v : (List) data) { + if (v != Float.NaN) { + mean += v; + n++; + } + } + break; + case DOUBLE: + for (double v : (List) data) { + if (v != Double.NaN) { + mean += v; + n++; + } + } + break; + } + + if (n > 0) { + mean = mean / n; + return mean; + } else { + return Double.NaN; + } + } + + /** + * Add function + * + * @param value The object value to add + * @param colName New column data name + * @return Result column data + */ + public ColumnData add(Object value, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = this.getDataType(value); + if (!inType.isNumeric()){ + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + rColData.addData((float)(Integer) this.getValue(i) + (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) + (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) + (Double) value); + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) + (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) + (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) + (Double) value); + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) + (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) + (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) + (Double) value); + } + break; + } + break; + } + + return rColData; + } + + /** + * Add function + * + * @param colData Anorther column data + * @param colName New column data name + * @return Result column data + */ + public ColumnData add(ColumnData colData, String colName) { + DataType thisType = dataColumn.getDataType(); + if (thisType == DataType.DATE || thisType == DataType.BOOLEAN) { + return null; + } + + DataType inType = colData.getDataType(); + if (inType == DataType.DATE || inType == DataType.BOOLEAN) { + return null; + } + + if (thisType == DataType.STRING && inType != DataType.STRING) { + return null; + } + + if (inType == DataType.STRING && thisType != DataType.STRING) { + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) + (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) + (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) + (Double) colData.getValue(i)); + } + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) + (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) + (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) + (Double) colData.getValue(i)); + } + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) + (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) + (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) + (Double) colData.getValue(i)); + } + } + break; + } + break; + case STRING: + rColData = new ColumnData(colName, DataType.STRING); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((String) this.getValue(i) + (String) colData.getValue(i)); + } + } + break; + } + + return rColData; + } + + /** + * Subtract function + * + * @param value The object value to subtract + * @param colName New column data name + * @return Result column data + */ + public ColumnData sub(Object value, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = this.getDataType(value); + if (!inType.isNumeric()){ + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + rColData.addData((float)(Integer) this.getValue(i) - (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) - (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) - (Double) value); + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) - (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) - (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) - (Double) value); + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) - (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) - (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) - (Double) value); + } + break; + } + break; + } + + return rColData; + } + + /** + * Subtract function + * + * @param colData Anorther column data + * @param colName New column data name + * @return Result column data + */ + public ColumnData sub(ColumnData colData, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = colData.getDataType(); + if (!inType.isNumeric()) { + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) - (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) - (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) - (Double) colData.getValue(i)); + } + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) - (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) - (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) - (Double) colData.getValue(i)); + } + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) - (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) - (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) - (Double) colData.getValue(i)); + } + } + break; + } + break; + } + + return rColData; + } + + /** + * Multiply function + * + * @param value The object value to multiply + * @param colName New column data name + * @return Result column data + */ + public ColumnData mul(Object value, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = this.getDataType(value); + if (!inType.isNumeric()){ + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + rColData.addData((float)(Integer) this.getValue(i) * (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) * (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) * (Double) value); + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) * (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) * (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) * (Double) value); + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) * (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) * (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) * (Double) value); + } + break; + } + break; + } + + return rColData; + } + + /** + * Multiply function + * + * @param colData Anorther column data + * @param colName New column data name + * @return Result column data + */ + public ColumnData mul(ColumnData colData, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = colData.getDataType(); + if (!inType.isNumeric()) { + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.INT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) * (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) * (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) * (Double) colData.getValue(i)); + } + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) * (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) * (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) * (Double) colData.getValue(i)); + } + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) * (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) * (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) * (Double) colData.getValue(i)); + } + } + break; + } + break; + } + + return rColData; + } + + /** + * Divide function + * + * @param colData Anorther column data + * @param colName New column data name + * @return Result column data + */ + public ColumnData div(ColumnData colData, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = colData.getDataType(); + if (!inType.isNumeric()) { + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((float)(Integer) this.getValue(i) / (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) / (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Integer) this.getValue(i) / (Double) colData.getValue(i)); + } + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) / (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) / (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Float) this.getValue(i) / (Double) colData.getValue(i)); + } + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) / (Integer) colData.getValue(i)); + } + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) / (Float) colData.getValue(i)); + } + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + if (i < colData.size()) { + rColData.addData((Double) this.getValue(i) / (Double) colData.getValue(i)); + } + } + break; + } + break; + } + + return rColData; + } + + /** + * Divide function + * + * @param value The object value to divide + * @param colName New column data name + * @return Result column data + */ + public ColumnData div(Object value, String colName) { + DataType thisType = dataColumn.getDataType(); + if (!thisType.isNumeric()) { + return null; + } + + DataType inType = this.getDataType(value); + if (!inType.isNumeric()){ + return null; + } + + ColumnData rColData = null; + int i; + switch (thisType) { + case INT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((float)(Integer) this.getValue(i) / (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) / (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Integer) this.getValue(i) / (Double) value); + } + break; + } + break; + case FLOAT: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) / (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.FLOAT); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) / (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Float) this.getValue(i) / (Double) value); + } + break; + } + break; + case DOUBLE: + switch (inType) { + case INT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) / (Integer) value); + } + break; + case FLOAT: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) / (Float) value); + } + break; + case DOUBLE: + rColData = new ColumnData(colName, DataType.DOUBLE); + for (i = 0; i < data.size(); i++) { + rColData.addData((Double) this.getValue(i) / (Double) value); + } + break; + } + break; + } + + return rColData; + } + + private DataType getDataType(Object value){ + if (value instanceof Integer) + return DataType.INT; + else if (value instanceof Float) + return DataType.FLOAT; + else if (value instanceof Double) + return DataType.DOUBLE; + else if (value instanceof Boolean) + return DataType.BOOLEAN; + else if (value instanceof String) + return DataType.STRING; + else if (value instanceof LocalDateTime) + return DataType.DATE; + else + return null; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataColumn.java b/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataColumn.java index 0cf8e3fa..63314c8c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataColumn.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataColumn.java @@ -16,7 +16,7 @@ package org.meteoinfo.table; import java.time.format.DateTimeFormatter; import java.time.LocalDateTime; -import org.meteoinfo.global.util.JDateUtil; +import org.meteoinfo.common.util.JDateUtil; import org.meteoinfo.ndarray.DataType; /** diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataTable.java b/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataTable.java index baada3bd..545b5346 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataTable.java +++ b/MeteoInfoLib/src/main/java/org/meteoinfo/table/DataTable.java @@ -1,1613 +1,1613 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.table; - -import org.meteoinfo.ndarray.DataType; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.meteoinfo.data.TableUtil; -import org.meteoinfo.data.mapdata.Field; -import org.meteoinfo.global.MIMath; -import ucar.ma2.Range; - -/** - * - * @author Yaqiang Wang - */ -public class DataTable { - - protected DataRowCollection rows; - protected DataColumnCollection columns; - protected String tableName; - protected boolean readOnly = false; - protected int nextRowIndex = 0; -//private DataExpression dataExpression; - protected Object tag; - - /** - * Constructor - */ - public DataTable() { - this.columns = new DataColumnCollection(); - this.rows = new DataRowCollection(); - this.rows.setColumns(columns); - //dataExpression = new DataExpression(this); - } - - /** - * Constructor - * - * @param dataTableName The data table name - */ - public DataTable(String dataTableName) { - this(); - this.tableName = dataTableName; - } - - /** - * Get total row count - * - * @return Row number - */ - public int getTotalCount() { - return rows.size(); - } - - /** - * Get row count - * - * @return Row count - */ - public int getRowCount() { - return rows.size(); - } - - /** - * Get column count - * - * @return Column count - */ - public int getColumnCount() { - return columns.size(); - } - - /** - * Get if is read only - * - * @return Boolean - */ - public boolean isReadOnly() { - return this.readOnly; - } - - /** - * Set if is read only - * - * @param readOnly Read only - */ - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - /** - * Get table name - * - * @return Table name - */ - public String getTableName() { - return this.tableName; - } - - /** - * Set tabel name - * - * @param tableName Table name - */ - public void setTableName(String tableName) { - this.tableName = tableName; - } - - /** - * Get data rows - * - * @return DataRowCollection The data rows - */ - public DataRowCollection getRows() { - return this.rows; - } - - /** - * Get data rows - * - * @param idx Index - * @return DataRowCollection The data rows - */ - public DataRowCollection getRows(List idx) { - DataRowCollection r = new DataRowCollection(); - for (int i : idx){ - r.add(this.rows.get(i)); - } - return r; - } - - /** - * Get data rows - * - * @param range Range - * @return DataRowCollection The data rows - */ - public DataRowCollection getRows(Range range) { - DataRowCollection r = new DataRowCollection(); - for (int i = range.first(); i < range.last(); i++){ - r.add(this.rows.get(i)); - } - return r; - } - - /** - * Get data columns - * - * @return The data columns - */ - public DataColumnCollection getColumns() { - return this.columns; - } - - /** - * Get column names - * - * @return Column names - */ - public List getColumnNames() { - return this.columns.getColumnNames(); - } - - /** - * Get the value by row index and column name - * - * @param row Row index - * @param colName Column name - * @return Object The value - */ - public Object getValue(int row, String colName) { - return this.rows.get(row).getValue(colName); - } - - /** - * Get the value by row and column index - * - * @param row Row index - * @param col Column index - * @return Object The value - */ - public Object getValue(int row, int col) { - return this.rows.get(row).getValue(col); - } - - /** - * Create a new data row - * - * @return DataRow The new data row - * @throws java.lang.Exception - */ - public DataRow newRow() throws Exception { - DataRow tempRow = new DataRow(this); - nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() - : nextRowIndex; - tempRow.setColumns(this.columns); - tempRow.setRowIndex(nextRowIndex++); - for (DataColumn col : columns) { - switch (col.getDataType()) { - case STRING: - tempRow.setValue(col.getColumnName(), ""); - break; - case DATE: - tempRow.setValue(col.getColumnName(), LocalDateTime.now()); - break; - case BOOLEAN: - tempRow.setValue(col.getColumnName(), Boolean.TRUE); - break; - default: - tempRow.setValue(col.getColumnName(), 0); - break; - } - } - return tempRow; - } - - /** - * Set a vlaue by row and column index - * - * @param row Row index - * @param col Column index - * @param value The value - */ - public void setValue(int row, int col, Object value) { - this.rows.get(row).setValue(col, value); - } - - /** - * Set a value - * - * @param row Row index - * @param colName Column name - * @param value The value - */ - public void setValue(int row, String colName, Object value) { - this.rows.get(row).setValue(colName, value); - } - - /** - * Set values - * - * @param colName Column name - * @param values Values - */ - public void setValues(String colName, List values) { - for (int i = 0; i < values.size(); i++) { - this.rows.get(i).setValue(colName, values.get(i)); - } - } - - /** - * Set tag - * - * @param tag The tag - */ - public void setTag(Object tag) { - this.tag = tag; - } - - /** - * Get tag - * - * @return the tag - */ - public Object getTag() { - return tag; - } - - /** - * Find column by name - * - * @param colName The column name - * @return The data column - */ - public DataColumn findColumn(String colName) { - if (colName == null) - return null; - - for (DataColumn col : this.columns) { - if (col.getColumnName().equals(colName)) { - return col; - } - } - - return null; - } - - /** - * Get data columns by names - * - * @param colNames Data column names - * @return Data columns - */ - public List findColumns(List colNames) { - List cols = new ArrayList<>(); - for (DataColumn col : this.getColumns()) { - for (String colName : colNames) { - if (col.getColumnName().equals(colName)) { - cols.add(col); - break; - } - } - } - - return cols; - } - - /** - * Get data columns by index - * - * @param colIndex Data column index - * @return Data columns - */ - public List findColumns_Index(List colIndex) { - List cols = new ArrayList<>(); - int n = this.getColumnCount(); - for (int i : colIndex) { - if (i < 0) - i = n + i; - if (i < n) - cols.add(this.columns.get(i)); - } - - return cols; - } - - /** - * Check if the table has time column - * @return Boolean - */ - public boolean hasTimeColumn(){ - for (DataColumn col : this.columns){ - if (col.getDataType() == DataType.DATE){ - return true; - } - } - return false; - } - - /** - * Add a data column - * - * @param columnName Data column name - * @param dataType Data type - * @return The data column - * @throws Exception - */ - public DataColumn addColumn(String columnName, DataType dataType) throws Exception { - DataColumn col = new DataColumn(columnName, dataType); - addColumn(col); - return col; - } - - /** - * Add a data column - * - * @param index The index - * @param columnName Data column name - * @param dataType Data type - * @return The data column - * @throws Exception - */ - public DataColumn addColumn(int index, String columnName, DataType dataType) throws Exception { - DataColumn col = new DataColumn(columnName, dataType); - addColumn(index, col); - return col; - } - - /** - * Add a data column by index - * - * @param index The index - * @param column Data column - */ - public void addColumn(int index, DataColumn column) { - this.columns.add(index, column); - for (DataRow row : this.rows) { - row.setColumns(columns); - row.addColumn(column); - } - } - - /** - * Add a data column - * - * @param column Data column - */ - public void addColumn(DataColumn column) { - this.columns.add(column); - for (DataRow row : this.rows) { - row.setColumns(columns); - row.addColumn(column); - } - } - - /** - * Remove a data column - * - * @param column The data column - */ - public void removeColumn(DataColumn column) { - this.columns.remove(column); - for (DataRow row : this.rows) { - row.setColumns(columns); - row.removeColumn(column); - } - } - - /** - * Rename column - * - * @param column The column - * @param fieldName The new column name - */ - public void renameColumn(DataColumn column, String fieldName) { - String oldName = column.getColumnName(); - this.columns.renameColumn(column, fieldName); - for (DataRow row : this.rows) { - row.setColumns(columns); - row.renameColumn(oldName, fieldName); - } - } - - /** - * Rename column - * - * @param oldName The old column name - * @param newName The new column name - */ - public void renameColumn(String oldName, String newName) { - DataColumn column = findColumn(oldName); - this.columns.renameColumn(column, newName); - for (DataRow row : this.rows) { - row.setColumns(columns); - row.renameColumn(oldName, newName); - } - } - - /** - * Rename column - * - * @param colIdx The column index - * @param fieldName The new column name - */ - public void renameColumn(int colIdx, String fieldName) { - DataColumn column = this.columns.get(colIdx); - this.renameColumn(column, fieldName); - } - - /** - * Add a data row - * - * @param row The data row - * @return Boolean - * @throws Exception - */ - public boolean addRow(DataRow row) throws Exception { - nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() - : nextRowIndex; - row.setColumns(this.columns); - row.setRowIndex(nextRowIndex++); - row.setTable(this); - return this.rows.add(row); - } - - /** - * Add data row - * - * @return Data row - * @throws Exception - */ - public DataRow addRow() throws Exception { - DataRow row = new DataRow(); - this.addRow(row); - return row; - } - - /** - * Add data rows - * - * @param rows Data rows - * @throws Exception - */ - public void addRows(List rows) throws Exception { - for (DataRow row : rows) { - addRow(row); - } - } - - /** - * Append a data row - * - * @param row Data row - * @return Boolean - */ - public boolean appendRow(DataRow row) { - List colNames = row.getColumns().getColumnNames(); - nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() - : nextRowIndex; - row.setColumns(this.columns); - row.setRowIndex(nextRowIndex++); - row.setTable(this); - for (DataColumn col : this.columns) { - if (!colNames.contains(col.getColumnName())) { - row.setValue(col, null); - } - } - return this.rows.add(row); - } - - /** - * Remove a row - * - * @param rowIdx Row index - */ - public void removeRow(int rowIdx) { - this.rows.remove(rowIdx); - } - - /** - * Remove a row - * - * @param row The row will be removed - */ - public void removeRow(DataRow row) { - this.rows.remove(row); - } - - /** - * Remove rows - * - * @param rows The rows will be removed - */ - public void removeRows(List rows) { - this.rows.removeAll(rows); - } - - /** - * Set data rows - * - * @param rows The data rows - */ - public void setRows(List rows) { - this.rows.clear(); - for (DataRow row : rows) { - this.rows.add(row); - } - } - - /** - * Add column data - * - * @param col The column - * @param colData The column data - * @throws Exception - */ - public void setColumnData(DataColumn col, List colData) throws Exception { - if (this.getRowCount() == 0) { - for (int i = 0; i < colData.size(); i++){ - DataRow row = this.addRow(); - row.setValue(col, colData.get(i)); - } - } else { - int i = 0; - for (DataRow row : this.rows) { - if (i < colData.size()) { - row.setValue(col, colData.get(i)); - } - i++; - } - } - } - - /** - * Add column data - * - * @param colName Column name - * @param colData The column data - * @throws Exception - */ - public void setColumnData(String colName, List colData) throws Exception { - DataColumn col = this.findColumn(colName); - if (col == null){ - System.out.println("The column not exists: " + colName + "!"); - return; - } - - setColumnData(col, colData); - } - - /** - * Add column data - * - * @param colData The column data - * @throws Exception - */ - public void addColumnData(ColumnData colData) throws Exception { - DataColumn col = this.addColumn(colData.getDataColumn().getColumnName(), colData.getDataType()); - int i = 0; - for (DataRow row : this.rows) { - if (i < colData.size()) { - row.setValue(col, colData.getValue(i)); - } - i++; - } - } - - /** - * Add column data - * - * @param colName Column name - * @param dataType Data type - * @param colData The column data - * @throws Exception - */ - public void addColumnData(String colName, DataType dataType, List colData) throws Exception { - DataColumn col = this.addColumn(colName, dataType); - setColumnData(col, colData); - } - - /** - * Add column data - * - * @param index Column index - * @param colName Column name - * @param dataType Data type - * @param colData The column data - * @throws Exception - */ - public void addColumnData(int index, String colName, DataType dataType, List colData) throws Exception { - DataColumn col = this.addColumn(index, colName, dataType); - setColumnData(col, colData); - } - - /** - * Add column data - * - * @param colName Column name - * @param dt Data type string - * @param colData The column data - * @throws Exception - */ - public void addColumnData(String colName, String dt, List colData) throws Exception { - DataType dataType = TableUtil.toDataTypes(dt); - this.addColumnData(colName, dataType, colData); - } - - /** - * Get column data - * - * @param colName The column name - * @return Column data - */ - public ColumnData getColumnData(String colName) { - return this.getColumnData(this.getRows(), colName); - } - - /** - * Get column data - * - * @param col The data column - * @return Column data - */ - public ColumnData getColumnData(DataColumn col) { - return this.getColumnData(col.getColumnName()); - } - - /** - * Get column data - * - * @param rows The data row list - * @param colName The data column name - * @return Column values - */ - public ColumnData getColumnData(List rows, String colName) { - ColumnData colData = new ColumnData(this.findColumn(colName)); - for (DataRow row : rows) { - colData.addData(row.getValue(colName)); - } - - return colData; - } - - /** - * Select data rows - * - * @param expression SQL expression - * @return Selected data rows - */ - public List select(String expression) { - SQLExpression e = new SQLExpression(expression); - List dataRows = new ArrayList<>(); - for (int i = 0; i < this.rows.size(); i++) { - DataRow row = this.rows.get(i); - row.setRowIndex(i); - if (e.eval(row.getItemMap())) { - dataRows.add(row); - } - } - - return dataRows; - } - - /** - * Select and form a new data table - * - * @param expression SQL expression - * @param dataColumns Data columns - * @return Selected data table - */ - public DataTable select(String expression, DataColumn[] dataColumns) { - DataTable result = new DataTable(); - List dataRows = this.select(expression); - for (DataColumn dc : dataColumns) { - DataColumn newDc = (DataColumn)dc.clone(); - result.columns.add(newDc); - } - - for (DataRow r : dataRows) { - try { - DataRow newRow = result.newRow(); - newRow.copyFrom(r); - result.addRow(newRow); - } catch (Exception ex) { - Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - return result; - } - - /** - * Get a new table by row range - * @param rowRange Row range - * @return - * @throws Exception - */ - public DataTable select(Range rowRange) throws Exception{ - return select(rowRange.first(), rowRange.last(), rowRange.stride()); - } - - /** - * Get a new table by select rows - * @param r_start row start - * @param r_stop row stop - * @param r_step row step - * @return Result table - * @throws Exception - */ - public DataTable select(int r_start, int r_stop, int r_step) throws Exception { - DataTable r = new DataTable(); - for (DataColumn dc : this.columns) { - DataColumn newDc = (DataColumn)dc.clone(); - r.columns.add(newDc); - } - - for (int i = r_start; i < r_stop; i+=r_step) { - if (i >= this.getRowCount()) - break; - DataRow newRow = r.newRow(); - newRow.copyFrom(this.rows.get(i)); - r.addRow(newRow); - } - - return r; - } - - /** - * Get a new table by row index - * @param rowIndex Row index - * @return Result table - * @throws Exception - */ - public DataTable select(List rowIndex) throws Exception { - DataTable r = new DataTable(); - for (DataColumn dc : this.columns) { - DataColumn newDc = (DataColumn)dc.clone(); - r.columns.add(newDc); - } - - for (int i : rowIndex) { - if (i >= this.getRowCount()) - break; - DataRow newRow = r.newRow(); - newRow.copyFrom(this.rows.get(i)); - r.addRow(newRow); - } - - return r; - } - - /** - * Get a new table by row range and column range - * @param rowRange Row range - * @param colRange Column range - * @return Result table - * @throws Exception - */ - public DataTable select(Range rowRange, Range colRange) throws Exception { - return select(rowRange.first(), rowRange.last(), rowRange.stride(), colRange.first(), colRange.last(), colRange.stride()); - } - - /** - * Get a new table by select rows - * @param r_start Row start - * @param r_stop Row stop - * @param r_step Row step - * @param c_start Column start - * @param c_stop Column stop - * @param c_step Column step - * @return Result table - * @throws Exception - */ - public DataTable select(int r_start, int r_stop, int r_step, int c_start, int c_stop, int c_step) throws Exception { - List cols = new ArrayList<>(); - for (int i = c_start; i < c_stop; i+= c_step){ - if (i >= this.getColumnCount()) - break; - cols.add(this.columns.get(i)); - } - - return this.select(r_start, r_stop, r_step, cols); - } - - /** - * Get a new table by row index and column range - * @param rowIndex Row index - * @param colRange Column range - * @return Result table - * @throws Exception - */ - public DataTable select(List rowIndex, Range colRange) throws Exception { - return select(rowIndex, colRange.first(), colRange.last(), colRange.stride()); - } - - /** - * Get a new table by row index and column slice - * @param rowIndex Row index - * @param c_start Column start - * @param c_stop Column stop - * @param c_step Column step - * @return Result table - * @throws Exception - */ - public DataTable select(List rowIndex, int c_start, int c_stop, int c_step) throws Exception { - List cols = new ArrayList<>(); - for (int i = c_start; i < c_stop; i+= c_step){ - if (i >= this.getColumnCount()) - break; - cols.add(this.columns.get(i)); - } - - return this.select(rowIndex, cols); - } - - /** - * Get a new table by row range and columns - * @param rowRange Row range - * @param cols Columns - * @return Result table - * @throws Exception - */ - public DataTable select(Range rowRange, List cols) throws Exception { - return select(rowRange.first(), rowRange.last(), rowRange.stride(), cols); - } - - /** - * Get a new table by select rows - * @param r_start Row start - * @param r_stop Row stop - * @param r_step Row step - * @param cols Columns - * @return Result table - * @throws Exception - */ - public DataTable select(int r_start, int r_stop, int r_step, List cols) throws Exception { - DataTable r = new DataTable(); - for (DataColumn dc : cols) { - DataColumn newDc = (DataColumn)dc.clone(); - r.columns.add(newDc); - } - - DataColumnCollection dcc = new DataColumnCollection(cols); - for (int i = r_start; i < r_stop; i+=r_step) { - if (i >= this.getRowCount()) - break; - DataRow newRow = this.rows.get(i).colSelect(dcc); - r.addRow(newRow); - } - - return r; - } - - /** - * Get a new table by row index and columns - * @param rowIndex Row index - * @param cols Columns - * @return Result table - * @throws Exception - */ - public DataTable select(List rowIndex, List cols) throws Exception { - DataTable r = new DataTable(); - for (DataColumn dc : cols) { - DataColumn newDc = (DataColumn)dc.clone(); - r.columns.add(newDc); - } - - DataColumnCollection dcc = new DataColumnCollection(cols); - for (int i : rowIndex) { - if (i >= this.getRowCount()) - break; - DataRow newRow = this.rows.get(i).colSelect(dcc); - r.addRow(newRow); - } - - return r; - } - - /** - * Create a new data table using selected columns - * @param cols The columns - * @return Selected data table - * @throws java.lang.Exception - */ - public DataTable colSelect(List cols) throws Exception { - DataTable r = new DataTable(); - for (DataColumn dc : cols) { - DataColumn newDc = (DataColumn)dc.clone(); - r.columns.add(dc); - } - - DataColumnCollection dcc = new DataColumnCollection(cols); - for (DataRow dr : this.rows) { - DataRow ndr = dr.colSelect(dcc); - r.addRow(ndr); - } - - return r; - } - - /** - * Select and form a new data table - * - * @param expression SQL expression - * @return Selected data table - */ - public DataTable sqlSelect(String expression) { - DataTable result = new DataTable(); - List dataRows = this.select(expression); - for (DataColumn dc : this.columns) { - DataColumn newDc = (DataColumn)dc.clone(); - result.columns.add(newDc); - } - - for (DataRow r : dataRows) { - try { - DataRow newRow = result.newRow(); - newRow.copyFrom(r); - result.addRow(newRow); - } catch (Exception ex) { - Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - return result; - } - -// //以下为数据表扩展方法实现集合 -// /** -// * 功能描述: 返回符合过滤条件的数据行集合,并返回 -// * @param -// * @return: DataTable -// */ -// public List select(String filterString) { -// List rows = new ArrayList(); -// if (StringUtil.isNotEmpty(filterString)) { -// for (Object row : this.rows) { -// DataRow currentRow = (DataRow) row; -// if ((Boolean) dataExpression.compute(filterString, -// currentRow.getItemMap())) { -// rows.add(currentRow); -// } -// } -// return rows; -// } else { -// return this.rows; -// } -// } -// /** -// * 功能描述: 对当前表进行查询 过滤,并返回指定列集合拼装的DataTable对象 -// * @param -// * @return: DataTable -// */ -// public DataTable select(String filterString, -// String[] columns, -// boolean distinct) throws Exception { -// DataTable result = new DataTable(); -// List rows = select(filterString); -// //构造表结构 -// for (String c : columns) { -// DataColumn dc = this.columns.get(c); -// DataColumn newDc = new DataColumn(dc.getColumnName(), -// dc.getDataType()); -// newDc.setCaptionName(dc.getCaptionName()); -// result.columns.add(newDc); -// } -// //填充数据 -// for (DataRow r : rows) { -// DataRow newRow = result.newRow(); -// newRow.copyFrom(r); -// result.addRow(newRow); -// } -// return result; -// } -// /** -// * 功能描述: 根据指定表达式对符合过滤条件的数据进行计算 -// * @param -// * @return: Object -// * @author: James Cheung -// * @version: 2.0 -// */ -// public Object compute(String expression, -// String filter) { -// return dataExpression.compute(expression, select(filter)); -// } - public Object max(String columns, - String filter) { - return null; - } - - public Object min(String columns, - String filter) { - return null; - } - - public Object avg(String columns, - String filter) { - return null; - } - - public Object max(String columns, - String filter, - String groupBy) { - return null; - } - - public Object min(String columns, - String filter, - String groupBy) { - return null; - } - - public Object avg(String columns, - String filter, - String groupBy) { - return null; - } - - /** - * Clone - * - * @return Cloned DataTable object - */ - @Override - public Object clone() { - DataTable table = new DataTable(); - table.tableName = this.tableName; - table.tag = this.tag; - table.readOnly = this.readOnly; - for (DataColumn col : this.columns) { - DataColumn newcol = (DataColumn) col.clone(); - //newcol.setTable(table); - table.addColumn(new Field(newcol)); - } - - for (DataRow row : this.rows) { - try { - DataRow newrow = this.newRow(); - newrow.copyFrom(row); - table.addRow(newrow); - } catch (Exception ex) { - Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - return table; - } - - /** - * Clone table - Vectorlayer with fields - * - * @return DataTable - */ - public DataTable cloneTable_Field() { - DataTable table = new DataTable(); - table.tableName = this.tableName; - table.tag = this.tag; - table.readOnly = this.readOnly; - for (DataColumn col : this.columns) { - Field newcol = new Field(col.getColumnName(), col.getDataType()); - newcol.setCaptionName(col.getCaptionName()); - newcol.setColumnIndex(col.getColumnIndex()); - newcol.setReadOnly(col.isReadOnly()); - //newcol.setTable(table); - table.addColumn(newcol); - } - - for (DataRow row : this.rows) { - try { - DataRow newrow = this.newRow(); - newrow.copyFrom(row); - table.addRow(newrow); - } catch (Exception ex) { - Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); - } - } - - return table; - } - - /** - * Convert to string - head - * - * @param n Head row number - * @return The string - */ - public String head(int n) { - StringBuilder sb = new StringBuilder(); - for (DataColumn col : this.columns) { - if (sb.length() == 0) { - sb.append(col.getColumnName()); - } else { - sb.append("\t"); - sb.append(col.getColumnName()); - } - } - sb.append("\n"); - - DateTimeFormatter format; - int rn = this.getRowCount(); - if (n > rn) { - n = rn; - } - Object v; - for (int r = 0; r < n; r++) { - DataRow row = this.rows.get(r); - int i = 0; - for (DataColumn col : this.columns) { - if (i > 0) { - sb.append("\t"); - } - switch (col.getDataType()) { - case DATE: - format = DateTimeFormatter.ofPattern(col.getFormat()); - sb.append(format.format((LocalDateTime) row.getValue(col.getColumnName()))); - break; - case STRING: - sb.append("'").append(row.getValue(col.getColumnName()).toString()).append("'"); - break; - default: - v = row.getValue(col.getColumnName()); - if (v == null) { - sb.append("null"); - } else { - sb.append(v.toString()); - } - break; - } - i += 1; - } - sb.append("\n"); - } - if (n < rn) { - sb.append("..."); - } - - return sb.toString(); - } - - /** - * Convert to string - tail - * - * @param n Tail row number - * @return The string - */ - public String tail(int n) { - StringBuilder sb = new StringBuilder(); - for (DataColumn col : this.columns) { - if (sb.length() == 0) { - sb.append(col.getColumnName()); - } else { - sb.append("\t"); - sb.append(col.getColumnName()); - } - } - sb.append("\n"); - - DateTimeFormatter format; - int rn = this.getRowCount(); - if (n > rn) { - n = rn; - } - Object v; - for (int r = rn - n; r < rn; r++) { - DataRow row = this.rows.get(r); - int i = 0; - for (DataColumn col : this.columns) { - if (i > 0) { - sb.append("\t"); - } - switch (col.getDataType()) { - case DATE: - format = DateTimeFormatter.ofPattern(col.getFormat()); - sb.append(format.format((LocalDateTime) row.getValue(col.getColumnName()))); - break; - case STRING: - sb.append("'").append(row.getValue(col.getColumnName()).toString()).append("'"); - break; - default: - v = row.getValue(col.getColumnName()); - if (v == null) { - sb.append("null"); - } else { - sb.append(v.toString()); - } - break; - } - i += 1; - } - sb.append("\n"); - } - - return sb.toString(); - } - - /** - * Convert to string - * - * @return The string - */ - @Override - public String toString() { - return head(100); - } - - /** - * Convert to string - * - * @param dateFormat Date format string - * @return The string - */ - public String toString(String dateFormat) { - String str = ""; - for (DataColumn col : this.columns) { - str += "," + col.getColumnName(); - } - str = str.substring(1); - DateTimeFormatter format = DateTimeFormatter.ofPattern(dateFormat); - for (DataRow row : this.rows) { - String line = ""; - for (DataColumn col : this.columns) { - if (col.getDataType() == DataType.DATE) { - line += "," + format.format((LocalDateTime) row.getValue(col.getColumnName())); - } else { - line += "," + row.getValue(col.getColumnName()).toString(); - } - } - line = line.substring(1); - str += System.getProperty("line.separator") + line; - } - - return str; - } - - /** - * Convert to string - * - * @param decimalNum Decimal number - * @return The string - */ - public String toString(int decimalNum) { - return this.toString("yyyyMMddHH", decimalNum); - } - - /** - * Convert to string - * - * @param dateFormat Date format string - * @param decimalNum Decimal number - * @return The string - */ - public String toString(String dateFormat, int decimalNum) { - DateTimeFormatter format = DateTimeFormatter.ofPattern(dateFormat); - String dFormat = "%1$." + String.valueOf(decimalNum) + "f"; - String str = ""; - for (DataColumn col : this.columns) { - str += "," + col.getColumnName(); - } - str = str.substring(1); - String vstr; - for (DataRow row : this.rows) { - String line = ""; - for (DataColumn col : this.columns) { - vstr = row.getValue(col.getColumnName()).toString(); - switch (col.getDataType()) { - case FLOAT: - case DOUBLE: - if (MIMath.isNumeric(vstr)) { - line += "," + String.format(dFormat, Double.parseDouble(vstr)); - } else { - line += ","; - } - break; - case DATE: - line += "," + format.format((LocalDateTime) row.getValue(col.getColumnName())); - break; - default: - line += "," + vstr; - break; - } - } - line = line.substring(1); - str += System.getProperty("line.separator") + line; - } - - return str; - } - - /** - * Save as csv file - * - * @param fileName File name - * @throws java.io.IOException - */ - public void saveAsCSVFile(String fileName) throws IOException { - this.saveAsCSVFile(fileName, null); - } - - /** - * Save as csv file - * - * @param fileName File name - * @param format Format string - * @throws java.io.IOException - */ - public void saveAsCSVFile(String fileName, String format) throws IOException { - List formats = TableUtil.getFormats(format); - int n = this.getColumnCount(); - if (formats != null) { - if (formats.size() < n) { - while (formats.size() < n) { - formats.add(null); - } - } - } - - if (!fileName.endsWith(".csv")) { - fileName = fileName + ".csv"; - } - - BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); - String str = ""; - for (DataColumn col : this.columns) { - str += "," + col.getColumnName(); - } - str = str.substring(1); - sw.write(str); - - String line, vstr; - DataColumn col; - String formatStr; - for (DataRow row : this.rows) { - line = ""; - for (int i = 0; i < n; i++) { - col = this.columns.get(i); - if (formats == null){ - vstr = row.getValueStr(col.getColumnName()); - } else { - formatStr = formats.get(i); - vstr = row.getValueStr(col.getColumnName(), formatStr); - } - if (vstr.equalsIgnoreCase("NaN") || vstr.equalsIgnoreCase("null")){ - vstr = ""; - } - line += "," + vstr; - } - line = line.substring(1); - sw.newLine(); - sw.write(line); - } - sw.flush(); - sw.close(); - } - - /** - * Save as ASCII file - * - * @param fileName File name - * @throws java.io.IOException - */ - public void saveAsASCIIFile(String fileName) throws IOException { - this.saveAsASCIIFile(fileName, ",", null, null); - } - - /** - * Save as ASCII file - * - * @param fileName File name - * @param delimiter Delimiter - * @param dateFormat Date format string - * @param floatFormat Float format string - * @throws java.io.IOException - */ - public void saveAsASCIIFile(String fileName, String delimiter, String dateFormat, String floatFormat) throws IOException { - BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); - int n = this.getColumnCount(); - String str = ""; - for (int i = 0; i < n; i++){ - if (i == 0) - str = this.columns.get(i).getColumnName(); - else - str = str + delimiter + this.columns.get(i).getColumnName(); - }; - sw.write(str); - - String line, vstr; - DataColumn col; - for (DataRow row : this.rows) { - line = ""; - for (int i = 0; i < n; i++) { - col = this.columns.get(i); - switch (col.getDataType()){ - case DATE: - vstr = row.getValueStr(col.getColumnName(), dateFormat); - break; - case FLOAT: - case DOUBLE: - vstr = row.getValueStr(col.getColumnName(), floatFormat); - break; - default: - vstr = row.getValueStr(col.getColumnName()); - break; - } - - line += delimiter + vstr; - } - line = line.substring(1); - sw.newLine(); - sw.write(line); - } - sw.flush(); - sw.close(); - } - - /** - * Save as ASCII file - * - * @param fileName File name - * @param format Format string - * @throws java.io.IOException - */ - public void saveAsASCIIFile_format(String fileName, String format) throws IOException { - List formats = TableUtil.getFormats(format); - int n = this.getColumnCount(); - if (formats != null) { - if (formats.size() < n) { - while (formats.size() < n) { - formats.add(null); - } - } - } - - BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); - String str = ""; - for (DataColumn col : this.columns) { - str += " " + col.getColumnName(); - } - str = str.substring(1); - sw.write(str); - - String line, vstr; - DataColumn col; - String formatStr; - for (DataRow row : this.rows) { - line = ""; - for (int i = 0; i < n; i++) { - col = this.columns.get(i); - if (formats == null) - vstr = row.getValueStr(col.getColumnName()); - else { - formatStr = formats.get(i); - vstr = row.getValueStr(col.getColumnName(), formatStr); - } - line += " " + vstr; - } - line = line.substring(1); - sw.newLine(); - sw.write(line); - } - sw.flush(); - sw.close(); - } - - /** - * Join data table - * - * @param dataTable The input data table - * @param colName The column name for join - */ - public void join(DataTable dataTable, String colName) { - this.join(dataTable, colName, colName, false); - } - - /** - * Join data table - * - * @param dataTable The input data table - * @param colName The column name for join - * @param isUpdate If update the existing values with same column name - */ - public void join(DataTable dataTable, String colName, boolean isUpdate) { - this.join(dataTable, colName, colName, isUpdate); - } - - /** - * Join data table - * - * @param dataTable The input data table - * @param colName_this The column name of this data table for join - * @param colName_in The column name of the input data table for join - * @param isUpdate If update the existing values with same column name - */ - public void join(DataTable dataTable, String colName_this, String colName_in, boolean isUpdate) { - DataColumn col_this = this.findColumn(colName_this); - if (col_this == null) { - System.out.println("There is no column of " + colName_this + " in this table"); - return; - } - DataColumn col_in = dataTable.findColumn(colName_in); - if (col_in == null) { - System.out.println("There is no column of " + colName_in + " in this table"); - return; - } - - List values_this = this.getColumnData(colName_this).getDataStrings(); - List values_in = dataTable.getColumnData(colName_in).getDataStrings(); - - List colNames = this.getColumnNames(); - List newColNames = new ArrayList<>(); - for (DataColumn col : dataTable.columns) { - if (col.getColumnName().equals(colName_in)) { - continue; - } - if (!colNames.contains(col.getColumnName())) { - Field newCol = new Field(col.getColumnName(), col.getDataType()); - newCol.setJoined(true); - this.addColumn(newCol); - newColNames.add(col.getColumnName()); - } - } - String value; - int idx; - for (int i = 0; i < this.getRowCount(); i++) { - value = values_this.get(i); - idx = values_in.indexOf(value); - if (idx >= 0) { - if (isUpdate) { - for (String cn : dataTable.getColumnNames()) { - if (cn.equals(colName_in)) { - continue; - } - this.setValue(i, cn, dataTable.getValue(idx, cn)); - } - } else { - for (String cn : newColNames) { - this.setValue(i, cn, dataTable.getValue(idx, cn)); - } - } - } - } - } - - /** - * Remove joined data columns - */ - public void removeJoin() { - for (DataColumn col : this.columns) { - if (col.isJoined()) { - this.removeColumn(col); - } - } - } -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.table; + +import org.meteoinfo.common.MIMath; +import org.meteoinfo.ndarray.DataType; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.meteoinfo.data.TableUtil; +import org.meteoinfo.data.mapdata.Field; +import ucar.ma2.Range; + +/** + * + * @author Yaqiang Wang + */ +public class DataTable { + + protected DataRowCollection rows; + protected DataColumnCollection columns; + protected String tableName; + protected boolean readOnly = false; + protected int nextRowIndex = 0; +//private DataExpression dataExpression; + protected Object tag; + + /** + * Constructor + */ + public DataTable() { + this.columns = new DataColumnCollection(); + this.rows = new DataRowCollection(); + this.rows.setColumns(columns); + //dataExpression = new DataExpression(this); + } + + /** + * Constructor + * + * @param dataTableName The data table name + */ + public DataTable(String dataTableName) { + this(); + this.tableName = dataTableName; + } + + /** + * Get total row count + * + * @return Row number + */ + public int getTotalCount() { + return rows.size(); + } + + /** + * Get row count + * + * @return Row count + */ + public int getRowCount() { + return rows.size(); + } + + /** + * Get column count + * + * @return Column count + */ + public int getColumnCount() { + return columns.size(); + } + + /** + * Get if is read only + * + * @return Boolean + */ + public boolean isReadOnly() { + return this.readOnly; + } + + /** + * Set if is read only + * + * @param readOnly Read only + */ + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + /** + * Get table name + * + * @return Table name + */ + public String getTableName() { + return this.tableName; + } + + /** + * Set tabel name + * + * @param tableName Table name + */ + public void setTableName(String tableName) { + this.tableName = tableName; + } + + /** + * Get data rows + * + * @return DataRowCollection The data rows + */ + public DataRowCollection getRows() { + return this.rows; + } + + /** + * Get data rows + * + * @param idx Index + * @return DataRowCollection The data rows + */ + public DataRowCollection getRows(List idx) { + DataRowCollection r = new DataRowCollection(); + for (int i : idx){ + r.add(this.rows.get(i)); + } + return r; + } + + /** + * Get data rows + * + * @param range Range + * @return DataRowCollection The data rows + */ + public DataRowCollection getRows(Range range) { + DataRowCollection r = new DataRowCollection(); + for (int i = range.first(); i < range.last(); i++){ + r.add(this.rows.get(i)); + } + return r; + } + + /** + * Get data columns + * + * @return The data columns + */ + public DataColumnCollection getColumns() { + return this.columns; + } + + /** + * Get column names + * + * @return Column names + */ + public List getColumnNames() { + return this.columns.getColumnNames(); + } + + /** + * Get the value by row index and column name + * + * @param row Row index + * @param colName Column name + * @return Object The value + */ + public Object getValue(int row, String colName) { + return this.rows.get(row).getValue(colName); + } + + /** + * Get the value by row and column index + * + * @param row Row index + * @param col Column index + * @return Object The value + */ + public Object getValue(int row, int col) { + return this.rows.get(row).getValue(col); + } + + /** + * Create a new data row + * + * @return DataRow The new data row + * @throws java.lang.Exception + */ + public DataRow newRow() throws Exception { + DataRow tempRow = new DataRow(this); + nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() + : nextRowIndex; + tempRow.setColumns(this.columns); + tempRow.setRowIndex(nextRowIndex++); + for (DataColumn col : columns) { + switch (col.getDataType()) { + case STRING: + tempRow.setValue(col.getColumnName(), ""); + break; + case DATE: + tempRow.setValue(col.getColumnName(), LocalDateTime.now()); + break; + case BOOLEAN: + tempRow.setValue(col.getColumnName(), Boolean.TRUE); + break; + default: + tempRow.setValue(col.getColumnName(), 0); + break; + } + } + return tempRow; + } + + /** + * Set a vlaue by row and column index + * + * @param row Row index + * @param col Column index + * @param value The value + */ + public void setValue(int row, int col, Object value) { + this.rows.get(row).setValue(col, value); + } + + /** + * Set a value + * + * @param row Row index + * @param colName Column name + * @param value The value + */ + public void setValue(int row, String colName, Object value) { + this.rows.get(row).setValue(colName, value); + } + + /** + * Set values + * + * @param colName Column name + * @param values Values + */ + public void setValues(String colName, List values) { + for (int i = 0; i < values.size(); i++) { + this.rows.get(i).setValue(colName, values.get(i)); + } + } + + /** + * Set tag + * + * @param tag The tag + */ + public void setTag(Object tag) { + this.tag = tag; + } + + /** + * Get tag + * + * @return the tag + */ + public Object getTag() { + return tag; + } + + /** + * Find column by name + * + * @param colName The column name + * @return The data column + */ + public DataColumn findColumn(String colName) { + if (colName == null) + return null; + + for (DataColumn col : this.columns) { + if (col.getColumnName().equals(colName)) { + return col; + } + } + + return null; + } + + /** + * Get data columns by names + * + * @param colNames Data column names + * @return Data columns + */ + public List findColumns(List colNames) { + List cols = new ArrayList<>(); + for (DataColumn col : this.getColumns()) { + for (String colName : colNames) { + if (col.getColumnName().equals(colName)) { + cols.add(col); + break; + } + } + } + + return cols; + } + + /** + * Get data columns by index + * + * @param colIndex Data column index + * @return Data columns + */ + public List findColumns_Index(List colIndex) { + List cols = new ArrayList<>(); + int n = this.getColumnCount(); + for (int i : colIndex) { + if (i < 0) + i = n + i; + if (i < n) + cols.add(this.columns.get(i)); + } + + return cols; + } + + /** + * Check if the table has time column + * @return Boolean + */ + public boolean hasTimeColumn(){ + for (DataColumn col : this.columns){ + if (col.getDataType() == DataType.DATE){ + return true; + } + } + return false; + } + + /** + * Add a data column + * + * @param columnName Data column name + * @param dataType Data type + * @return The data column + * @throws Exception + */ + public DataColumn addColumn(String columnName, DataType dataType) throws Exception { + DataColumn col = new DataColumn(columnName, dataType); + addColumn(col); + return col; + } + + /** + * Add a data column + * + * @param index The index + * @param columnName Data column name + * @param dataType Data type + * @return The data column + * @throws Exception + */ + public DataColumn addColumn(int index, String columnName, DataType dataType) throws Exception { + DataColumn col = new DataColumn(columnName, dataType); + addColumn(index, col); + return col; + } + + /** + * Add a data column by index + * + * @param index The index + * @param column Data column + */ + public void addColumn(int index, DataColumn column) { + this.columns.add(index, column); + for (DataRow row : this.rows) { + row.setColumns(columns); + row.addColumn(column); + } + } + + /** + * Add a data column + * + * @param column Data column + */ + public void addColumn(DataColumn column) { + this.columns.add(column); + for (DataRow row : this.rows) { + row.setColumns(columns); + row.addColumn(column); + } + } + + /** + * Remove a data column + * + * @param column The data column + */ + public void removeColumn(DataColumn column) { + this.columns.remove(column); + for (DataRow row : this.rows) { + row.setColumns(columns); + row.removeColumn(column); + } + } + + /** + * Rename column + * + * @param column The column + * @param fieldName The new column name + */ + public void renameColumn(DataColumn column, String fieldName) { + String oldName = column.getColumnName(); + this.columns.renameColumn(column, fieldName); + for (DataRow row : this.rows) { + row.setColumns(columns); + row.renameColumn(oldName, fieldName); + } + } + + /** + * Rename column + * + * @param oldName The old column name + * @param newName The new column name + */ + public void renameColumn(String oldName, String newName) { + DataColumn column = findColumn(oldName); + this.columns.renameColumn(column, newName); + for (DataRow row : this.rows) { + row.setColumns(columns); + row.renameColumn(oldName, newName); + } + } + + /** + * Rename column + * + * @param colIdx The column index + * @param fieldName The new column name + */ + public void renameColumn(int colIdx, String fieldName) { + DataColumn column = this.columns.get(colIdx); + this.renameColumn(column, fieldName); + } + + /** + * Add a data row + * + * @param row The data row + * @return Boolean + * @throws Exception + */ + public boolean addRow(DataRow row) throws Exception { + nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() + : nextRowIndex; + row.setColumns(this.columns); + row.setRowIndex(nextRowIndex++); + row.setTable(this); + return this.rows.add(row); + } + + /** + * Add data row + * + * @return Data row + * @throws Exception + */ + public DataRow addRow() throws Exception { + DataRow row = new DataRow(); + this.addRow(row); + return row; + } + + /** + * Add data rows + * + * @param rows Data rows + * @throws Exception + */ + public void addRows(List rows) throws Exception { + for (DataRow row : rows) { + addRow(row); + } + } + + /** + * Append a data row + * + * @param row Data row + * @return Boolean + */ + public boolean appendRow(DataRow row) { + List colNames = row.getColumns().getColumnNames(); + nextRowIndex = nextRowIndex < this.rows.size() ? this.rows.size() + : nextRowIndex; + row.setColumns(this.columns); + row.setRowIndex(nextRowIndex++); + row.setTable(this); + for (DataColumn col : this.columns) { + if (!colNames.contains(col.getColumnName())) { + row.setValue(col, null); + } + } + return this.rows.add(row); + } + + /** + * Remove a row + * + * @param rowIdx Row index + */ + public void removeRow(int rowIdx) { + this.rows.remove(rowIdx); + } + + /** + * Remove a row + * + * @param row The row will be removed + */ + public void removeRow(DataRow row) { + this.rows.remove(row); + } + + /** + * Remove rows + * + * @param rows The rows will be removed + */ + public void removeRows(List rows) { + this.rows.removeAll(rows); + } + + /** + * Set data rows + * + * @param rows The data rows + */ + public void setRows(List rows) { + this.rows.clear(); + for (DataRow row : rows) { + this.rows.add(row); + } + } + + /** + * Add column data + * + * @param col The column + * @param colData The column data + * @throws Exception + */ + public void setColumnData(DataColumn col, List colData) throws Exception { + if (this.getRowCount() == 0) { + for (int i = 0; i < colData.size(); i++){ + DataRow row = this.addRow(); + row.setValue(col, colData.get(i)); + } + } else { + int i = 0; + for (DataRow row : this.rows) { + if (i < colData.size()) { + row.setValue(col, colData.get(i)); + } + i++; + } + } + } + + /** + * Add column data + * + * @param colName Column name + * @param colData The column data + * @throws Exception + */ + public void setColumnData(String colName, List colData) throws Exception { + DataColumn col = this.findColumn(colName); + if (col == null){ + System.out.println("The column not exists: " + colName + "!"); + return; + } + + setColumnData(col, colData); + } + + /** + * Add column data + * + * @param colData The column data + * @throws Exception + */ + public void addColumnData(ColumnData colData) throws Exception { + DataColumn col = this.addColumn(colData.getDataColumn().getColumnName(), colData.getDataType()); + int i = 0; + for (DataRow row : this.rows) { + if (i < colData.size()) { + row.setValue(col, colData.getValue(i)); + } + i++; + } + } + + /** + * Add column data + * + * @param colName Column name + * @param dataType Data type + * @param colData The column data + * @throws Exception + */ + public void addColumnData(String colName, DataType dataType, List colData) throws Exception { + DataColumn col = this.addColumn(colName, dataType); + setColumnData(col, colData); + } + + /** + * Add column data + * + * @param index Column index + * @param colName Column name + * @param dataType Data type + * @param colData The column data + * @throws Exception + */ + public void addColumnData(int index, String colName, DataType dataType, List colData) throws Exception { + DataColumn col = this.addColumn(index, colName, dataType); + setColumnData(col, colData); + } + + /** + * Add column data + * + * @param colName Column name + * @param dt Data type string + * @param colData The column data + * @throws Exception + */ + public void addColumnData(String colName, String dt, List colData) throws Exception { + DataType dataType = TableUtil.toDataTypes(dt); + this.addColumnData(colName, dataType, colData); + } + + /** + * Get column data + * + * @param colName The column name + * @return Column data + */ + public ColumnData getColumnData(String colName) { + return this.getColumnData(this.getRows(), colName); + } + + /** + * Get column data + * + * @param col The data column + * @return Column data + */ + public ColumnData getColumnData(DataColumn col) { + return this.getColumnData(col.getColumnName()); + } + + /** + * Get column data + * + * @param rows The data row list + * @param colName The data column name + * @return Column values + */ + public ColumnData getColumnData(List rows, String colName) { + ColumnData colData = new ColumnData(this.findColumn(colName)); + for (DataRow row : rows) { + colData.addData(row.getValue(colName)); + } + + return colData; + } + + /** + * Select data rows + * + * @param expression SQL expression + * @return Selected data rows + */ + public List select(String expression) { + SQLExpression e = new SQLExpression(expression); + List dataRows = new ArrayList<>(); + for (int i = 0; i < this.rows.size(); i++) { + DataRow row = this.rows.get(i); + row.setRowIndex(i); + if (e.eval(row.getItemMap())) { + dataRows.add(row); + } + } + + return dataRows; + } + + /** + * Select and form a new data table + * + * @param expression SQL expression + * @param dataColumns Data columns + * @return Selected data table + */ + public DataTable select(String expression, DataColumn[] dataColumns) { + DataTable result = new DataTable(); + List dataRows = this.select(expression); + for (DataColumn dc : dataColumns) { + DataColumn newDc = (DataColumn)dc.clone(); + result.columns.add(newDc); + } + + for (DataRow r : dataRows) { + try { + DataRow newRow = result.newRow(); + newRow.copyFrom(r); + result.addRow(newRow); + } catch (Exception ex) { + Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + return result; + } + + /** + * Get a new table by row range + * @param rowRange Row range + * @return + * @throws Exception + */ + public DataTable select(Range rowRange) throws Exception{ + return select(rowRange.first(), rowRange.last(), rowRange.stride()); + } + + /** + * Get a new table by select rows + * @param r_start row start + * @param r_stop row stop + * @param r_step row step + * @return Result table + * @throws Exception + */ + public DataTable select(int r_start, int r_stop, int r_step) throws Exception { + DataTable r = new DataTable(); + for (DataColumn dc : this.columns) { + DataColumn newDc = (DataColumn)dc.clone(); + r.columns.add(newDc); + } + + for (int i = r_start; i < r_stop; i+=r_step) { + if (i >= this.getRowCount()) + break; + DataRow newRow = r.newRow(); + newRow.copyFrom(this.rows.get(i)); + r.addRow(newRow); + } + + return r; + } + + /** + * Get a new table by row index + * @param rowIndex Row index + * @return Result table + * @throws Exception + */ + public DataTable select(List rowIndex) throws Exception { + DataTable r = new DataTable(); + for (DataColumn dc : this.columns) { + DataColumn newDc = (DataColumn)dc.clone(); + r.columns.add(newDc); + } + + for (int i : rowIndex) { + if (i >= this.getRowCount()) + break; + DataRow newRow = r.newRow(); + newRow.copyFrom(this.rows.get(i)); + r.addRow(newRow); + } + + return r; + } + + /** + * Get a new table by row range and column range + * @param rowRange Row range + * @param colRange Column range + * @return Result table + * @throws Exception + */ + public DataTable select(Range rowRange, Range colRange) throws Exception { + return select(rowRange.first(), rowRange.last(), rowRange.stride(), colRange.first(), colRange.last(), colRange.stride()); + } + + /** + * Get a new table by select rows + * @param r_start Row start + * @param r_stop Row stop + * @param r_step Row step + * @param c_start Column start + * @param c_stop Column stop + * @param c_step Column step + * @return Result table + * @throws Exception + */ + public DataTable select(int r_start, int r_stop, int r_step, int c_start, int c_stop, int c_step) throws Exception { + List cols = new ArrayList<>(); + for (int i = c_start; i < c_stop; i+= c_step){ + if (i >= this.getColumnCount()) + break; + cols.add(this.columns.get(i)); + } + + return this.select(r_start, r_stop, r_step, cols); + } + + /** + * Get a new table by row index and column range + * @param rowIndex Row index + * @param colRange Column range + * @return Result table + * @throws Exception + */ + public DataTable select(List rowIndex, Range colRange) throws Exception { + return select(rowIndex, colRange.first(), colRange.last(), colRange.stride()); + } + + /** + * Get a new table by row index and column slice + * @param rowIndex Row index + * @param c_start Column start + * @param c_stop Column stop + * @param c_step Column step + * @return Result table + * @throws Exception + */ + public DataTable select(List rowIndex, int c_start, int c_stop, int c_step) throws Exception { + List cols = new ArrayList<>(); + for (int i = c_start; i < c_stop; i+= c_step){ + if (i >= this.getColumnCount()) + break; + cols.add(this.columns.get(i)); + } + + return this.select(rowIndex, cols); + } + + /** + * Get a new table by row range and columns + * @param rowRange Row range + * @param cols Columns + * @return Result table + * @throws Exception + */ + public DataTable select(Range rowRange, List cols) throws Exception { + return select(rowRange.first(), rowRange.last(), rowRange.stride(), cols); + } + + /** + * Get a new table by select rows + * @param r_start Row start + * @param r_stop Row stop + * @param r_step Row step + * @param cols Columns + * @return Result table + * @throws Exception + */ + public DataTable select(int r_start, int r_stop, int r_step, List cols) throws Exception { + DataTable r = new DataTable(); + for (DataColumn dc : cols) { + DataColumn newDc = (DataColumn)dc.clone(); + r.columns.add(newDc); + } + + DataColumnCollection dcc = new DataColumnCollection(cols); + for (int i = r_start; i < r_stop; i+=r_step) { + if (i >= this.getRowCount()) + break; + DataRow newRow = this.rows.get(i).colSelect(dcc); + r.addRow(newRow); + } + + return r; + } + + /** + * Get a new table by row index and columns + * @param rowIndex Row index + * @param cols Columns + * @return Result table + * @throws Exception + */ + public DataTable select(List rowIndex, List cols) throws Exception { + DataTable r = new DataTable(); + for (DataColumn dc : cols) { + DataColumn newDc = (DataColumn)dc.clone(); + r.columns.add(newDc); + } + + DataColumnCollection dcc = new DataColumnCollection(cols); + for (int i : rowIndex) { + if (i >= this.getRowCount()) + break; + DataRow newRow = this.rows.get(i).colSelect(dcc); + r.addRow(newRow); + } + + return r; + } + + /** + * Create a new data table using selected columns + * @param cols The columns + * @return Selected data table + * @throws java.lang.Exception + */ + public DataTable colSelect(List cols) throws Exception { + DataTable r = new DataTable(); + for (DataColumn dc : cols) { + DataColumn newDc = (DataColumn)dc.clone(); + r.columns.add(dc); + } + + DataColumnCollection dcc = new DataColumnCollection(cols); + for (DataRow dr : this.rows) { + DataRow ndr = dr.colSelect(dcc); + r.addRow(ndr); + } + + return r; + } + + /** + * Select and form a new data table + * + * @param expression SQL expression + * @return Selected data table + */ + public DataTable sqlSelect(String expression) { + DataTable result = new DataTable(); + List dataRows = this.select(expression); + for (DataColumn dc : this.columns) { + DataColumn newDc = (DataColumn)dc.clone(); + result.columns.add(newDc); + } + + for (DataRow r : dataRows) { + try { + DataRow newRow = result.newRow(); + newRow.copyFrom(r); + result.addRow(newRow); + } catch (Exception ex) { + Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + return result; + } + +// //以下为数据表扩展方法实现集合 +// /** +// * 功能描述: 返回符合过滤条件的数据行集合,并返回 +// * @param +// * @return: DataTable +// */ +// public List select(String filterString) { +// List rows = new ArrayList(); +// if (StringUtil.isNotEmpty(filterString)) { +// for (Object row : this.rows) { +// DataRow currentRow = (DataRow) row; +// if ((Boolean) dataExpression.compute(filterString, +// currentRow.getItemMap())) { +// rows.add(currentRow); +// } +// } +// return rows; +// } else { +// return this.rows; +// } +// } +// /** +// * 功能描述: 对当前表进行查询 过滤,并返回指定列集合拼装的DataTable对象 +// * @param +// * @return: DataTable +// */ +// public DataTable select(String filterString, +// String[] columns, +// boolean distinct) throws Exception { +// DataTable result = new DataTable(); +// List rows = select(filterString); +// //构造表结构 +// for (String c : columns) { +// DataColumn dc = this.columns.get(c); +// DataColumn newDc = new DataColumn(dc.getColumnName(), +// dc.getDataType()); +// newDc.setCaptionName(dc.getCaptionName()); +// result.columns.add(newDc); +// } +// //填充数据 +// for (DataRow r : rows) { +// DataRow newRow = result.newRow(); +// newRow.copyFrom(r); +// result.addRow(newRow); +// } +// return result; +// } +// /** +// * 功能描述: 根据指定表达式对符合过滤条件的数据进行计算 +// * @param +// * @return: Object +// * @author: James Cheung +// * @version: 2.0 +// */ +// public Object compute(String expression, +// String filter) { +// return dataExpression.compute(expression, select(filter)); +// } + public Object max(String columns, + String filter) { + return null; + } + + public Object min(String columns, + String filter) { + return null; + } + + public Object avg(String columns, + String filter) { + return null; + } + + public Object max(String columns, + String filter, + String groupBy) { + return null; + } + + public Object min(String columns, + String filter, + String groupBy) { + return null; + } + + public Object avg(String columns, + String filter, + String groupBy) { + return null; + } + + /** + * Clone + * + * @return Cloned DataTable object + */ + @Override + public Object clone() { + DataTable table = new DataTable(); + table.tableName = this.tableName; + table.tag = this.tag; + table.readOnly = this.readOnly; + for (DataColumn col : this.columns) { + DataColumn newcol = (DataColumn) col.clone(); + //newcol.setTable(table); + table.addColumn(new Field(newcol)); + } + + for (DataRow row : this.rows) { + try { + DataRow newrow = this.newRow(); + newrow.copyFrom(row); + table.addRow(newrow); + } catch (Exception ex) { + Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + return table; + } + + /** + * Clone table - Vectorlayer with fields + * + * @return DataTable + */ + public DataTable cloneTable_Field() { + DataTable table = new DataTable(); + table.tableName = this.tableName; + table.tag = this.tag; + table.readOnly = this.readOnly; + for (DataColumn col : this.columns) { + Field newcol = new Field(col.getColumnName(), col.getDataType()); + newcol.setCaptionName(col.getCaptionName()); + newcol.setColumnIndex(col.getColumnIndex()); + newcol.setReadOnly(col.isReadOnly()); + //newcol.setTable(table); + table.addColumn(newcol); + } + + for (DataRow row : this.rows) { + try { + DataRow newrow = this.newRow(); + newrow.copyFrom(row); + table.addRow(newrow); + } catch (Exception ex) { + Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex); + } + } + + return table; + } + + /** + * Convert to string - head + * + * @param n Head row number + * @return The string + */ + public String head(int n) { + StringBuilder sb = new StringBuilder(); + for (DataColumn col : this.columns) { + if (sb.length() == 0) { + sb.append(col.getColumnName()); + } else { + sb.append("\t"); + sb.append(col.getColumnName()); + } + } + sb.append("\n"); + + DateTimeFormatter format; + int rn = this.getRowCount(); + if (n > rn) { + n = rn; + } + Object v; + for (int r = 0; r < n; r++) { + DataRow row = this.rows.get(r); + int i = 0; + for (DataColumn col : this.columns) { + if (i > 0) { + sb.append("\t"); + } + switch (col.getDataType()) { + case DATE: + format = DateTimeFormatter.ofPattern(col.getFormat()); + sb.append(format.format((LocalDateTime) row.getValue(col.getColumnName()))); + break; + case STRING: + sb.append("'").append(row.getValue(col.getColumnName()).toString()).append("'"); + break; + default: + v = row.getValue(col.getColumnName()); + if (v == null) { + sb.append("null"); + } else { + sb.append(v.toString()); + } + break; + } + i += 1; + } + sb.append("\n"); + } + if (n < rn) { + sb.append("..."); + } + + return sb.toString(); + } + + /** + * Convert to string - tail + * + * @param n Tail row number + * @return The string + */ + public String tail(int n) { + StringBuilder sb = new StringBuilder(); + for (DataColumn col : this.columns) { + if (sb.length() == 0) { + sb.append(col.getColumnName()); + } else { + sb.append("\t"); + sb.append(col.getColumnName()); + } + } + sb.append("\n"); + + DateTimeFormatter format; + int rn = this.getRowCount(); + if (n > rn) { + n = rn; + } + Object v; + for (int r = rn - n; r < rn; r++) { + DataRow row = this.rows.get(r); + int i = 0; + for (DataColumn col : this.columns) { + if (i > 0) { + sb.append("\t"); + } + switch (col.getDataType()) { + case DATE: + format = DateTimeFormatter.ofPattern(col.getFormat()); + sb.append(format.format((LocalDateTime) row.getValue(col.getColumnName()))); + break; + case STRING: + sb.append("'").append(row.getValue(col.getColumnName()).toString()).append("'"); + break; + default: + v = row.getValue(col.getColumnName()); + if (v == null) { + sb.append("null"); + } else { + sb.append(v.toString()); + } + break; + } + i += 1; + } + sb.append("\n"); + } + + return sb.toString(); + } + + /** + * Convert to string + * + * @return The string + */ + @Override + public String toString() { + return head(100); + } + + /** + * Convert to string + * + * @param dateFormat Date format string + * @return The string + */ + public String toString(String dateFormat) { + String str = ""; + for (DataColumn col : this.columns) { + str += "," + col.getColumnName(); + } + str = str.substring(1); + DateTimeFormatter format = DateTimeFormatter.ofPattern(dateFormat); + for (DataRow row : this.rows) { + String line = ""; + for (DataColumn col : this.columns) { + if (col.getDataType() == DataType.DATE) { + line += "," + format.format((LocalDateTime) row.getValue(col.getColumnName())); + } else { + line += "," + row.getValue(col.getColumnName()).toString(); + } + } + line = line.substring(1); + str += System.getProperty("line.separator") + line; + } + + return str; + } + + /** + * Convert to string + * + * @param decimalNum Decimal number + * @return The string + */ + public String toString(int decimalNum) { + return this.toString("yyyyMMddHH", decimalNum); + } + + /** + * Convert to string + * + * @param dateFormat Date format string + * @param decimalNum Decimal number + * @return The string + */ + public String toString(String dateFormat, int decimalNum) { + DateTimeFormatter format = DateTimeFormatter.ofPattern(dateFormat); + String dFormat = "%1$." + String.valueOf(decimalNum) + "f"; + String str = ""; + for (DataColumn col : this.columns) { + str += "," + col.getColumnName(); + } + str = str.substring(1); + String vstr; + for (DataRow row : this.rows) { + String line = ""; + for (DataColumn col : this.columns) { + vstr = row.getValue(col.getColumnName()).toString(); + switch (col.getDataType()) { + case FLOAT: + case DOUBLE: + if (MIMath.isNumeric(vstr)) { + line += "," + String.format(dFormat, Double.parseDouble(vstr)); + } else { + line += ","; + } + break; + case DATE: + line += "," + format.format((LocalDateTime) row.getValue(col.getColumnName())); + break; + default: + line += "," + vstr; + break; + } + } + line = line.substring(1); + str += System.getProperty("line.separator") + line; + } + + return str; + } + + /** + * Save as csv file + * + * @param fileName File name + * @throws java.io.IOException + */ + public void saveAsCSVFile(String fileName) throws IOException { + this.saveAsCSVFile(fileName, null); + } + + /** + * Save as csv file + * + * @param fileName File name + * @param format Format string + * @throws java.io.IOException + */ + public void saveAsCSVFile(String fileName, String format) throws IOException { + List formats = TableUtil.getFormats(format); + int n = this.getColumnCount(); + if (formats != null) { + if (formats.size() < n) { + while (formats.size() < n) { + formats.add(null); + } + } + } + + if (!fileName.endsWith(".csv")) { + fileName = fileName + ".csv"; + } + + BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); + String str = ""; + for (DataColumn col : this.columns) { + str += "," + col.getColumnName(); + } + str = str.substring(1); + sw.write(str); + + String line, vstr; + DataColumn col; + String formatStr; + for (DataRow row : this.rows) { + line = ""; + for (int i = 0; i < n; i++) { + col = this.columns.get(i); + if (formats == null){ + vstr = row.getValueStr(col.getColumnName()); + } else { + formatStr = formats.get(i); + vstr = row.getValueStr(col.getColumnName(), formatStr); + } + if (vstr.equalsIgnoreCase("NaN") || vstr.equalsIgnoreCase("null")){ + vstr = ""; + } + line += "," + vstr; + } + line = line.substring(1); + sw.newLine(); + sw.write(line); + } + sw.flush(); + sw.close(); + } + + /** + * Save as ASCII file + * + * @param fileName File name + * @throws java.io.IOException + */ + public void saveAsASCIIFile(String fileName) throws IOException { + this.saveAsASCIIFile(fileName, ",", null, null); + } + + /** + * Save as ASCII file + * + * @param fileName File name + * @param delimiter Delimiter + * @param dateFormat Date format string + * @param floatFormat Float format string + * @throws java.io.IOException + */ + public void saveAsASCIIFile(String fileName, String delimiter, String dateFormat, String floatFormat) throws IOException { + BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); + int n = this.getColumnCount(); + String str = ""; + for (int i = 0; i < n; i++){ + if (i == 0) + str = this.columns.get(i).getColumnName(); + else + str = str + delimiter + this.columns.get(i).getColumnName(); + }; + sw.write(str); + + String line, vstr; + DataColumn col; + for (DataRow row : this.rows) { + line = ""; + for (int i = 0; i < n; i++) { + col = this.columns.get(i); + switch (col.getDataType()){ + case DATE: + vstr = row.getValueStr(col.getColumnName(), dateFormat); + break; + case FLOAT: + case DOUBLE: + vstr = row.getValueStr(col.getColumnName(), floatFormat); + break; + default: + vstr = row.getValueStr(col.getColumnName()); + break; + } + + line += delimiter + vstr; + } + line = line.substring(1); + sw.newLine(); + sw.write(line); + } + sw.flush(); + sw.close(); + } + + /** + * Save as ASCII file + * + * @param fileName File name + * @param format Format string + * @throws java.io.IOException + */ + public void saveAsASCIIFile_format(String fileName, String format) throws IOException { + List formats = TableUtil.getFormats(format); + int n = this.getColumnCount(); + if (formats != null) { + if (formats.size() < n) { + while (formats.size() < n) { + formats.add(null); + } + } + } + + BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fileName))); + String str = ""; + for (DataColumn col : this.columns) { + str += " " + col.getColumnName(); + } + str = str.substring(1); + sw.write(str); + + String line, vstr; + DataColumn col; + String formatStr; + for (DataRow row : this.rows) { + line = ""; + for (int i = 0; i < n; i++) { + col = this.columns.get(i); + if (formats == null) + vstr = row.getValueStr(col.getColumnName()); + else { + formatStr = formats.get(i); + vstr = row.getValueStr(col.getColumnName(), formatStr); + } + line += " " + vstr; + } + line = line.substring(1); + sw.newLine(); + sw.write(line); + } + sw.flush(); + sw.close(); + } + + /** + * Join data table + * + * @param dataTable The input data table + * @param colName The column name for join + */ + public void join(DataTable dataTable, String colName) { + this.join(dataTable, colName, colName, false); + } + + /** + * Join data table + * + * @param dataTable The input data table + * @param colName The column name for join + * @param isUpdate If update the existing values with same column name + */ + public void join(DataTable dataTable, String colName, boolean isUpdate) { + this.join(dataTable, colName, colName, isUpdate); + } + + /** + * Join data table + * + * @param dataTable The input data table + * @param colName_this The column name of this data table for join + * @param colName_in The column name of the input data table for join + * @param isUpdate If update the existing values with same column name + */ + public void join(DataTable dataTable, String colName_this, String colName_in, boolean isUpdate) { + DataColumn col_this = this.findColumn(colName_this); + if (col_this == null) { + System.out.println("There is no column of " + colName_this + " in this table"); + return; + } + DataColumn col_in = dataTable.findColumn(colName_in); + if (col_in == null) { + System.out.println("There is no column of " + colName_in + " in this table"); + return; + } + + List values_this = this.getColumnData(colName_this).getDataStrings(); + List values_in = dataTable.getColumnData(colName_in).getDataStrings(); + + List colNames = this.getColumnNames(); + List newColNames = new ArrayList<>(); + for (DataColumn col : dataTable.columns) { + if (col.getColumnName().equals(colName_in)) { + continue; + } + if (!colNames.contains(col.getColumnName())) { + Field newCol = new Field(col.getColumnName(), col.getDataType()); + newCol.setJoined(true); + this.addColumn(newCol); + newColNames.add(col.getColumnName()); + } + } + String value; + int idx; + for (int i = 0; i < this.getRowCount(); i++) { + value = values_this.get(i); + idx = values_in.indexOf(value); + if (idx >= 0) { + if (isUpdate) { + for (String cn : dataTable.getColumnNames()) { + if (cn.equals(colName_in)) { + continue; + } + this.setValue(i, cn, dataTable.getValue(idx, cn)); + } + } else { + for (String cn : newColNames) { + this.setValue(i, cn, dataTable.getValue(idx, cn)); + } + } + } + } + } + + /** + * Remove joined data columns + */ + public void removeJoin() { + for (DataColumn col : this.columns) { + if (col.isJoined()) { + this.removeColumn(col); + } + } + } +} diff --git a/MeteoInfoLib/src/test/java/map/frmMap.java b/MeteoInfoLib/src/test/java/map/frmMap.java index af160057..7ea8471f 100644 --- a/MeteoInfoLib/src/test/java/map/frmMap.java +++ b/MeteoInfoLib/src/test/java/map/frmMap.java @@ -1,23 +1,14 @@ package map; +import org.meteoinfo.common.GenericFileFilter; import org.meteoinfo.data.mapdata.MapDataManage; -import org.meteoinfo.data.mapdata.ShapeFileManage; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.event.*; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; -import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.layout.MapLayout; import org.meteoinfo.legend.LayersLegend; -import org.meteoinfo.map.FeatureUndoableEdit; import org.meteoinfo.map.MapView; -import org.meteoinfo.map.MapViewUndoRedo; import org.meteoinfo.map.MouseTools; -import org.meteoinfo.projection.info.ProjectionInfo; import javax.swing.*; -import javax.swing.undo.UndoableEdit; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/MeteoInfoMap/MeteoInfoMap.iml b/MeteoInfoMap/MeteoInfoMap.iml index 90c2e067..89551a44 100644 --- a/MeteoInfoMap/MeteoInfoMap.iml +++ b/MeteoInfoMap/MeteoInfoMap.iml @@ -12,6 +12,15 @@ + + + + + + + + + diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/MeteoInfoMap.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/MeteoInfoMap.java index 4fe5871d..2c1e624f 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/MeteoInfoMap.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/MeteoInfoMap.java @@ -19,12 +19,13 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.*; import javax.xml.parsers.ParserConfigurationException; + +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.desktop.config.Options; import org.meteoinfo.desktop.forms.FrmMain; import org.meteoinfo.desktop.forms.FrmTextEditor; import org.meteoinfo.global.DataConvert; import org.meteoinfo.global.util.FontUtil; -import org.meteoinfo.global.util.GlobalUtil; import org.python.core.PyString; import org.python.core.PySystemState; import org.python.util.InteractiveConsole; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAbout.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAbout.java index 32cea2fe..01cdfbc1 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAbout.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAbout.java @@ -4,6 +4,8 @@ */ package org.meteoinfo.desktop.forms; +import org.meteoinfo.common.util.GlobalUtil; + import java.awt.Cursor; import java.awt.Desktop; import java.io.IOException; @@ -11,7 +13,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; -import org.meteoinfo.global.util.GlobalUtil; /** * diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAddXYData.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAddXYData.java index 074c4e0a..e4679cc8 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAddXYData.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmAddXYData.java @@ -17,12 +17,13 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFileChooser; import javax.swing.JOptionPane; + +import org.meteoinfo.common.GenericFileFilter; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.mapdata.Field; -import org.meteoinfo.global.GenericFileFilter; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.layer.LayerDrawType; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.legend.LegendManage; @@ -286,7 +287,7 @@ public class FrmAddXYData extends javax.swing.JDialog { try { File aFile = aDlg.getSelectedFile(); System.setProperty("user.dir", aFile.getParent()); - String extent = ((org.meteoinfo.global.GenericFileFilter) aDlg.getFileFilter()).getFileExtent(); + String extent = ((GenericFileFilter) aDlg.getFileFilter()).getFileExtent(); String fileName = aFile.getAbsolutePath(); if (!fileName.substring(fileName.length() - extent.length()).equals(extent)) { fileName = fileName + "." + extent; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmConsole.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmConsole.java index 08c0baff..9e95f7f1 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmConsole.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmConsole.java @@ -14,8 +14,8 @@ import java.util.Locale; import javax.imageio.ImageIO; import javax.swing.ImageIcon; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.console.jython.PythonInteractiveInterpreter; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.console.JConsole; import org.meteoinfo.console.jython.JIntrospect; import org.python.core.Py; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMain.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMain.java index d5824aea..6659b375 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMain.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMain.java @@ -56,6 +56,10 @@ import javax.swing.undo.UndoableEdit; import javax.xml.parsers.ParserConfigurationException; import com.formdev.flatlaf.extras.FlatSVGIcon; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointF; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.data.mapdata.webmap.WebMapProvider; import org.meteoinfo.desktop.config.GenericFileFilter; import org.meteoinfo.desktop.config.Options; @@ -64,12 +68,8 @@ import org.meteoinfo.desktop.config.PluginCollection; import org.meteoinfo.desktop.config.ProjectFile; import org.meteoinfo.data.mapdata.FrmAttriData; import org.meteoinfo.data.mapdata.MapDataManage; -import org.meteoinfo.global.Extent; import org.meteoinfo.global.FrmProperty; import org.meteoinfo.global.colors.ColorUtil; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointF; import org.meteoinfo.global.event.ActiveMapFrameChangedEvent; import org.meteoinfo.global.event.ElementSelectedEvent; import org.meteoinfo.global.event.GraphicSelectedEvent; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMeteoData.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMeteoData.java index 8c692ab6..3c43b9e7 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMeteoData.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmMeteoData.java @@ -36,6 +36,9 @@ import javax.swing.SwingWorker; import com.formdev.flatlaf.extras.FlatSVGIcon; import com.formdev.flatlaf.extras.FlatSVGUtils; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.PointF; import org.meteoinfo.desktop.config.GenericFileFilter; import org.meteoinfo.data.DataMath; import org.meteoinfo.data.GridData; @@ -59,9 +62,6 @@ import org.meteoinfo.global.colors.ColorUtil; import org.meteoinfo.legend.*; import org.meteoinfo.geoprocess.analysis.InterpolationMethods; import org.meteoinfo.geoprocess.analysis.InterpolationSetting; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.PointF; import org.meteoinfo.image.AnimatedGifEncoder; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOneDim.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOneDim.java index 10437485..e04e0530 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOneDim.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOneDim.java @@ -29,6 +29,7 @@ import org.meteoinfo.chart.Location; import org.meteoinfo.chart.plot.ChartPlotMethod; import org.meteoinfo.chart.plot.PlotOrientation; import org.meteoinfo.chart.plot.XY1DPlot; +import org.meteoinfo.common.PointD; import org.meteoinfo.data.GridData; import org.meteoinfo.data.XYDataset; import org.meteoinfo.data.XYListDataset; @@ -38,7 +39,6 @@ import org.meteoinfo.data.meteodata.PlotDimension; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.data.meteodata.hysplit.HYSPLITTrajDataInfo; import org.meteoinfo.desktop.config.GenericFileFilter; -import org.meteoinfo.global.PointD; import org.meteoinfo.image.AnimatedGifEncoder; import org.meteoinfo.layer.LayerDrawType; import org.meteoinfo.layer.MapLayer; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOutputMapData.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOutputMapData.java index 0b91e045..155e312f 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOutputMapData.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmOutputMapData.java @@ -18,6 +18,10 @@ import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; + +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.VectorLayer; import org.meteoinfo.desktop.config.GenericFileFilter; @@ -25,9 +29,6 @@ import org.meteoinfo.data.meteodata.GridDataSetting; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.data.meteodata.grads.GrADSDataInfo; import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; import org.meteoinfo.shape.PointShape; import org.meteoinfo.shape.PolygonShape; import org.meteoinfo.shape.PolylineShape; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmPluginManager.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmPluginManager.java index ecbaabec..d3af8f56 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmPluginManager.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmPluginManager.java @@ -12,9 +12,10 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.DefaultListModel; import javax.swing.JFrame; + +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.desktop.config.Plugin; import org.meteoinfo.desktop.config.PluginCollection; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.ui.CheckBoxListEntry; /** diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSectionPlot.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSectionPlot.java index 29110d1e..fb1d54f6 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSectionPlot.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSectionPlot.java @@ -5,6 +5,8 @@ package org.meteoinfo.desktop.forms; import com.formdev.flatlaf.extras.FlatSVGIcon; +import org.meteoinfo.common.Extent; +import org.meteoinfo.common.PointF; import org.meteoinfo.data.GridData; import org.meteoinfo.ndarray.Dimension; import org.meteoinfo.data.meteodata.DrawMeteoData; @@ -13,8 +15,7 @@ import org.meteoinfo.data.meteodata.MeteoDataInfo; import org.meteoinfo.data.meteodata.PlotDimension; import org.meteoinfo.data.meteodata.Variable; import org.meteoinfo.data.meteodata.grads.GrADSDataInfo; -import org.meteoinfo.global.Extent; -import org.meteoinfo.global.PointF; + import java.awt.Color; import java.awt.Cursor; import java.awt.Rectangle; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByAttributes.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByAttributes.java index 14df963e..3262b5b6 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByAttributes.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByAttributes.java @@ -10,7 +10,7 @@ import java.util.Collections; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.ListSelectionModel; -import org.meteoinfo.global.MIMath; + import org.meteoinfo.table.DataRow; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByLocation.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByLocation.java index f8bea528..7acdea59 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByLocation.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmSelectByLocation.java @@ -8,9 +8,10 @@ import java.awt.Cursor; import java.util.ArrayList; import java.util.List; import javax.swing.JOptionPane; + +import org.meteoinfo.common.PointD; import org.meteoinfo.geoprocess.GeoComputation; import org.meteoinfo.geoprocess.SpatialQueryTypes; -import org.meteoinfo.global.PointD; import org.meteoinfo.layer.LayerTypes; import org.meteoinfo.layer.MapLayer; import org.meteoinfo.layer.VectorLayer; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmTextEditor.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmTextEditor.java index 66492537..95e446ea 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmTextEditor.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmTextEditor.java @@ -19,11 +19,9 @@ import java.text.MessageFormat; import java.util.List; import java.util.Locale; import javax.swing.*; -import javax.swing.text.DefaultCaret; +import org.meteoinfo.common.util.GlobalUtil; import org.meteoinfo.console.JConsole; -import org.meteoinfo.console.editor.JTextAreaPrintStream; -import org.meteoinfo.console.editor.JTextAreaWriter; import org.meteoinfo.console.jython.JIntrospect; import org.meteoinfo.console.editor.MITextEditorPane; import org.meteoinfo.console.jython.PythonInteractiveInterpreter; @@ -33,9 +31,7 @@ import org.meteoinfo.console.editor.TextEditor; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rsyntaxtextarea.TextEditorPane; -import org.meteoinfo.global.util.GlobalUtil; import org.meteoinfo.ui.ButtonTabComponent; -import org.python.util.PythonInterpreter; /** * diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmViewData.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmViewData.java index b96acdd2..a527d56c 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmViewData.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmViewData.java @@ -18,12 +18,12 @@ import javax.swing.JOptionPane; import javax.swing.table.DefaultTableModel; import com.formdev.flatlaf.extras.FlatSVGIcon; +import org.meteoinfo.common.MIMath; import org.meteoinfo.data.GridData; import org.meteoinfo.data.StationData; import org.meteoinfo.data.XYListDataset; import org.meteoinfo.data.meteodata.ascii.LonLatStationDataInfo; import org.meteoinfo.desktop.config.GenericFileFilter; -import org.meteoinfo.global.MIMath; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.table.RowHeaderTable; import org.meteoinfo.projection.info.ProjectionInfo; diff --git a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmZoomToExtent.java b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmZoomToExtent.java index e607b4c2..c3ac1939 100644 --- a/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmZoomToExtent.java +++ b/MeteoInfoMap/src/main/java/org/meteoinfo/desktop/forms/FrmZoomToExtent.java @@ -13,7 +13,7 @@ */ package org.meteoinfo.desktop.forms; -import org.meteoinfo.global.Extent; +import org.meteoinfo.common.Extent; import org.meteoinfo.map.MapView; import javax.swing.JOptionPane; diff --git a/meteoinfo-common/meteoinfo-common.iml b/meteoinfo-common/meteoinfo-common.iml new file mode 100644 index 00000000..bd6ce06e --- /dev/null +++ b/meteoinfo-common/meteoinfo-common.iml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/meteoinfo-common/pom.xml b/meteoinfo-common/pom.xml new file mode 100644 index 00000000..aec2a959 --- /dev/null +++ b/meteoinfo-common/pom.xml @@ -0,0 +1,40 @@ + + + + MeteoInfo + org.meteothink + 3.0.0 + + 4.0.0 + + meteoinfo-common + + + + ebi + ebiRepo + http://www.ebi.ac.uk/intact/maven/nexus/content/repositories/ebi-repo/ + + + + + + com.google.guava + guava + 28.0-jre + + + org.mozilla.intl + chardet + 1.0 + + + + + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Bytes2Number.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/Bytes2Number.java similarity index 93% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/Bytes2Number.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/Bytes2Number.java index ca47d7b6..84310321 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Bytes2Number.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/Bytes2Number.java @@ -1,48 +1,48 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.global; - -import java.io.IOException; -import java.io.RandomAccessFile; - -/** - * - * @author yaqiang - */ -public class Bytes2Number { - - /** - * Convert four ints into a signed integer. - * - * @param a Highest int - * @param b Higher middle int - * @param c Lower middle int - * @param d Lowest int - * @return Integer value - */ - public static int int4(int a, int b, int c, int d) { - if ((a == 255) && (b == 255) && (c == 255) && (d == 255)) { - return -9999; - } - - return (1 - ((a & 0x80) >> 6)) * ((a & 0x7F) << 24 | b << 16 | c << 8 | d); - } - - /** - * Read signed integer of 4 bytes from binary reader - * - * @param raf RandomAccessFile - * @return Signed integer - * @throws IOException - */ - public static int int4(RandomAccessFile raf) throws IOException { - int a = raf.read(); - int b = raf.read(); - int c = raf.read(); - int d = raf.read(); - - return int4(a, b, c, d); - } -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author yaqiang + */ +public class Bytes2Number { + + /** + * Convert four ints into a signed integer. + * + * @param a Highest int + * @param b Higher middle int + * @param c Lower middle int + * @param d Lowest int + * @return Integer value + */ + public static int int4(int a, int b, int c, int d) { + if ((a == 255) && (b == 255) && (c == 255) && (d == 255)) { + return -9999; + } + + return (1 - ((a & 0x80) >> 6)) * ((a & 0x7F) << 24 | b << 16 | c << 8 | d); + } + + /** + * Read signed integer of 4 bytes from binary reader + * + * @param raf RandomAccessFile + * @return Signed integer + * @throws IOException + */ + public static int int4(RandomAccessFile raf) throws IOException { + int a = raf.read(); + int b = raf.read(); + int c = raf.read(); + int d = raf.read(); + + return int4(a, b, c, d); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Direction.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/Direction.java similarity index 92% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/Direction.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/Direction.java index 6f42bb8b..ac76dc2f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Direction.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/Direction.java @@ -1,38 +1,38 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global; - -/** - * - * @author Yaqiang Wang - */ -public enum Direction { - /// - /// East - /// - - East, - /// - /// West - /// - Weast, - /// - /// North - /// - North, - /// - /// South - /// - South -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common; + +/** + * + * @author Yaqiang Wang + */ +public enum Direction { + /// + /// East + /// + + East, + /// + /// West + /// + Weast, + /// + /// North + /// + North, + /// + /// South + /// + South +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/Extent.java similarity index 98% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/Extent.java index e84df9d8..37509b20 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/Extent.java @@ -11,9 +11,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. */ -package org.meteoinfo.global; +package org.meteoinfo.common; -import java.awt.Rectangle; +import java.awt.*; /** * Template diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent3D.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/Extent3D.java similarity index 95% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent3D.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/Extent3D.java index c1a55e29..6664a25b 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Extent3D.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/Extent3D.java @@ -1,130 +1,130 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.global; - -/** - * - * @author Yaqiang Wang - */ -public class Extent3D extends Extent{ - public double minZ; - public double maxZ; - - /** - * Constructor - */ - public Extent3D(){ - - } - - /** - * Constructor - * - * @param xMin Minimum X - * @param xMax Maximum X - * @param yMin Minimum Y - * @param yMax Maximum Y - * @param zMin Minimum Z - * @param zMax Maximum Z - */ - public Extent3D(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax) { - super(xMin, xMax, yMin, yMax); - minZ = zMin; - maxZ = zMax; - } - - /** - * Get is 3D or not - * @return false - */ - @Override - public boolean is3D(){ - return true; - } - - /** - * Tests whether this extent intersects the second extent. - * @param extent The second extent - * @return Boolean - */ - @Override - public boolean intersects(Extent extent) { - Extent3D bET = (Extent3D)extent; - return !(maxX < bET.minX || maxY < bET.minY || maxZ < bET.minZ || - bET.maxX < minX || bET.maxY < minY || bET.maxZ < minZ); - } - - /** - * Return union extent - * - * @param ex Other extent - * @return Union extent - */ - public Extent3D union(Extent3D ex) { - Extent3D cET = new Extent3D(); - if (this.isNaN()) { - return (Extent3D) ex.clone(); - } else if (ex.isNaN()) { - return (Extent3D) this.clone(); - } - - cET.minX = Math.min(this.minX, ex.minX); - cET.minY = Math.min(this.minY, ex.minY); - cET.maxX = Math.max(this.maxX, ex.maxX); - cET.maxY = Math.max(this.maxY, ex.maxY); - cET.minZ = Math.min(this.minZ, ex.minZ); - cET.maxZ = Math.max(this.maxZ, ex.maxZ); - - return cET; - } - - /** - * Shift extent - * - * @param dx X shift value - * @param dy Y shift value - * @param dz Z shift value - * @return Shifted extent - */ - public Extent3D shift(double dx, double dy, double dz) { - return new Extent3D(minX + dx, maxX + dx, minY + dy, maxY + dy, minZ + dz, maxZ + dz); - } - - /** - * Extends extent by ratio - * @param ratio The ratio - * @return Extended extent - */ - public Extent3D extend(double ratio) { - double dx = this.getWidth() * ratio; - double dy = this.getHeight() * ratio; - double dz = (maxZ - minZ) * ratio; - return extend(dx, dy, dz); - } - - /** - * Extends extent - * - * @param dx X delta - * @param dy Y delta - * @param dz Z delta - * @return Extended extent - */ - public Extent3D extend(double dx, double dy, double dz) { - return new Extent3D(minX - dx, maxX + dx, minY - dy, maxY + dy, minZ - dz, maxZ + dz); - } - - /** - * Clone - * - * @return Extent object - */ - @Override - public Object clone() { - return new Extent3D(minX, maxX, minY, maxY, minZ, maxZ); - } - -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common; + +/** + * + * @author Yaqiang Wang + */ +public class Extent3D extends Extent{ + public double minZ; + public double maxZ; + + /** + * Constructor + */ + public Extent3D(){ + + } + + /** + * Constructor + * + * @param xMin Minimum X + * @param xMax Maximum X + * @param yMin Minimum Y + * @param yMax Maximum Y + * @param zMin Minimum Z + * @param zMax Maximum Z + */ + public Extent3D(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax) { + super(xMin, xMax, yMin, yMax); + minZ = zMin; + maxZ = zMax; + } + + /** + * Get is 3D or not + * @return false + */ + @Override + public boolean is3D(){ + return true; + } + + /** + * Tests whether this extent intersects the second extent. + * @param extent The second extent + * @return Boolean + */ + @Override + public boolean intersects(Extent extent) { + Extent3D bET = (Extent3D)extent; + return !(maxX < bET.minX || maxY < bET.minY || maxZ < bET.minZ || + bET.maxX < minX || bET.maxY < minY || bET.maxZ < minZ); + } + + /** + * Return union extent + * + * @param ex Other extent + * @return Union extent + */ + public Extent3D union(Extent3D ex) { + Extent3D cET = new Extent3D(); + if (this.isNaN()) { + return (Extent3D) ex.clone(); + } else if (ex.isNaN()) { + return (Extent3D) this.clone(); + } + + cET.minX = Math.min(this.minX, ex.minX); + cET.minY = Math.min(this.minY, ex.minY); + cET.maxX = Math.max(this.maxX, ex.maxX); + cET.maxY = Math.max(this.maxY, ex.maxY); + cET.minZ = Math.min(this.minZ, ex.minZ); + cET.maxZ = Math.max(this.maxZ, ex.maxZ); + + return cET; + } + + /** + * Shift extent + * + * @param dx X shift value + * @param dy Y shift value + * @param dz Z shift value + * @return Shifted extent + */ + public Extent3D shift(double dx, double dy, double dz) { + return new Extent3D(minX + dx, maxX + dx, minY + dy, maxY + dy, minZ + dz, maxZ + dz); + } + + /** + * Extends extent by ratio + * @param ratio The ratio + * @return Extended extent + */ + public Extent3D extend(double ratio) { + double dx = this.getWidth() * ratio; + double dy = this.getHeight() * ratio; + double dz = (maxZ - minZ) * ratio; + return extend(dx, dy, dz); + } + + /** + * Extends extent + * + * @param dx X delta + * @param dy Y delta + * @param dz Z delta + * @return Extended extent + */ + public Extent3D extend(double dx, double dy, double dz) { + return new Extent3D(minX - dx, maxX + dx, minY - dy, maxY + dy, minZ - dz, maxZ + dz); + } + + /** + * Clone + * + * @return Extent object + */ + @Override + public Object clone() { + return new Extent3D(minX, maxX, minY, maxY, minZ, maxZ); + } + +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/GenericFileFilter.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/GenericFileFilter.java similarity index 95% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/GenericFileFilter.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/GenericFileFilter.java index a7cf00e3..4a01dfcd 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/GenericFileFilter.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/GenericFileFilter.java @@ -1,103 +1,103 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.global; - -import java.io.File; -import javax.swing.filechooser.FileFilter; - -/** - * - * @author yaqiang - */ -public class GenericFileFilter extends FileFilter { - - private static final boolean ONE = true; - private String fileExt; - private String[] fileExts; - private boolean type = false; - private String description; - private int length; - private String extension; - - /** - * This is the constructor - it takes in the following:-
filesExtsIn - - * this is the array of file extensions that you wish to create a file - * filter for.
description - this is the description that will be - * displayed in the file chooser dialog box. - */ - public GenericFileFilter(String[] filesExtsIn, String description) { - if (filesExtsIn.length == 1) {//we only have one file - type = ONE; - fileExt = filesExtsIn[0]; - } else { - fileExts = filesExtsIn; - length = fileExts.length; - } - this.description = description; - } - - /** - * This is the method to allow a file to bee added to the displayed list or - * not. This method is called by the model that handles the FileChooser - * dialog - */ - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - extension = getExtension(f); - if (extension != null) { - if (type) { - return check(fileExt); - } else { - for (int i = 0; i < length; i++) { - if (check(fileExts[i])) { - return true; - } - } - } - } - return false; - } - - /** - * This checks to see if the extension (stored) is the same as the file type - * stored at construction time. The "in" being the value passed over. - */ - private boolean check(String in) { - return extension.equalsIgnoreCase(in); - } - - /** - * This is the method defined by the model - */ - @Override - public String getDescription() { - return description; - } - - /** - * Get file extent - * - * @return File extent - */ - public String getFileExtent(){ - return fileExt; - } - - /** - * This is the method to get the file extension from the file name - */ - public static String getExtension(File file) { - String filename = file.getName(); - int length = filename.length(); - int i = filename.lastIndexOf('.'); - if (i > 0 && i < length - 1) { - return filename.substring(i + 1).toLowerCase(); - } - return null; - } -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common; + +import javax.swing.filechooser.FileFilter; +import java.io.File; + +/** + * + * @author yaqiang + */ +public class GenericFileFilter extends FileFilter { + + private static final boolean ONE = true; + private String fileExt; + private String[] fileExts; + private boolean type = false; + private String description; + private int length; + private String extension; + + /** + * This is the constructor - it takes in the following:-
filesExtsIn - + * this is the array of file extensions that you wish to create a file + * filter for.
description - this is the description that will be + * displayed in the file chooser dialog box. + */ + public GenericFileFilter(String[] filesExtsIn, String description) { + if (filesExtsIn.length == 1) {//we only have one file + type = ONE; + fileExt = filesExtsIn[0]; + } else { + fileExts = filesExtsIn; + length = fileExts.length; + } + this.description = description; + } + + /** + * This is the method to allow a file to bee added to the displayed list or + * not. This method is called by the model that handles the FileChooser + * dialog + */ + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + extension = getExtension(f); + if (extension != null) { + if (type) { + return check(fileExt); + } else { + for (int i = 0; i < length; i++) { + if (check(fileExts[i])) { + return true; + } + } + } + } + return false; + } + + /** + * This checks to see if the extension (stored) is the same as the file type + * stored at construction time. The "in" being the value passed over. + */ + private boolean check(String in) { + return extension.equalsIgnoreCase(in); + } + + /** + * This is the method defined by the model + */ + @Override + public String getDescription() { + return description; + } + + /** + * Get file extent + * + * @return File extent + */ + public String getFileExtent(){ + return fileExt; + } + + /** + * This is the method to get the file extension from the file name + */ + public static String getExtension(File file) { + String filename = file.getName(); + int length = filename.length(); + int i = filename.lastIndexOf('.'); + if (i > 0 && i < length - 1) { + return filename.substring(i + 1).toLowerCase(); + } + return null; + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/MIMath.java similarity index 87% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/MIMath.java index 929ea850..4b5938cb 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/MIMath.java @@ -11,17 +11,14 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. */ -package org.meteoinfo.global; +package org.meteoinfo.common; -import java.awt.Point; -import java.awt.Rectangle; +import org.meteoinfo.common.util.BigDecimalUtil; + +import java.awt.*; import java.util.ArrayList; import java.util.List; -import org.meteoinfo.ndarray.util.BigDecimalUtil; -import org.meteoinfo.shape.PointZ; -import org.meteoinfo.shape.Shape; - /** * MeteoInfo Math class * @@ -187,74 +184,6 @@ public class MIMath { } } - /** - * Get extent from point list - * - * @param PList point list - * @return extent - */ - public static Extent getPointsExtent(List PList) { - if (PList.get(0) instanceof PointZ){ - Extent3D cET = new Extent3D(); - for (int i = 0; i < PList.size(); i++) { - PointZ aP = (PointZ)PList.get(i); - if (i == 0) { - cET.minX = aP.X; - cET.maxX = aP.X; - cET.minY = aP.Y; - cET.maxY = aP.Y; - cET.minZ = aP.Z; - cET.maxZ = aP.Z; - } else { - if (cET.minX > aP.X) { - cET.minX = aP.X; - } else if (cET.maxX < aP.X) { - cET.maxX = aP.X; - } - - if (cET.minY > aP.Y) { - cET.minY = aP.Y; - } else if (cET.maxY < aP.Y) { - cET.maxY = aP.Y; - } - - if (cET.minZ > aP.Z) { - cET.minZ = aP.Z; - } else if (cET.maxZ < aP.Z) { - cET.maxZ = aP.Z; - } - } - } - - return cET; - } else { - Extent cET = new Extent(); - for (int i = 0; i < PList.size(); i++) { - PointD aP = PList.get(i); - if (i == 0) { - cET.minX = aP.X; - cET.maxX = aP.X; - cET.minY = aP.Y; - cET.maxY = aP.Y; - } else { - if (cET.minX > aP.X) { - cET.minX = aP.X; - } else if (cET.maxX < aP.X) { - cET.maxX = aP.X; - } - - if (cET.minY > aP.Y) { - cET.minY = aP.Y; - } else if (cET.maxY < aP.Y) { - cET.maxY = aP.Y; - } - } - } - - return cET; - } - } - /** * Get extent from PointF array * @@ -535,89 +464,6 @@ public class MIMath { return cET; } - /** - * Get extent of the shapes - * - * @param shapes - * @return Extent - */ - public static Extent getExtent(List shapes) { - Extent extent = (Extent) shapes.get(0).getExtent().clone(); - double minx = extent.minX; - double maxx = extent.maxX; - double miny = extent.minY; - double maxy = extent.maxY; - Extent ext; - for (int i = 1; i < shapes.size(); i++) { - ext = shapes.get(i).getExtent(); - if (minx > ext.minX) { - minx = ext.minX; - } - if (maxx < ext.maxX) { - maxx = ext.maxX; - } - if (miny > ext.minY) { - miny = ext.minY; - } - if (maxy < ext.maxY) { - maxy = ext.maxY; - } - } - - extent.minX = minx; - extent.maxX = maxx; - extent.minY = miny; - extent.maxY = maxy; - - return extent; - } - - /** - * Get extent of the points - * - * @param points - * @return Extent - */ - public static Extent3D getExtent(PointZ[] points) { - PointZ p = points[0]; - double minx = p.X; - double maxx = p.X; - double miny = p.Y; - double maxy = p.Y; - double minz = p.Z; - double maxz = p.Z; - for (int i = 1; i < points.length; i++) { - if (minx > p.X) { - minx = p.M; - } - if (maxx < p.X) { - maxx = p.M; - } - if (miny > p.Y) { - miny = p.Y; - } - if (maxy < p.Y) { - maxy = p.Y; - } - if (minz > p.Z) { - minz = p.Z; - } - if (maxz < p.Z) { - maxz = p.Z; - } - } - - Extent3D extent = new Extent3D(); - extent.minX = minx; - extent.maxX = maxx; - extent.minY = miny; - extent.maxY = maxy; - extent.minZ = minz; - extent.maxZ = maxz; - - return extent; - } - /** * Determine if two extent cross each other * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/PointD.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/PointD.java similarity index 98% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/PointD.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/PointD.java index 5144953b..3c23ebaf 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/PointD.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/PointD.java @@ -12,7 +12,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. */ -package org.meteoinfo.global; +package org.meteoinfo.common; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/PointF.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/PointF.java similarity index 93% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/PointF.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/PointF.java index 0c875fd3..b7bc6d61 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/PointF.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/PointF.java @@ -1,67 +1,67 @@ -/* - * Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.global; - -/** - * PointF class - * - * @author Yaqiang Wang - */ -public class PointF implements Cloneable{ - // - - public float X; - public float Y; - // - // - - /** - * Constructor - */ - public PointF() { - } - - /** - * Contructor - * @param x - * @param y - */ - public PointF(float x, float y) { - X = x; - Y = y; - } - // - // - // - // - - /** - * Clone - * - * @return PointF object - */ - @Override - public Object clone() { - PointF o = null; - try { - o = (PointF)super.clone(); - } catch (CloneNotSupportedException ex) { - ex.printStackTrace(); - } - - return o; - } - // -} +/* + * Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common; + +/** + * PointF class + * + * @author Yaqiang Wang + */ +public class PointF implements Cloneable{ + // + + public float X; + public float Y; + // + // + + /** + * Constructor + */ + public PointF() { + } + + /** + * Contructor + * @param x + * @param y + */ + public PointF(float x, float y) { + X = x; + Y = y; + } + // + // + // + // + + /** + * Clone + * + * @return PointF object + */ + @Override + public Object clone() { + PointF o = null; + try { + o = (PointF)super.clone(); + } catch (CloneNotSupportedException ex) { + ex.printStackTrace(); + } + + return o; + } + // +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Template.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/Template.java similarity index 96% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/Template.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/Template.java index dd83d847..3086aa1d 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/Template.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/Template.java @@ -11,7 +11,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. */ -package org.meteoinfo.global; +package org.meteoinfo.common; /** * Template diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EncodingDetect.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EncodingDetect.java similarity index 97% rename from MeteoInfoLib/src/main/java/org/meteoinfo/io/EncodingDetect.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/io/EncodingDetect.java index 14000fe7..ac2768ac 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EncodingDetect.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EncodingDetect.java @@ -1,4830 +1,4830 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.io; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.net.URL; - -/** - * (Detect encoding .) Copyright (C) (2009) (Fluck,ACC http://androidos.cc/dev ) - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * @author Billows.Van - * @since Create on 2010-01-27 11:19:00 - * @version 1.0 - */ -public class EncodingDetect extends Encoding { - - public static void main(String argc[]) { - if (argc.length == 0) { - System.out.println("Usage: EncodingDetect ... [-d]"); - System.exit(1); - } - EncodingDetect sinodetector; - int result = OTHER; - int i; - sinodetector = new EncodingDetect(); - for (i = 0; i < argc.length; i++) { - if (argc[i].startsWith("http://") == true) { - try { - result = sinodetector.detectEncoding(new URL(argc[i])); - } catch (Exception e) { - System.err.println("Bad URL " + e.toString()); - } - } else if (argc[i].equals("-d")) { - sinodetector.debug = true; - continue; - } else { - result = sinodetector.detectEncoding(new File(argc[i])); - } - System.out.println(nicename[result]); - } - } - - // Frequency tables to hold the GB, Big5, and EUC-TW character - // frequencies - int GBFreq[][]; - - int GBKFreq[][]; - - int Big5Freq[][]; - - int Big5PFreq[][]; - - int EUC_TWFreq[][]; - - int KRFreq[][]; - - int JPFreq[][]; - - // int UnicodeFreq[94][128]; - // public static String[] nicename; - // public static String[] codings; - public boolean debug; - - public EncodingDetect() { - super(); - debug = false; - GBFreq = new int[94][94]; - GBKFreq = new int[126][191]; - Big5Freq = new int[94][158]; - Big5PFreq = new int[126][191]; - EUC_TWFreq = new int[94][94]; - KRFreq = new int[94][94]; - JPFreq = new int[94][94]; - // Initialize the Frequency Table for GB, GBK, Big5, EUC-TW, KR, JP - initialize_frequencies(); - } - - /** - * Function : detectEncoding Aruguments: URL Returns : One of the encodings - * from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, or OTHER) - * Description: This function looks at the URL contents and assigns it a - * probability score for each encoding type. The encoding type with the - * highest probability is returned. - */ - public int detectEncoding(URL testurl) { - byte[] rawtext = new byte[10000]; - int bytesread = 0, byteoffset = 0; - int guess = OTHER; - InputStream chinesestream; - try { - chinesestream = testurl.openStream(); - while ((bytesread = chinesestream.read(rawtext, byteoffset, rawtext.length - byteoffset)) > 0) { - byteoffset += bytesread; - } - ; - chinesestream.close(); - guess = detectEncoding(rawtext); - } catch (Exception e) { - System.err.println("Error loading or using URL " + e.toString()); - guess = -1; - } - return guess; - } - - /** - * Function : detectEncoding Aruguments: File Returns : One of the encodings - * from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, or OTHER) - * Description: This function looks at the file and assigns it a probability - * score for each encoding type. The encoding type with the highest - * probability is returned. - */ - public int detectEncoding(File testfile) { - FileInputStream chinesefile; - byte[] rawtext; - rawtext = new byte[(int) testfile.length()]; - try { - chinesefile = new FileInputStream(testfile); - chinesefile.read(rawtext); - chinesefile.close(); - } catch (Exception e) { - System.err.println("Error: " + e); - e.printStackTrace(); - } - return detectEncoding(rawtext); - } - - /** - * Function : detectEncoding Aruguments: byte array Returns : One of the - * encodings from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, - * or OTHER) Description: This function looks at the byte array and assigns - * it a probability score for each encoding type. The encoding type with the - * highest probability is returned. - */ - public int detectEncoding(byte[] rawtext) { - int[] scores; - int index, maxscore = 0; - int encoding_guess = OTHER; - scores = new int[TOTALTYPES]; - // Assign Scores - scores[GB2312] = gb2312_probability(rawtext); - scores[GBK] = gbk_probability(rawtext); - scores[GB18030] = gb18030_probability(rawtext); - scores[HZ] = hz_probability(rawtext); - scores[BIG5] = big5_probability(rawtext); - scores[CNS11643] = euc_tw_probability(rawtext); - scores[ISO2022CN] = iso_2022_cn_probability(rawtext); - scores[UTF8] = utf8_probability(rawtext); - scores[UNICODE] = utf16_probability(rawtext); - scores[EUC_KR] = euc_kr_probability(rawtext); - scores[CP949] = cp949_probability(rawtext); - scores[JOHAB] = 0; - scores[ISO2022KR] = iso_2022_kr_probability(rawtext); - scores[ASCII] = ascii_probability(rawtext); - scores[SJIS] = sjis_probability(rawtext); - scores[EUC_JP] = euc_jp_probability(rawtext); - scores[ISO2022JP] = iso_2022_jp_probability(rawtext); - scores[UNICODET] = 0; - scores[UNICODES] = 0; - scores[ISO2022CN_GB] = 0; - scores[ISO2022CN_CNS] = 0; - scores[OTHER] = 0; - // Tabulate Scores - for (index = 0; index < TOTALTYPES; index++) { - if (debug) { - System.err.println("Encoding " + nicename[index] + " score " + scores[index]); - } - if (scores[index] > maxscore) { - encoding_guess = index; - maxscore = scores[index]; - } - } - // Return OTHER if nothing scored above 50 - if (maxscore <= 50) { - encoding_guess = OTHER; - } - return encoding_guess; - } - - /* - * Function: gb2312_probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses GB-2312 - * encoding - */ - int gb2312_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, gbchars = 1; - long gbfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 && (byte) 0xA1 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0xFE) { - gbchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - if (GBFreq[row][column] != 0) { - gbfreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - // In GB high-freq character range - gbfreq += 200; - } - } - i++; - } - } - rangeval = 50 * ((float) gbchars / (float) dbchars); - freqval = 50 * ((float) gbfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - /* - * Function: gbk_probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses GBK - * encoding - */ - int gbk_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, gbchars = 1; - long gbfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 - && // Original - // GB - // range - (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { - gbchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - // System.out.println("original row " + row + " column " + - // column); - if (GBFreq[row][column] != 0) { - gbfreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - gbfreq += 200; - } - } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE - && // Extended - // GB - // range - (((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) - || ((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E))) { - gbchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0x81; - if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { - column = rawtext[i + 1] - 0x40; - } else { - column = rawtext[i + 1] + 256 - 0x40; - } - // System.out.println("extended row " + row + " column " + - // column + " rawtext[i] " + rawtext[i]); - if (GBKFreq[row][column] != 0) { - gbfreq += GBKFreq[row][column]; - } - } - i++; - } - } - rangeval = 50 * ((float) gbchars / (float) dbchars); - freqval = 50 * ((float) gbfreq / (float) totalfreq); - // For regular GB files, this would give the same score, so I handicap - // it slightly - return (int) (rangeval + freqval) - 1; - } - - /* - * Function: gb18030_probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses GBK - * encoding - */ - int gb18030_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, gbchars = 1; - long gbfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 - && // Original - // GB - // range - i + 1 < rawtextlen && (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { - gbchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - // System.out.println("original row " + row + " column " + - // column); - if (GBFreq[row][column] != 0) { - gbfreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - gbfreq += 200; - } - } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE - && // Extended - // GB - // range - i + 1 < rawtextlen && (((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) - || ((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E))) { - gbchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0x81; - if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { - column = rawtext[i + 1] - 0x40; - } else { - column = rawtext[i + 1] + 256 - 0x40; - } - // System.out.println("extended row " + row + " column " + - // column + " rawtext[i] " + rawtext[i]); - if (GBKFreq[row][column] != 0) { - gbfreq += GBKFreq[row][column]; - } - } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE - && // Extended - // GB - // range - i + 3 < rawtextlen && (byte) 0x30 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x39 - && (byte) 0x81 <= rawtext[i + 2] && rawtext[i + 2] <= (byte) 0xFE - && (byte) 0x30 <= rawtext[i + 3] && rawtext[i + 3] <= (byte) 0x39) { - gbchars++; - /* - * totalfreq += 500; row = rawtext[i] + 256 - 0x81; if (0x40 - * <= rawtext[i+1] && rawtext[i+1] <= 0x7E) { column = - * rawtext[i+1] - 0x40; } else { column = rawtext[i+1] + 256 - * - 0x40; } //System.out.println("extended row " + row + " - * column " + column + " rawtext[i] " + rawtext[i]); if - * (GBKFreq[row][column] != 0) { gbfreq += - * GBKFreq[row][column]; } - */ - } - i++; - } - } - rangeval = 50 * ((float) gbchars / (float) dbchars); - freqval = 50 * ((float) gbfreq / (float) totalfreq); - // For regular GB files, this would give the same score, so I handicap - // it slightly - return (int) (rangeval + freqval) - 1; - } - - /* - * Function: hz_probability Argument: byte array Returns : number from 0 to - * 100 representing probability text in array uses HZ encoding - */ - @SuppressWarnings("unused") - int hz_probability(byte[] rawtext) { - int i, rawtextlen; - int hzchars = 0, dbchars = 1; - long hzfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int hzstart = 0, hzend = 0; - int row, column; - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen; i++) { - if (rawtext[i] == '~') { - if (rawtext[i + 1] == '{') { - hzstart++; - i += 2; - while (i < rawtextlen - 1) { - if (rawtext[i] == 0x0A || rawtext[i] == 0x0D) { - break; - } else if (rawtext[i] == '~' && rawtext[i + 1] == '}') { - hzend++; - i++; - break; - } else if ((0x21 <= rawtext[i] && rawtext[i] <= 0x77) - && (0x21 <= rawtext[i + 1] && rawtext[i + 1] <= 0x77)) { - hzchars += 2; - row = rawtext[i] - 0x21; - column = rawtext[i + 1] - 0x21; - totalfreq += 500; - if (GBFreq[row][column] != 0) { - hzfreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - hzfreq += 200; - } - } else if ((0xA1 <= rawtext[i] && rawtext[i] <= 0xF7) - && (0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= 0xF7)) { - hzchars += 2; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - totalfreq += 500; - if (GBFreq[row][column] != 0) { - hzfreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - hzfreq += 200; - } - } - dbchars += 2; - i += 2; - } - } else if (rawtext[i + 1] == '}') { - hzend++; - i++; - } else if (rawtext[i + 1] == '~') { - i++; - } - } - } - if (hzstart > 4) { - rangeval = 50; - } else if (hzstart > 1) { - rangeval = 41; - } else if (hzstart > 0) { // Only 39 in case the sequence happened to - // occur - rangeval = 39; // in otherwise non-Hz text - } else { - rangeval = 0; - } - freqval = 50 * ((float) hzfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - /** - * Function: big5_probability Argument: byte array Returns : number from 0 - * to 100 representing probability text in array uses Big5 encoding - */ - int big5_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, bfchars = 1; - float rangeval = 0, freqval = 0; - long bffreq = 0, totalfreq = 1; - int row, column; - // Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF9 - && (((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E) - || ((byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE))) { - bfchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { - column = rawtext[i + 1] - 0x40; - } else { - column = rawtext[i + 1] + 256 - 0x61; - } - if (Big5Freq[row][column] != 0) { - bffreq += Big5Freq[row][column]; - } else if (3 <= row && row <= 37) { - bffreq += 200; - } - } - i++; - } - } - rangeval = 50 * ((float) bfchars / (float) dbchars); - freqval = 50 * ((float) bffreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - /* - * Function: big5plus_probability Argument: pointer to unsigned char array - * Returns : number from 0 to 100 representing probability text in array - * uses Big5+ encoding - */ - int big5plus_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, bfchars = 1; - long bffreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 128) { - // asciichars++; - } else { - dbchars++; - if (0xA1 <= rawtext[i] && rawtext[i] <= 0xF9 - && // Original Big5 - // range - ((0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) - || (0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= 0xFE))) { - bfchars++; - totalfreq += 500; - row = rawtext[i] - 0xA1; - if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { - column = rawtext[i + 1] - 0x40; - } else { - column = rawtext[i + 1] - 0x61; - } - // System.out.println("original row " + row + " column " + - // column); - if (Big5Freq[row][column] != 0) { - bffreq += Big5Freq[row][column]; - } else if (3 <= row && row < 37) { - bffreq += 200; - } - } else if (0x81 <= rawtext[i] && rawtext[i] <= 0xFE - && // Extended - // Big5 - // range - ((0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) - || (0x80 <= rawtext[i + 1] && rawtext[i + 1] <= 0xFE))) { - bfchars++; - totalfreq += 500; - row = rawtext[i] - 0x81; - if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { - column = rawtext[i + 1] - 0x40; - } else { - column = rawtext[i + 1] - 0x40; - } - // System.out.println("extended row " + row + " column " + - // column + " rawtext[i] " + rawtext[i]); - if (Big5PFreq[row][column] != 0) { - bffreq += Big5PFreq[row][column]; - } - } - i++; - } - } - rangeval = 50 * ((float) bfchars / (float) dbchars); - freqval = 50 * ((float) bffreq / (float) totalfreq); - // For regular Big5 files, this would give the same score, so I handicap - // it slightly - return (int) (rangeval + freqval) - 1; - } - - /* - * Function: euc_tw_probability Argument: byte array Returns : number from 0 - * to 100 representing probability text in array uses EUC-TW (CNS 11643) - * encoding - */ - int euc_tw_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, cnschars = 1; - long cnsfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Check to see if characters fit into acceptable ranges - // and have expected frequency of use - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - if (rawtext[i] >= 0) { // in ASCII range - // asciichars++; - } else { // high bit set - dbchars++; - if (i + 3 < rawtextlen && (byte) 0x8E == rawtext[i] && (byte) 0xA1 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0xB0 && (byte) 0xA1 <= rawtext[i + 2] - && rawtext[i + 2] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 3] - && rawtext[i + 3] <= (byte) 0xFE) { // Planes 1 - 16 - cnschars++; - // System.out.println("plane 2 or above CNS char"); - // These are all less frequent chars so just ignore freq - i += 3; - } else if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE - && // Plane - // 1 - (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { - cnschars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - if (EUC_TWFreq[row][column] != 0) { - cnsfreq += EUC_TWFreq[row][column]; - } else if (35 <= row && row <= 92) { - cnsfreq += 150; - } - i++; - } - } - } - rangeval = 50 * ((float) cnschars / (float) dbchars); - freqval = 50 * ((float) cnsfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - /* - * Function: iso_2022_cn_probability Argument: byte array Returns : number - * from 0 to 100 representing probability text in array uses ISO 2022-CN - * encoding WORKS FOR BASIC CASES, BUT STILL NEEDS MORE WORK - */ - int iso_2022_cn_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, isochars = 1; - long isofreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Check to see if characters fit into acceptable ranges - // and have expected frequency of use - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - if (rawtext[i] == (byte) 0x1B && i + 3 < rawtextlen) { // Escape - // char ESC - if (rawtext[i + 1] == (byte) 0x24 && rawtext[i + 2] == 0x29 && rawtext[i + 3] == (byte) 0x41) { // GB - // Escape - // $ - // ) - // A - i += 4; - while (rawtext[i] != (byte) 0x1B) { - dbchars++; - if ((0x21 <= rawtext[i] && rawtext[i] <= 0x77) - && (0x21 <= rawtext[i + 1] && rawtext[i + 1] <= 0x77)) { - isochars++; - row = rawtext[i] - 0x21; - column = rawtext[i + 1] - 0x21; - totalfreq += 500; - if (GBFreq[row][column] != 0) { - isofreq += GBFreq[row][column]; - } else if (15 <= row && row < 55) { - isofreq += 200; - } - i++; - } - i++; - } - } else if (i + 3 < rawtextlen && rawtext[i + 1] == (byte) 0x24 && rawtext[i + 2] == (byte) 0x29 - && rawtext[i + 3] == (byte) 0x47) { - // CNS Escape $ ) G - i += 4; - while (rawtext[i] != (byte) 0x1B) { - dbchars++; - if ((byte) 0x21 <= rawtext[i] && rawtext[i] <= (byte) 0x7E && (byte) 0x21 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0x7E) { - isochars++; - totalfreq += 500; - row = rawtext[i] - 0x21; - column = rawtext[i + 1] - 0x21; - if (EUC_TWFreq[row][column] != 0) { - isofreq += EUC_TWFreq[row][column]; - } else if (35 <= row && row <= 92) { - isofreq += 150; - } - i++; - } - i++; - } - } - if (rawtext[i] == (byte) 0x1B && i + 2 < rawtextlen && rawtext[i + 1] == (byte) 0x28 - && rawtext[i + 2] == (byte) 0x42) { // ASCII: - // ESC - // ( B - i += 2; - } - } - } - rangeval = 50 * ((float) isochars / (float) dbchars); - freqval = 50 * ((float) isofreq / (float) totalfreq); - // System.out.println("isochars dbchars isofreq totalfreq " + isochars + - // " " + dbchars + " " + isofreq + " " + totalfreq + " - // " + rangeval + " " + freqval); - return (int) (rangeval + freqval); - // return 0; - } - - /* - * Function: utf8_probability Argument: byte array Returns : number from 0 - * to 100 representing probability text in array uses UTF-8 encoding of - * Unicode - */ - int utf8_probability(byte[] rawtext) { - int score = 0; - int i, rawtextlen = 0; - int goodbytes = 0, asciibytes = 0; - // Maybe also use UTF8 Byte Order Mark: EF BB BF - // Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen; i++) { - if ((rawtext[i] & (byte) 0x7F) == rawtext[i]) { // One byte - asciibytes++; - // Ignore ASCII, can throw off count - } else if (-64 <= rawtext[i] && rawtext[i] <= -33 - && // Two bytes - i + 1 < rawtextlen && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65) { - goodbytes += 2; - i++; - } else if (-32 <= rawtext[i] && rawtext[i] <= -17 - && // Three bytes - i + 2 < rawtextlen && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 && -128 <= rawtext[i + 2] - && rawtext[i + 2] <= -65) { - goodbytes += 3; - i += 2; - } - } - if (asciibytes == rawtextlen) { - return 0; - } - score = (int) (100 * ((float) goodbytes / (float) (rawtextlen - asciibytes))); - // System.out.println("rawtextlen " + rawtextlen + " goodbytes " + - // goodbytes + " asciibytes " + asciibytes + " score " + - // score); - // If not above 98, reduce to zero to prevent coincidental matches - // Allows for some (few) bad formed sequences - if (score > 98) { - return score; - } else if (score > 95 && goodbytes > 30) { - return score; - } else { - return 0; - } - } - - /* - * Function: utf16_probability Argument: byte array Returns : number from 0 - * to 100 representing probability text in array uses UTF-16 encoding of - * Unicode, guess based on BOM // NOT VERY GENERAL, NEEDS MUCH MORE WORK - */ - int utf16_probability(byte[] rawtext) { - // int score = 0; - // int i, rawtextlen = 0; - // int goodbytes = 0, asciibytes = 0; - if (rawtext.length > 1 && ((byte) 0xFE == rawtext[0] && (byte) 0xFF == rawtext[1]) - || // Big-endian - ((byte) 0xFF == rawtext[0] && (byte) 0xFE == rawtext[1])) { // Little-endian - return 100; - } - return 0; - /* - * // Check to see if characters fit into acceptable ranges rawtextlen = - * rawtext.length; for (i = 0; i < rawtextlen; i++) { if ((rawtext[i] & - * (byte)0x7F) == rawtext[i]) { // One byte goodbytes += 1; - * asciibytes++; } else if ((rawtext[i] & (byte)0xDF) == rawtext[i]) { - * // Two bytes if (i+1 < rawtextlen && (rawtext[i+1] & (byte)0xBF) == - * rawtext[i+1]) { goodbytes += 2; i++; } } else if ((rawtext[i] & - * (byte)0xEF) == rawtext[i]) { // Three bytes if (i+2 < rawtextlen && - * (rawtext[i+1] & (byte)0xBF) == rawtext[i+1] && (rawtext[i+2] & - * (byte)0xBF) == rawtext[i+2]) { goodbytes += 3; i+=2; } } } - * - * score = (int)(100 * ((float)goodbytes/(float)rawtext.length)); // An - * all ASCII file is also a good UTF8 file, but I'd rather it // get - * identified as ASCII. Can delete following 3 lines otherwise if - * (goodbytes == asciibytes) { score = 0; } // If not above 90, reduce - * to zero to prevent coincidental matches if (score > 90) { return - * score; } else { return 0; } - */ - } - - /* - * Function: ascii_probability Argument: byte array Returns : number from 0 - * to 100 representing probability text in array uses all ASCII Description: - * Sees if array has any characters not in ASCII range, if so, score is - * reduced - */ - int ascii_probability(byte[] rawtext) { - int score = 75; - int i, rawtextlen; - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen; i++) { - if (rawtext[i] < 0) { - score = score - 5; - } else if (rawtext[i] == (byte) 0x1B) { // ESC (used by ISO 2022) - score = score - 5; - } - if (score <= 0) { - return 0; - } - } - return score; - } - - /* - * Function: euc_kr__probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses EUC-KR - * encoding - */ - int euc_kr_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, krchars = 1; - long krfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0xFE) { - krchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - if (KRFreq[row][column] != 0) { - krfreq += KRFreq[row][column]; - } else if (15 <= row && row < 55) { - krfreq += 0; - } - } - i++; - } - } - rangeval = 50 * ((float) krchars / (float) dbchars); - freqval = 50 * ((float) krfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - /* - * Function: cp949__probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses Cp949 - * encoding - */ - int cp949_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, krchars = 1; - long krfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE - && ((byte) 0x41 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x5A - || (byte) 0x61 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7A - || (byte) 0x81 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE)) { - krchars++; - totalfreq += 500; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0xFE) { - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - if (KRFreq[row][column] != 0) { - krfreq += KRFreq[row][column]; - } - } - } - i++; - } - } - rangeval = 50 * ((float) krchars / (float) dbchars); - freqval = 50 * ((float) krfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - int iso_2022_kr_probability(byte[] rawtext) { - int i; - for (i = 0; i < rawtext.length; i++) { - if (i + 3 < rawtext.length && rawtext[i] == 0x1b && (char) rawtext[i + 1] == '$' - && (char) rawtext[i + 2] == ')' && (char) rawtext[i + 3] == 'C') { - return 100; - } - } - return 0; - } - - /* - * Function: euc_jp_probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses EUC-JP - * encoding - */ - int euc_jp_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, jpchars = 1; - long jpfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] - && rawtext[i + 1] <= (byte) 0xFE) { - jpchars++; - totalfreq += 500; - row = rawtext[i] + 256 - 0xA1; - column = rawtext[i + 1] + 256 - 0xA1; - if (JPFreq[row][column] != 0) { - jpfreq += JPFreq[row][column]; - } else if (15 <= row && row < 55) { - jpfreq += 0; - } - } - i++; - } - } - rangeval = 50 * ((float) jpchars / (float) dbchars); - freqval = 50 * ((float) jpfreq / (float) totalfreq); - return (int) (rangeval + freqval); - } - - int iso_2022_jp_probability(byte[] rawtext) { - int i; - for (i = 0; i < rawtext.length; i++) { - if (i + 2 < rawtext.length && rawtext[i] == 0x1b && (char) rawtext[i + 1] == '$' - && (char) rawtext[i + 2] == 'B') { - return 100; - } - } - return 0; - } - - /* - * Function: sjis_probability Argument: pointer to byte array Returns : - * number from 0 to 100 representing probability text in array uses - * Shift-JIS encoding - */ - int sjis_probability(byte[] rawtext) { - int i, rawtextlen = 0; - int dbchars = 1, jpchars = 1; - long jpfreq = 0, totalfreq = 1; - float rangeval = 0, freqval = 0; - int row, column, adjust; - // Stage 1: Check to see if characters fit into acceptable ranges - rawtextlen = rawtext.length; - for (i = 0; i < rawtextlen - 1; i++) { - // System.err.println(rawtext[i]); - if (rawtext[i] >= 0) { - // asciichars++; - } else { - dbchars++; - if (i + 1 < rawtext.length - && (((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0x9F) - || ((byte) 0xE0 <= rawtext[i] && rawtext[i] <= (byte) 0xEF)) - && (((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E) - || ((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFC))) { - jpchars++; - totalfreq += 500; - row = rawtext[i] + 256; - column = rawtext[i + 1] + 256; - if (column < 0x9f) { - adjust = 1; - if (column > 0x7f) { - column -= 0x20; - } else { - column -= 0x19; - } - } else { - adjust = 0; - column -= 0x7e; - } - if (row < 0xa0) { - row = ((row - 0x70) << 1) - adjust; - } else { - row = ((row - 0xb0) << 1) - adjust; - } - row -= 0x20; - column = 0x20; - // System.out.println("original row " + row + " column " + - // column); - if (row < JPFreq.length && column < JPFreq[row].length && JPFreq[row][column] != 0) { - jpfreq += JPFreq[row][column]; - } - i++; - } else if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xDF) { - // half-width katakana, convert to full-width - } - } - } - rangeval = 50 * ((float) jpchars / (float) dbchars); - freqval = 50 * ((float) jpfreq / (float) totalfreq); - // For regular GB files, this would give the same score, so I handicap - // it slightly - return (int) (rangeval + freqval) - 1; - } - - void initialize_frequencies() { - int i, j; - for (i = 0; i < 94; i++) { - for (j = 0; j < 94; j++) { - GBFreq[i][j] = 0; - } - } - for (i = 0; i < 126; i++) { - for (j = 0; j < 191; j++) { - GBKFreq[i][j] = 0; - } - } - for (i = 0; i < 94; i++) { - for (j = 0; j < 158; j++) { - Big5Freq[i][j] = 0; - } - } - for (i = 0; i < 126; i++) { - for (j = 0; j < 191; j++) { - Big5PFreq[i][j] = 0; - } - } - for (i = 0; i < 94; i++) { - for (j = 0; j < 94; j++) { - EUC_TWFreq[i][j] = 0; - } - } - for (i = 0; i < 94; i++) { - for (j = 0; j < 94; j++) { - JPFreq[i][j] = 0; - } - } - GBFreq[20][35] = 599; - GBFreq[49][26] = 598; - GBFreq[41][38] = 597; - GBFreq[17][26] = 596; - GBFreq[32][42] = 595; - GBFreq[39][42] = 594; - GBFreq[45][49] = 593; - GBFreq[51][57] = 592; - GBFreq[50][47] = 591; - GBFreq[42][90] = 590; - GBFreq[52][65] = 589; - GBFreq[53][47] = 588; - GBFreq[19][82] = 587; - GBFreq[31][19] = 586; - GBFreq[40][46] = 585; - GBFreq[24][89] = 584; - GBFreq[23][85] = 583; - GBFreq[20][28] = 582; - GBFreq[42][20] = 581; - GBFreq[34][38] = 580; - GBFreq[45][9] = 579; - GBFreq[54][50] = 578; - GBFreq[25][44] = 577; - GBFreq[35][66] = 576; - GBFreq[20][55] = 575; - GBFreq[18][85] = 574; - GBFreq[20][31] = 573; - GBFreq[49][17] = 572; - GBFreq[41][16] = 571; - GBFreq[35][73] = 570; - GBFreq[20][34] = 569; - GBFreq[29][44] = 568; - GBFreq[35][38] = 567; - GBFreq[49][9] = 566; - GBFreq[46][33] = 565; - GBFreq[49][51] = 564; - GBFreq[40][89] = 563; - GBFreq[26][64] = 562; - GBFreq[54][51] = 561; - GBFreq[54][36] = 560; - GBFreq[39][4] = 559; - GBFreq[53][13] = 558; - GBFreq[24][92] = 557; - GBFreq[27][49] = 556; - GBFreq[48][6] = 555; - GBFreq[21][51] = 554; - GBFreq[30][40] = 553; - GBFreq[42][92] = 552; - GBFreq[31][78] = 551; - GBFreq[25][82] = 550; - GBFreq[47][0] = 549; - GBFreq[34][19] = 548; - GBFreq[47][35] = 547; - GBFreq[21][63] = 546; - GBFreq[43][75] = 545; - GBFreq[21][87] = 544; - GBFreq[35][59] = 543; - GBFreq[25][34] = 542; - GBFreq[21][27] = 541; - GBFreq[39][26] = 540; - GBFreq[34][26] = 539; - GBFreq[39][52] = 538; - GBFreq[50][57] = 537; - GBFreq[37][79] = 536; - GBFreq[26][24] = 535; - GBFreq[22][1] = 534; - GBFreq[18][40] = 533; - GBFreq[41][33] = 532; - GBFreq[53][26] = 531; - GBFreq[54][86] = 530; - GBFreq[20][16] = 529; - GBFreq[46][74] = 528; - GBFreq[30][19] = 527; - GBFreq[45][35] = 526; - GBFreq[45][61] = 525; - GBFreq[30][9] = 524; - GBFreq[41][53] = 523; - GBFreq[41][13] = 522; - GBFreq[50][34] = 521; - GBFreq[53][86] = 520; - GBFreq[47][47] = 519; - GBFreq[22][28] = 518; - GBFreq[50][53] = 517; - GBFreq[39][70] = 516; - GBFreq[38][15] = 515; - GBFreq[42][88] = 514; - GBFreq[16][29] = 513; - GBFreq[27][90] = 512; - GBFreq[29][12] = 511; - GBFreq[44][22] = 510; - GBFreq[34][69] = 509; - GBFreq[24][10] = 508; - GBFreq[44][11] = 507; - GBFreq[39][92] = 506; - GBFreq[49][48] = 505; - GBFreq[31][46] = 504; - GBFreq[19][50] = 503; - GBFreq[21][14] = 502; - GBFreq[32][28] = 501; - GBFreq[18][3] = 500; - GBFreq[53][9] = 499; - GBFreq[34][80] = 498; - GBFreq[48][88] = 497; - GBFreq[46][53] = 496; - GBFreq[22][53] = 495; - GBFreq[28][10] = 494; - GBFreq[44][65] = 493; - GBFreq[20][10] = 492; - GBFreq[40][76] = 491; - GBFreq[47][8] = 490; - GBFreq[50][74] = 489; - GBFreq[23][62] = 488; - GBFreq[49][65] = 487; - GBFreq[28][87] = 486; - GBFreq[15][48] = 485; - GBFreq[22][7] = 484; - GBFreq[19][42] = 483; - GBFreq[41][20] = 482; - GBFreq[26][55] = 481; - GBFreq[21][93] = 480; - GBFreq[31][76] = 479; - GBFreq[34][31] = 478; - GBFreq[20][66] = 477; - GBFreq[51][33] = 476; - GBFreq[34][86] = 475; - GBFreq[37][67] = 474; - GBFreq[53][53] = 473; - GBFreq[40][88] = 472; - GBFreq[39][10] = 471; - GBFreq[24][3] = 470; - GBFreq[27][25] = 469; - GBFreq[26][15] = 468; - GBFreq[21][88] = 467; - GBFreq[52][62] = 466; - GBFreq[46][81] = 465; - GBFreq[38][72] = 464; - GBFreq[17][30] = 463; - GBFreq[52][92] = 462; - GBFreq[34][90] = 461; - GBFreq[21][7] = 460; - GBFreq[36][13] = 459; - GBFreq[45][41] = 458; - GBFreq[32][5] = 457; - GBFreq[26][89] = 456; - GBFreq[23][87] = 455; - GBFreq[20][39] = 454; - GBFreq[27][23] = 453; - GBFreq[25][59] = 452; - GBFreq[49][20] = 451; - GBFreq[54][77] = 450; - GBFreq[27][67] = 449; - GBFreq[47][33] = 448; - GBFreq[41][17] = 447; - GBFreq[19][81] = 446; - GBFreq[16][66] = 445; - GBFreq[45][26] = 444; - GBFreq[49][81] = 443; - GBFreq[53][55] = 442; - GBFreq[16][26] = 441; - GBFreq[54][62] = 440; - GBFreq[20][70] = 439; - GBFreq[42][35] = 438; - GBFreq[20][57] = 437; - GBFreq[34][36] = 436; - GBFreq[46][63] = 435; - GBFreq[19][45] = 434; - GBFreq[21][10] = 433; - GBFreq[52][93] = 432; - GBFreq[25][2] = 431; - GBFreq[30][57] = 430; - GBFreq[41][24] = 429; - GBFreq[28][43] = 428; - GBFreq[45][86] = 427; - GBFreq[51][56] = 426; - GBFreq[37][28] = 425; - GBFreq[52][69] = 424; - GBFreq[43][92] = 423; - GBFreq[41][31] = 422; - GBFreq[37][87] = 421; - GBFreq[47][36] = 420; - GBFreq[16][16] = 419; - GBFreq[40][56] = 418; - GBFreq[24][55] = 417; - GBFreq[17][1] = 416; - GBFreq[35][57] = 415; - GBFreq[27][50] = 414; - GBFreq[26][14] = 413; - GBFreq[50][40] = 412; - GBFreq[39][19] = 411; - GBFreq[19][89] = 410; - GBFreq[29][91] = 409; - GBFreq[17][89] = 408; - GBFreq[39][74] = 407; - GBFreq[46][39] = 406; - GBFreq[40][28] = 405; - GBFreq[45][68] = 404; - GBFreq[43][10] = 403; - GBFreq[42][13] = 402; - GBFreq[44][81] = 401; - GBFreq[41][47] = 400; - GBFreq[48][58] = 399; - GBFreq[43][68] = 398; - GBFreq[16][79] = 397; - GBFreq[19][5] = 396; - GBFreq[54][59] = 395; - GBFreq[17][36] = 394; - GBFreq[18][0] = 393; - GBFreq[41][5] = 392; - GBFreq[41][72] = 391; - GBFreq[16][39] = 390; - GBFreq[54][0] = 389; - GBFreq[51][16] = 388; - GBFreq[29][36] = 387; - GBFreq[47][5] = 386; - GBFreq[47][51] = 385; - GBFreq[44][7] = 384; - GBFreq[35][30] = 383; - GBFreq[26][9] = 382; - GBFreq[16][7] = 381; - GBFreq[32][1] = 380; - GBFreq[33][76] = 379; - GBFreq[34][91] = 378; - GBFreq[52][36] = 377; - GBFreq[26][77] = 376; - GBFreq[35][48] = 375; - GBFreq[40][80] = 374; - GBFreq[41][92] = 373; - GBFreq[27][93] = 372; - GBFreq[15][17] = 371; - GBFreq[16][76] = 370; - GBFreq[51][12] = 369; - GBFreq[18][20] = 368; - GBFreq[15][54] = 367; - GBFreq[50][5] = 366; - GBFreq[33][22] = 365; - GBFreq[37][57] = 364; - GBFreq[28][47] = 363; - GBFreq[42][31] = 362; - GBFreq[18][2] = 361; - GBFreq[43][64] = 360; - GBFreq[23][47] = 359; - GBFreq[28][79] = 358; - GBFreq[25][45] = 357; - GBFreq[23][91] = 356; - GBFreq[22][19] = 355; - GBFreq[25][46] = 354; - GBFreq[22][36] = 353; - GBFreq[54][85] = 352; - GBFreq[46][20] = 351; - GBFreq[27][37] = 350; - GBFreq[26][81] = 349; - GBFreq[42][29] = 348; - GBFreq[31][90] = 347; - GBFreq[41][59] = 346; - GBFreq[24][65] = 345; - GBFreq[44][84] = 344; - GBFreq[24][90] = 343; - GBFreq[38][54] = 342; - GBFreq[28][70] = 341; - GBFreq[27][15] = 340; - GBFreq[28][80] = 339; - GBFreq[29][8] = 338; - GBFreq[45][80] = 337; - GBFreq[53][37] = 336; - GBFreq[28][65] = 335; - GBFreq[23][86] = 334; - GBFreq[39][45] = 333; - GBFreq[53][32] = 332; - GBFreq[38][68] = 331; - GBFreq[45][78] = 330; - GBFreq[43][7] = 329; - GBFreq[46][82] = 328; - GBFreq[27][38] = 327; - GBFreq[16][62] = 326; - GBFreq[24][17] = 325; - GBFreq[22][70] = 324; - GBFreq[52][28] = 323; - GBFreq[23][40] = 322; - GBFreq[28][50] = 321; - GBFreq[42][91] = 320; - GBFreq[47][76] = 319; - GBFreq[15][42] = 318; - GBFreq[43][55] = 317; - GBFreq[29][84] = 316; - GBFreq[44][90] = 315; - GBFreq[53][16] = 314; - GBFreq[22][93] = 313; - GBFreq[34][10] = 312; - GBFreq[32][53] = 311; - GBFreq[43][65] = 310; - GBFreq[28][7] = 309; - GBFreq[35][46] = 308; - GBFreq[21][39] = 307; - GBFreq[44][18] = 306; - GBFreq[40][10] = 305; - GBFreq[54][53] = 304; - GBFreq[38][74] = 303; - GBFreq[28][26] = 302; - GBFreq[15][13] = 301; - GBFreq[39][34] = 300; - GBFreq[39][46] = 299; - GBFreq[42][66] = 298; - GBFreq[33][58] = 297; - GBFreq[15][56] = 296; - GBFreq[18][51] = 295; - GBFreq[49][68] = 294; - GBFreq[30][37] = 293; - GBFreq[51][84] = 292; - GBFreq[51][9] = 291; - GBFreq[40][70] = 290; - GBFreq[41][84] = 289; - GBFreq[28][64] = 288; - GBFreq[32][88] = 287; - GBFreq[24][5] = 286; - GBFreq[53][23] = 285; - GBFreq[42][27] = 284; - GBFreq[22][38] = 283; - GBFreq[32][86] = 282; - GBFreq[34][30] = 281; - GBFreq[38][63] = 280; - GBFreq[24][59] = 279; - GBFreq[22][81] = 278; - GBFreq[32][11] = 277; - GBFreq[51][21] = 276; - GBFreq[54][41] = 275; - GBFreq[21][50] = 274; - GBFreq[23][89] = 273; - GBFreq[19][87] = 272; - GBFreq[26][7] = 271; - GBFreq[30][75] = 270; - GBFreq[43][84] = 269; - GBFreq[51][25] = 268; - GBFreq[16][67] = 267; - GBFreq[32][9] = 266; - GBFreq[48][51] = 265; - GBFreq[39][7] = 264; - GBFreq[44][88] = 263; - GBFreq[52][24] = 262; - GBFreq[23][34] = 261; - GBFreq[32][75] = 260; - GBFreq[19][10] = 259; - GBFreq[28][91] = 258; - GBFreq[32][83] = 257; - GBFreq[25][75] = 256; - GBFreq[53][45] = 255; - GBFreq[29][85] = 254; - GBFreq[53][59] = 253; - GBFreq[16][2] = 252; - GBFreq[19][78] = 251; - GBFreq[15][75] = 250; - GBFreq[51][42] = 249; - GBFreq[45][67] = 248; - GBFreq[15][74] = 247; - GBFreq[25][81] = 246; - GBFreq[37][62] = 245; - GBFreq[16][55] = 244; - GBFreq[18][38] = 243; - GBFreq[23][23] = 242; - GBFreq[38][30] = 241; - GBFreq[17][28] = 240; - GBFreq[44][73] = 239; - GBFreq[23][78] = 238; - GBFreq[40][77] = 237; - GBFreq[38][87] = 236; - GBFreq[27][19] = 235; - GBFreq[38][82] = 234; - GBFreq[37][22] = 233; - GBFreq[41][30] = 232; - GBFreq[54][9] = 231; - GBFreq[32][30] = 230; - GBFreq[30][52] = 229; - GBFreq[40][84] = 228; - GBFreq[53][57] = 227; - GBFreq[27][27] = 226; - GBFreq[38][64] = 225; - GBFreq[18][43] = 224; - GBFreq[23][69] = 223; - GBFreq[28][12] = 222; - GBFreq[50][78] = 221; - GBFreq[50][1] = 220; - GBFreq[26][88] = 219; - GBFreq[36][40] = 218; - GBFreq[33][89] = 217; - GBFreq[41][28] = 216; - GBFreq[31][77] = 215; - GBFreq[46][1] = 214; - GBFreq[47][19] = 213; - GBFreq[35][55] = 212; - GBFreq[41][21] = 211; - GBFreq[27][10] = 210; - GBFreq[32][77] = 209; - GBFreq[26][37] = 208; - GBFreq[20][33] = 207; - GBFreq[41][52] = 206; - GBFreq[32][18] = 205; - GBFreq[38][13] = 204; - GBFreq[20][18] = 203; - GBFreq[20][24] = 202; - GBFreq[45][19] = 201; - GBFreq[18][53] = 200; - /* - * GBFreq[39][0] = 199; GBFreq[40][71] = 198; GBFreq[41][27] = 197; - * GBFreq[15][69] = 196; GBFreq[42][10] = 195; GBFreq[31][89] = 194; - * GBFreq[51][28] = 193; GBFreq[41][22] = 192; GBFreq[40][43] = 191; - * GBFreq[38][6] = 190; GBFreq[37][11] = 189; GBFreq[39][60] = 188; - * GBFreq[48][47] = 187; GBFreq[46][80] = 186; GBFreq[52][49] = 185; - * GBFreq[50][48] = 184; GBFreq[25][1] = 183; GBFreq[52][29] = 182; - * GBFreq[24][66] = 181; GBFreq[23][35] = 180; GBFreq[49][72] = 179; - * GBFreq[47][45] = 178; GBFreq[45][14] = 177; GBFreq[51][70] = 176; - * GBFreq[22][30] = 175; GBFreq[49][83] = 174; GBFreq[26][79] = 173; - * GBFreq[27][41] = 172; GBFreq[51][81] = 171; GBFreq[41][54] = 170; - * GBFreq[20][4] = 169; GBFreq[29][60] = 168; GBFreq[20][27] = 167; - * GBFreq[50][15] = 166; GBFreq[41][6] = 165; GBFreq[35][34] = 164; - * GBFreq[44][87] = 163; GBFreq[46][66] = 162; GBFreq[42][37] = 161; - * GBFreq[42][24] = 160; GBFreq[54][7] = 159; GBFreq[41][14] = 158; - * GBFreq[39][83] = 157; GBFreq[16][87] = 156; GBFreq[20][59] = 155; - * GBFreq[42][12] = 154; GBFreq[47][2] = 153; GBFreq[21][32] = 152; - * GBFreq[53][29] = 151; GBFreq[22][40] = 150; GBFreq[24][58] = 149; - * GBFreq[52][88] = 148; GBFreq[29][30] = 147; GBFreq[15][91] = 146; - * GBFreq[54][72] = 145; GBFreq[51][75] = 144; GBFreq[33][67] = 143; - * GBFreq[41][50] = 142; GBFreq[27][34] = 141; GBFreq[46][17] = 140; - * GBFreq[31][74] = 139; GBFreq[42][67] = 138; GBFreq[54][87] = 137; - * GBFreq[27][14] = 136; GBFreq[16][63] = 135; GBFreq[16][5] = 134; - * GBFreq[43][23] = 133; GBFreq[23][13] = 132; GBFreq[31][12] = 131; - * GBFreq[25][57] = 130; GBFreq[38][49] = 129; GBFreq[42][69] = 128; - * GBFreq[23][80] = 127; GBFreq[29][0] = 126; GBFreq[28][2] = 125; - * GBFreq[28][17] = 124; GBFreq[17][27] = 123; GBFreq[40][16] = 122; - * GBFreq[45][1] = 121; GBFreq[36][33] = 120; GBFreq[35][23] = 119; - * GBFreq[20][86] = 118; GBFreq[29][53] = 117; GBFreq[23][88] = 116; - * GBFreq[51][87] = 115; GBFreq[54][27] = 114; GBFreq[44][36] = 113; - * GBFreq[21][45] = 112; GBFreq[53][52] = 111; GBFreq[31][53] = 110; - * GBFreq[38][47] = 109; GBFreq[27][21] = 108; GBFreq[30][42] = 107; - * GBFreq[29][10] = 106; GBFreq[35][35] = 105; GBFreq[24][56] = 104; - * GBFreq[41][29] = 103; GBFreq[18][68] = 102; GBFreq[29][24] = 101; - * GBFreq[25][84] = 100; GBFreq[35][47] = 99; GBFreq[29][56] = 98; - * GBFreq[30][44] = 97; GBFreq[53][3] = 96; GBFreq[30][63] = 95; - * GBFreq[52][52] = 94; GBFreq[54][1] = 93; GBFreq[22][48] = 92; - * GBFreq[54][66] = 91; GBFreq[21][90] = 90; GBFreq[52][47] = 89; - * GBFreq[39][25] = 88; GBFreq[39][39] = 87; GBFreq[44][37] = 86; - * GBFreq[44][76] = 85; GBFreq[46][75] = 84; GBFreq[18][37] = 83; - * GBFreq[47][42] = 82; GBFreq[19][92] = 81; GBFreq[51][27] = 80; - * GBFreq[48][83] = 79; GBFreq[23][70] = 78; GBFreq[29][9] = 77; - * GBFreq[33][79] = 76; GBFreq[52][90] = 75; GBFreq[53][6] = 74; - * GBFreq[24][36] = 73; GBFreq[25][25] = 72; GBFreq[44][26] = 71; - * GBFreq[25][36] = 70; GBFreq[29][87] = 69; GBFreq[48][0] = 68; - * GBFreq[15][40] = 67; GBFreq[17][45] = 66; GBFreq[30][14] = 65; - * GBFreq[48][38] = 64; GBFreq[23][19] = 63; GBFreq[40][42] = 62; - * GBFreq[31][63] = 61; GBFreq[16][23] = 60; GBFreq[26][21] = 59; - * GBFreq[32][76] = 58; GBFreq[23][58] = 57; GBFreq[41][37] = 56; - * GBFreq[30][43] = 55; GBFreq[47][38] = 54; GBFreq[21][46] = 53; - * GBFreq[18][33] = 52; GBFreq[52][37] = 51; GBFreq[36][8] = 50; - * GBFreq[49][24] = 49; GBFreq[15][66] = 48; GBFreq[35][77] = 47; - * GBFreq[27][58] = 46; GBFreq[35][51] = 45; GBFreq[24][69] = 44; - * GBFreq[20][54] = 43; GBFreq[24][41] = 42; GBFreq[41][0] = 41; - * GBFreq[33][71] = 40; GBFreq[23][52] = 39; GBFreq[29][67] = 38; - * GBFreq[46][51] = 37; GBFreq[46][90] = 36; GBFreq[49][33] = 35; - * GBFreq[33][28] = 34; GBFreq[37][86] = 33; GBFreq[39][22] = 32; - * GBFreq[37][37] = 31; GBFreq[29][62] = 30; GBFreq[29][50] = 29; - * GBFreq[36][89] = 28; GBFreq[42][44] = 27; GBFreq[51][82] = 26; - * GBFreq[28][83] = 25; GBFreq[15][78] = 24; GBFreq[46][62] = 23; - * GBFreq[19][69] = 22; GBFreq[51][23] = 21; GBFreq[37][69] = 20; - * GBFreq[25][5] = 19; GBFreq[51][85] = 18; GBFreq[48][77] = 17; - * GBFreq[32][46] = 16; GBFreq[53][60] = 15; GBFreq[28][57] = 14; - * GBFreq[54][82] = 13; GBFreq[54][15] = 12; GBFreq[49][54] = 11; - * GBFreq[53][87] = 10; GBFreq[27][16] = 9; GBFreq[29][34] = 8; - * GBFreq[20][44] = 7; GBFreq[42][73] = 6; GBFreq[47][71] = 5; - * GBFreq[29][37] = 4; GBFreq[25][50] = 3; GBFreq[18][84] = 2; - * GBFreq[50][45] = 1; GBFreq[48][46] = 0; - */ - // GBFreq[43][89] = -1; GBFreq[54][68] = -2; - Big5Freq[9][89] = 600; - Big5Freq[11][15] = 599; - Big5Freq[3][66] = 598; - Big5Freq[6][121] = 597; - Big5Freq[3][0] = 596; - Big5Freq[5][82] = 595; - Big5Freq[3][42] = 594; - Big5Freq[5][34] = 593; - Big5Freq[3][8] = 592; - Big5Freq[3][6] = 591; - Big5Freq[3][67] = 590; - Big5Freq[7][139] = 589; - Big5Freq[23][137] = 588; - Big5Freq[12][46] = 587; - Big5Freq[4][8] = 586; - Big5Freq[4][41] = 585; - Big5Freq[18][47] = 584; - Big5Freq[12][114] = 583; - Big5Freq[6][1] = 582; - Big5Freq[22][60] = 581; - Big5Freq[5][46] = 580; - Big5Freq[11][79] = 579; - Big5Freq[3][23] = 578; - Big5Freq[7][114] = 577; - Big5Freq[29][102] = 576; - Big5Freq[19][14] = 575; - Big5Freq[4][133] = 574; - Big5Freq[3][29] = 573; - Big5Freq[4][109] = 572; - Big5Freq[14][127] = 571; - Big5Freq[5][48] = 570; - Big5Freq[13][104] = 569; - Big5Freq[3][132] = 568; - Big5Freq[26][64] = 567; - Big5Freq[7][19] = 566; - Big5Freq[4][12] = 565; - Big5Freq[11][124] = 564; - Big5Freq[7][89] = 563; - Big5Freq[15][124] = 562; - Big5Freq[4][108] = 561; - Big5Freq[19][66] = 560; - Big5Freq[3][21] = 559; - Big5Freq[24][12] = 558; - Big5Freq[28][111] = 557; - Big5Freq[12][107] = 556; - Big5Freq[3][112] = 555; - Big5Freq[8][113] = 554; - Big5Freq[5][40] = 553; - Big5Freq[26][145] = 552; - Big5Freq[3][48] = 551; - Big5Freq[3][70] = 550; - Big5Freq[22][17] = 549; - Big5Freq[16][47] = 548; - Big5Freq[3][53] = 547; - Big5Freq[4][24] = 546; - Big5Freq[32][120] = 545; - Big5Freq[24][49] = 544; - Big5Freq[24][142] = 543; - Big5Freq[18][66] = 542; - Big5Freq[29][150] = 541; - Big5Freq[5][122] = 540; - Big5Freq[5][114] = 539; - Big5Freq[3][44] = 538; - Big5Freq[10][128] = 537; - Big5Freq[15][20] = 536; - Big5Freq[13][33] = 535; - Big5Freq[14][87] = 534; - Big5Freq[3][126] = 533; - Big5Freq[4][53] = 532; - Big5Freq[4][40] = 531; - Big5Freq[9][93] = 530; - Big5Freq[15][137] = 529; - Big5Freq[10][123] = 528; - Big5Freq[4][56] = 527; - Big5Freq[5][71] = 526; - Big5Freq[10][8] = 525; - Big5Freq[5][16] = 524; - Big5Freq[5][146] = 523; - Big5Freq[18][88] = 522; - Big5Freq[24][4] = 521; - Big5Freq[20][47] = 520; - Big5Freq[5][33] = 519; - Big5Freq[9][43] = 518; - Big5Freq[20][12] = 517; - Big5Freq[20][13] = 516; - Big5Freq[5][156] = 515; - Big5Freq[22][140] = 514; - Big5Freq[8][146] = 513; - Big5Freq[21][123] = 512; - Big5Freq[4][90] = 511; - Big5Freq[5][62] = 510; - Big5Freq[17][59] = 509; - Big5Freq[10][37] = 508; - Big5Freq[18][107] = 507; - Big5Freq[14][53] = 506; - Big5Freq[22][51] = 505; - Big5Freq[8][13] = 504; - Big5Freq[5][29] = 503; - Big5Freq[9][7] = 502; - Big5Freq[22][14] = 501; - Big5Freq[8][55] = 500; - Big5Freq[33][9] = 499; - Big5Freq[16][64] = 498; - Big5Freq[7][131] = 497; - Big5Freq[34][4] = 496; - Big5Freq[7][101] = 495; - Big5Freq[11][139] = 494; - Big5Freq[3][135] = 493; - Big5Freq[7][102] = 492; - Big5Freq[17][13] = 491; - Big5Freq[3][20] = 490; - Big5Freq[27][106] = 489; - Big5Freq[5][88] = 488; - Big5Freq[6][33] = 487; - Big5Freq[5][139] = 486; - Big5Freq[6][0] = 485; - Big5Freq[17][58] = 484; - Big5Freq[5][133] = 483; - Big5Freq[9][107] = 482; - Big5Freq[23][39] = 481; - Big5Freq[5][23] = 480; - Big5Freq[3][79] = 479; - Big5Freq[32][97] = 478; - Big5Freq[3][136] = 477; - Big5Freq[4][94] = 476; - Big5Freq[21][61] = 475; - Big5Freq[23][123] = 474; - Big5Freq[26][16] = 473; - Big5Freq[24][137] = 472; - Big5Freq[22][18] = 471; - Big5Freq[5][1] = 470; - Big5Freq[20][119] = 469; - Big5Freq[3][7] = 468; - Big5Freq[10][79] = 467; - Big5Freq[15][105] = 466; - Big5Freq[3][144] = 465; - Big5Freq[12][80] = 464; - Big5Freq[15][73] = 463; - Big5Freq[3][19] = 462; - Big5Freq[8][109] = 461; - Big5Freq[3][15] = 460; - Big5Freq[31][82] = 459; - Big5Freq[3][43] = 458; - Big5Freq[25][119] = 457; - Big5Freq[16][111] = 456; - Big5Freq[7][77] = 455; - Big5Freq[3][95] = 454; - Big5Freq[24][82] = 453; - Big5Freq[7][52] = 452; - Big5Freq[9][151] = 451; - Big5Freq[3][129] = 450; - Big5Freq[5][87] = 449; - Big5Freq[3][55] = 448; - Big5Freq[8][153] = 447; - Big5Freq[4][83] = 446; - Big5Freq[3][114] = 445; - Big5Freq[23][147] = 444; - Big5Freq[15][31] = 443; - Big5Freq[3][54] = 442; - Big5Freq[11][122] = 441; - Big5Freq[4][4] = 440; - Big5Freq[34][149] = 439; - Big5Freq[3][17] = 438; - Big5Freq[21][64] = 437; - Big5Freq[26][144] = 436; - Big5Freq[4][62] = 435; - Big5Freq[8][15] = 434; - Big5Freq[35][80] = 433; - Big5Freq[7][110] = 432; - Big5Freq[23][114] = 431; - Big5Freq[3][108] = 430; - Big5Freq[3][62] = 429; - Big5Freq[21][41] = 428; - Big5Freq[15][99] = 427; - Big5Freq[5][47] = 426; - Big5Freq[4][96] = 425; - Big5Freq[20][122] = 424; - Big5Freq[5][21] = 423; - Big5Freq[4][157] = 422; - Big5Freq[16][14] = 421; - Big5Freq[3][117] = 420; - Big5Freq[7][129] = 419; - Big5Freq[4][27] = 418; - Big5Freq[5][30] = 417; - Big5Freq[22][16] = 416; - Big5Freq[5][64] = 415; - Big5Freq[17][99] = 414; - Big5Freq[17][57] = 413; - Big5Freq[8][105] = 412; - Big5Freq[5][112] = 411; - Big5Freq[20][59] = 410; - Big5Freq[6][129] = 409; - Big5Freq[18][17] = 408; - Big5Freq[3][92] = 407; - Big5Freq[28][118] = 406; - Big5Freq[3][109] = 405; - Big5Freq[31][51] = 404; - Big5Freq[13][116] = 403; - Big5Freq[6][15] = 402; - Big5Freq[36][136] = 401; - Big5Freq[12][74] = 400; - Big5Freq[20][88] = 399; - Big5Freq[36][68] = 398; - Big5Freq[3][147] = 397; - Big5Freq[15][84] = 396; - Big5Freq[16][32] = 395; - Big5Freq[16][58] = 394; - Big5Freq[7][66] = 393; - Big5Freq[23][107] = 392; - Big5Freq[9][6] = 391; - Big5Freq[12][86] = 390; - Big5Freq[23][112] = 389; - Big5Freq[37][23] = 388; - Big5Freq[3][138] = 387; - Big5Freq[20][68] = 386; - Big5Freq[15][116] = 385; - Big5Freq[18][64] = 384; - Big5Freq[12][139] = 383; - Big5Freq[11][155] = 382; - Big5Freq[4][156] = 381; - Big5Freq[12][84] = 380; - Big5Freq[18][49] = 379; - Big5Freq[25][125] = 378; - Big5Freq[25][147] = 377; - Big5Freq[15][110] = 376; - Big5Freq[19][96] = 375; - Big5Freq[30][152] = 374; - Big5Freq[6][31] = 373; - Big5Freq[27][117] = 372; - Big5Freq[3][10] = 371; - Big5Freq[6][131] = 370; - Big5Freq[13][112] = 369; - Big5Freq[36][156] = 368; - Big5Freq[4][60] = 367; - Big5Freq[15][121] = 366; - Big5Freq[4][112] = 365; - Big5Freq[30][142] = 364; - Big5Freq[23][154] = 363; - Big5Freq[27][101] = 362; - Big5Freq[9][140] = 361; - Big5Freq[3][89] = 360; - Big5Freq[18][148] = 359; - Big5Freq[4][69] = 358; - Big5Freq[16][49] = 357; - Big5Freq[6][117] = 356; - Big5Freq[36][55] = 355; - Big5Freq[5][123] = 354; - Big5Freq[4][126] = 353; - Big5Freq[4][119] = 352; - Big5Freq[9][95] = 351; - Big5Freq[5][24] = 350; - Big5Freq[16][133] = 349; - Big5Freq[10][134] = 348; - Big5Freq[26][59] = 347; - Big5Freq[6][41] = 346; - Big5Freq[6][146] = 345; - Big5Freq[19][24] = 344; - Big5Freq[5][113] = 343; - Big5Freq[10][118] = 342; - Big5Freq[34][151] = 341; - Big5Freq[9][72] = 340; - Big5Freq[31][25] = 339; - Big5Freq[18][126] = 338; - Big5Freq[18][28] = 337; - Big5Freq[4][153] = 336; - Big5Freq[3][84] = 335; - Big5Freq[21][18] = 334; - Big5Freq[25][129] = 333; - Big5Freq[6][107] = 332; - Big5Freq[12][25] = 331; - Big5Freq[17][109] = 330; - Big5Freq[7][76] = 329; - Big5Freq[15][15] = 328; - Big5Freq[4][14] = 327; - Big5Freq[23][88] = 326; - Big5Freq[18][2] = 325; - Big5Freq[6][88] = 324; - Big5Freq[16][84] = 323; - Big5Freq[12][48] = 322; - Big5Freq[7][68] = 321; - Big5Freq[5][50] = 320; - Big5Freq[13][54] = 319; - Big5Freq[7][98] = 318; - Big5Freq[11][6] = 317; - Big5Freq[9][80] = 316; - Big5Freq[16][41] = 315; - Big5Freq[7][43] = 314; - Big5Freq[28][117] = 313; - Big5Freq[3][51] = 312; - Big5Freq[7][3] = 311; - Big5Freq[20][81] = 310; - Big5Freq[4][2] = 309; - Big5Freq[11][16] = 308; - Big5Freq[10][4] = 307; - Big5Freq[10][119] = 306; - Big5Freq[6][142] = 305; - Big5Freq[18][51] = 304; - Big5Freq[8][144] = 303; - Big5Freq[10][65] = 302; - Big5Freq[11][64] = 301; - Big5Freq[11][130] = 300; - Big5Freq[9][92] = 299; - Big5Freq[18][29] = 298; - Big5Freq[18][78] = 297; - Big5Freq[18][151] = 296; - Big5Freq[33][127] = 295; - Big5Freq[35][113] = 294; - Big5Freq[10][155] = 293; - Big5Freq[3][76] = 292; - Big5Freq[36][123] = 291; - Big5Freq[13][143] = 290; - Big5Freq[5][135] = 289; - Big5Freq[23][116] = 288; - Big5Freq[6][101] = 287; - Big5Freq[14][74] = 286; - Big5Freq[7][153] = 285; - Big5Freq[3][101] = 284; - Big5Freq[9][74] = 283; - Big5Freq[3][156] = 282; - Big5Freq[4][147] = 281; - Big5Freq[9][12] = 280; - Big5Freq[18][133] = 279; - Big5Freq[4][0] = 278; - Big5Freq[7][155] = 277; - Big5Freq[9][144] = 276; - Big5Freq[23][49] = 275; - Big5Freq[5][89] = 274; - Big5Freq[10][11] = 273; - Big5Freq[3][110] = 272; - Big5Freq[3][40] = 271; - Big5Freq[29][115] = 270; - Big5Freq[9][100] = 269; - Big5Freq[21][67] = 268; - Big5Freq[23][145] = 267; - Big5Freq[10][47] = 266; - Big5Freq[4][31] = 265; - Big5Freq[4][81] = 264; - Big5Freq[22][62] = 263; - Big5Freq[4][28] = 262; - Big5Freq[27][39] = 261; - Big5Freq[27][54] = 260; - Big5Freq[32][46] = 259; - Big5Freq[4][76] = 258; - Big5Freq[26][15] = 257; - Big5Freq[12][154] = 256; - Big5Freq[9][150] = 255; - Big5Freq[15][17] = 254; - Big5Freq[5][129] = 253; - Big5Freq[10][40] = 252; - Big5Freq[13][37] = 251; - Big5Freq[31][104] = 250; - Big5Freq[3][152] = 249; - Big5Freq[5][22] = 248; - Big5Freq[8][48] = 247; - Big5Freq[4][74] = 246; - Big5Freq[6][17] = 245; - Big5Freq[30][82] = 244; - Big5Freq[4][116] = 243; - Big5Freq[16][42] = 242; - Big5Freq[5][55] = 241; - Big5Freq[4][64] = 240; - Big5Freq[14][19] = 239; - Big5Freq[35][82] = 238; - Big5Freq[30][139] = 237; - Big5Freq[26][152] = 236; - Big5Freq[32][32] = 235; - Big5Freq[21][102] = 234; - Big5Freq[10][131] = 233; - Big5Freq[9][128] = 232; - Big5Freq[3][87] = 231; - Big5Freq[4][51] = 230; - Big5Freq[10][15] = 229; - Big5Freq[4][150] = 228; - Big5Freq[7][4] = 227; - Big5Freq[7][51] = 226; - Big5Freq[7][157] = 225; - Big5Freq[4][146] = 224; - Big5Freq[4][91] = 223; - Big5Freq[7][13] = 222; - Big5Freq[17][116] = 221; - Big5Freq[23][21] = 220; - Big5Freq[5][106] = 219; - Big5Freq[14][100] = 218; - Big5Freq[10][152] = 217; - Big5Freq[14][89] = 216; - Big5Freq[6][138] = 215; - Big5Freq[12][157] = 214; - Big5Freq[10][102] = 213; - Big5Freq[19][94] = 212; - Big5Freq[7][74] = 211; - Big5Freq[18][128] = 210; - Big5Freq[27][111] = 209; - Big5Freq[11][57] = 208; - Big5Freq[3][131] = 207; - Big5Freq[30][23] = 206; - Big5Freq[30][126] = 205; - Big5Freq[4][36] = 204; - Big5Freq[26][124] = 203; - Big5Freq[4][19] = 202; - Big5Freq[9][152] = 201; - /* - * Big5Freq[5][0] = 200; Big5Freq[26][57] = 199; Big5Freq[13][155] = - * 198; Big5Freq[3][38] = 197; Big5Freq[9][155] = 196; Big5Freq[28][53] - * = 195; Big5Freq[15][71] = 194; Big5Freq[21][95] = 193; - * Big5Freq[15][112] = 192; Big5Freq[14][138] = 191; Big5Freq[8][18] = - * 190; Big5Freq[20][151] = 189; Big5Freq[37][27] = 188; - * Big5Freq[32][48] = 187; Big5Freq[23][66] = 186; Big5Freq[9][2] = 185; - * Big5Freq[13][133] = 184; Big5Freq[7][127] = 183; Big5Freq[3][11] = - * 182; Big5Freq[12][118] = 181; Big5Freq[13][101] = 180; - * Big5Freq[30][153] = 179; Big5Freq[4][65] = 178; Big5Freq[5][25] = - * 177; Big5Freq[5][140] = 176; Big5Freq[6][25] = 175; Big5Freq[4][52] = - * 174; Big5Freq[30][156] = 173; Big5Freq[16][13] = 172; Big5Freq[21][8] - * = 171; Big5Freq[19][74] = 170; Big5Freq[15][145] = 169; - * Big5Freq[9][15] = 168; Big5Freq[13][82] = 167; Big5Freq[26][86] = - * 166; Big5Freq[18][52] = 165; Big5Freq[6][109] = 164; Big5Freq[10][99] - * = 163; Big5Freq[18][101] = 162; Big5Freq[25][49] = 161; - * Big5Freq[31][79] = 160; Big5Freq[28][20] = 159; Big5Freq[12][115] = - * 158; Big5Freq[15][66] = 157; Big5Freq[11][104] = 156; - * Big5Freq[23][106] = 155; Big5Freq[34][157] = 154; Big5Freq[32][94] = - * 153; Big5Freq[29][88] = 152; Big5Freq[10][46] = 151; - * Big5Freq[13][118] = 150; Big5Freq[20][37] = 149; Big5Freq[12][30] = - * 148; Big5Freq[21][4] = 147; Big5Freq[16][33] = 146; Big5Freq[13][52] - * = 145; Big5Freq[4][7] = 144; Big5Freq[21][49] = 143; Big5Freq[3][27] - * = 142; Big5Freq[16][91] = 141; Big5Freq[5][155] = 140; - * Big5Freq[29][130] = 139; Big5Freq[3][125] = 138; Big5Freq[14][26] = - * 137; Big5Freq[15][39] = 136; Big5Freq[24][110] = 135; - * Big5Freq[7][141] = 134; Big5Freq[21][15] = 133; Big5Freq[32][104] = - * 132; Big5Freq[8][31] = 131; Big5Freq[34][112] = 130; Big5Freq[10][75] - * = 129; Big5Freq[21][23] = 128; Big5Freq[34][131] = 127; - * Big5Freq[12][3] = 126; Big5Freq[10][62] = 125; Big5Freq[9][120] = - * 124; Big5Freq[32][149] = 123; Big5Freq[8][44] = 122; Big5Freq[24][2] - * = 121; Big5Freq[6][148] = 120; Big5Freq[15][103] = 119; - * Big5Freq[36][54] = 118; Big5Freq[36][134] = 117; Big5Freq[11][7] = - * 116; Big5Freq[3][90] = 115; Big5Freq[36][73] = 114; Big5Freq[8][102] - * = 113; Big5Freq[12][87] = 112; Big5Freq[25][64] = 111; Big5Freq[9][1] - * = 110; Big5Freq[24][121] = 109; Big5Freq[5][75] = 108; - * Big5Freq[17][83] = 107; Big5Freq[18][57] = 106; Big5Freq[8][95] = - * 105; Big5Freq[14][36] = 104; Big5Freq[28][113] = 103; - * Big5Freq[12][56] = 102; Big5Freq[14][61] = 101; Big5Freq[25][138] = - * 100; Big5Freq[4][34] = 99; Big5Freq[11][152] = 98; Big5Freq[35][0] = - * 97; Big5Freq[4][15] = 96; Big5Freq[8][82] = 95; Big5Freq[20][73] = - * 94; Big5Freq[25][52] = 93; Big5Freq[24][6] = 92; Big5Freq[21][78] = - * 91; Big5Freq[17][32] = 90; Big5Freq[17][91] = 89; Big5Freq[5][76] = - * 88; Big5Freq[15][60] = 87; Big5Freq[15][150] = 86; Big5Freq[5][80] = - * 85; Big5Freq[15][81] = 84; Big5Freq[28][108] = 83; Big5Freq[18][14] = - * 82; Big5Freq[19][109] = 81; Big5Freq[28][133] = 80; Big5Freq[21][97] - * = 79; Big5Freq[5][105] = 78; Big5Freq[18][114] = 77; Big5Freq[16][95] - * = 76; Big5Freq[5][51] = 75; Big5Freq[3][148] = 74; Big5Freq[22][102] - * = 73; Big5Freq[4][123] = 72; Big5Freq[8][88] = 71; Big5Freq[25][111] - * = 70; Big5Freq[8][149] = 69; Big5Freq[9][48] = 68; Big5Freq[16][126] - * = 67; Big5Freq[33][150] = 66; Big5Freq[9][54] = 65; Big5Freq[29][104] - * = 64; Big5Freq[3][3] = 63; Big5Freq[11][49] = 62; Big5Freq[24][109] = - * 61; Big5Freq[28][116] = 60; Big5Freq[34][113] = 59; Big5Freq[5][3] = - * 58; Big5Freq[21][106] = 57; Big5Freq[4][98] = 56; Big5Freq[12][135] = - * 55; Big5Freq[16][101] = 54; Big5Freq[12][147] = 53; Big5Freq[27][55] - * = 52; Big5Freq[3][5] = 51; Big5Freq[11][101] = 50; Big5Freq[16][157] - * = 49; Big5Freq[22][114] = 48; Big5Freq[18][46] = 47; Big5Freq[4][29] - * = 46; Big5Freq[8][103] = 45; Big5Freq[16][151] = 44; Big5Freq[8][29] - * = 43; Big5Freq[15][114] = 42; Big5Freq[22][70] = 41; - * Big5Freq[13][121] = 40; Big5Freq[7][112] = 39; Big5Freq[20][83] = 38; - * Big5Freq[3][36] = 37; Big5Freq[10][103] = 36; Big5Freq[3][96] = 35; - * Big5Freq[21][79] = 34; Big5Freq[25][120] = 33; Big5Freq[29][121] = - * 32; Big5Freq[23][71] = 31; Big5Freq[21][22] = 30; Big5Freq[18][89] = - * 29; Big5Freq[25][104] = 28; Big5Freq[10][124] = 27; Big5Freq[26][4] = - * 26; Big5Freq[21][136] = 25; Big5Freq[6][112] = 24; Big5Freq[12][103] - * = 23; Big5Freq[17][66] = 22; Big5Freq[13][151] = 21; - * Big5Freq[33][152] = 20; Big5Freq[11][148] = 19; Big5Freq[13][57] = - * 18; Big5Freq[13][41] = 17; Big5Freq[7][60] = 16; Big5Freq[21][29] = - * 15; Big5Freq[9][157] = 14; Big5Freq[24][95] = 13; Big5Freq[15][148] = - * 12; Big5Freq[15][122] = 11; Big5Freq[6][125] = 10; Big5Freq[11][25] = - * 9; Big5Freq[20][55] = 8; Big5Freq[19][84] = 7; Big5Freq[21][82] = 6; - * Big5Freq[24][3] = 5; Big5Freq[13][70] = 4; Big5Freq[6][21] = 3; - * Big5Freq[21][86] = 2; Big5Freq[12][23] = 1; Big5Freq[3][85] = 0; - * EUC_TWFreq[45][90] = 600; - */ - Big5PFreq[41][122] = 600; - Big5PFreq[35][0] = 599; - Big5PFreq[43][15] = 598; - Big5PFreq[35][99] = 597; - Big5PFreq[35][6] = 596; - Big5PFreq[35][8] = 595; - Big5PFreq[38][154] = 594; - Big5PFreq[37][34] = 593; - Big5PFreq[37][115] = 592; - Big5PFreq[36][12] = 591; - Big5PFreq[18][77] = 590; - Big5PFreq[35][100] = 589; - Big5PFreq[35][42] = 588; - Big5PFreq[120][75] = 587; - Big5PFreq[35][23] = 586; - Big5PFreq[13][72] = 585; - Big5PFreq[0][67] = 584; - Big5PFreq[39][172] = 583; - Big5PFreq[22][182] = 582; - Big5PFreq[15][186] = 581; - Big5PFreq[15][165] = 580; - Big5PFreq[35][44] = 579; - Big5PFreq[40][13] = 578; - Big5PFreq[38][1] = 577; - Big5PFreq[37][33] = 576; - Big5PFreq[36][24] = 575; - Big5PFreq[56][4] = 574; - Big5PFreq[35][29] = 573; - Big5PFreq[9][96] = 572; - Big5PFreq[37][62] = 571; - Big5PFreq[48][47] = 570; - Big5PFreq[51][14] = 569; - Big5PFreq[39][122] = 568; - Big5PFreq[44][46] = 567; - Big5PFreq[35][21] = 566; - Big5PFreq[36][8] = 565; - Big5PFreq[36][141] = 564; - Big5PFreq[3][81] = 563; - Big5PFreq[37][155] = 562; - Big5PFreq[42][84] = 561; - Big5PFreq[36][40] = 560; - Big5PFreq[35][103] = 559; - Big5PFreq[11][84] = 558; - Big5PFreq[45][33] = 557; - Big5PFreq[121][79] = 556; - Big5PFreq[2][77] = 555; - Big5PFreq[36][41] = 554; - Big5PFreq[37][47] = 553; - Big5PFreq[39][125] = 552; - Big5PFreq[37][26] = 551; - Big5PFreq[35][48] = 550; - Big5PFreq[35][28] = 549; - Big5PFreq[35][159] = 548; - Big5PFreq[37][40] = 547; - Big5PFreq[35][145] = 546; - Big5PFreq[37][147] = 545; - Big5PFreq[46][160] = 544; - Big5PFreq[37][46] = 543; - Big5PFreq[50][99] = 542; - Big5PFreq[52][13] = 541; - Big5PFreq[10][82] = 540; - Big5PFreq[35][169] = 539; - Big5PFreq[35][31] = 538; - Big5PFreq[47][31] = 537; - Big5PFreq[18][79] = 536; - Big5PFreq[16][113] = 535; - Big5PFreq[37][104] = 534; - Big5PFreq[39][134] = 533; - Big5PFreq[36][53] = 532; - Big5PFreq[38][0] = 531; - Big5PFreq[4][86] = 530; - Big5PFreq[54][17] = 529; - Big5PFreq[43][157] = 528; - Big5PFreq[35][165] = 527; - Big5PFreq[69][147] = 526; - Big5PFreq[117][95] = 525; - Big5PFreq[35][162] = 524; - Big5PFreq[35][17] = 523; - Big5PFreq[36][142] = 522; - Big5PFreq[36][4] = 521; - Big5PFreq[37][166] = 520; - Big5PFreq[35][168] = 519; - Big5PFreq[35][19] = 518; - Big5PFreq[37][48] = 517; - Big5PFreq[42][37] = 516; - Big5PFreq[40][146] = 515; - Big5PFreq[36][123] = 514; - Big5PFreq[22][41] = 513; - Big5PFreq[20][119] = 512; - Big5PFreq[2][74] = 511; - Big5PFreq[44][113] = 510; - Big5PFreq[35][125] = 509; - Big5PFreq[37][16] = 508; - Big5PFreq[35][20] = 507; - Big5PFreq[35][55] = 506; - Big5PFreq[37][145] = 505; - Big5PFreq[0][88] = 504; - Big5PFreq[3][94] = 503; - Big5PFreq[6][65] = 502; - Big5PFreq[26][15] = 501; - Big5PFreq[41][126] = 500; - Big5PFreq[36][129] = 499; - Big5PFreq[31][75] = 498; - Big5PFreq[19][61] = 497; - Big5PFreq[35][128] = 496; - Big5PFreq[29][79] = 495; - Big5PFreq[36][62] = 494; - Big5PFreq[37][189] = 493; - Big5PFreq[39][109] = 492; - Big5PFreq[39][135] = 491; - Big5PFreq[72][15] = 490; - Big5PFreq[47][106] = 489; - Big5PFreq[54][14] = 488; - Big5PFreq[24][52] = 487; - Big5PFreq[38][162] = 486; - Big5PFreq[41][43] = 485; - Big5PFreq[37][121] = 484; - Big5PFreq[14][66] = 483; - Big5PFreq[37][30] = 482; - Big5PFreq[35][7] = 481; - Big5PFreq[49][58] = 480; - Big5PFreq[43][188] = 479; - Big5PFreq[24][66] = 478; - Big5PFreq[35][171] = 477; - Big5PFreq[40][186] = 476; - Big5PFreq[39][164] = 475; - Big5PFreq[78][186] = 474; - Big5PFreq[8][72] = 473; - Big5PFreq[36][190] = 472; - Big5PFreq[35][53] = 471; - Big5PFreq[35][54] = 470; - Big5PFreq[22][159] = 469; - Big5PFreq[35][9] = 468; - Big5PFreq[41][140] = 467; - Big5PFreq[37][22] = 466; - Big5PFreq[48][97] = 465; - Big5PFreq[50][97] = 464; - Big5PFreq[36][127] = 463; - Big5PFreq[37][23] = 462; - Big5PFreq[40][55] = 461; - Big5PFreq[35][43] = 460; - Big5PFreq[26][22] = 459; - Big5PFreq[35][15] = 458; - Big5PFreq[72][179] = 457; - Big5PFreq[20][129] = 456; - Big5PFreq[52][101] = 455; - Big5PFreq[35][12] = 454; - Big5PFreq[42][156] = 453; - Big5PFreq[15][157] = 452; - Big5PFreq[50][140] = 451; - Big5PFreq[26][28] = 450; - Big5PFreq[54][51] = 449; - Big5PFreq[35][112] = 448; - Big5PFreq[36][116] = 447; - Big5PFreq[42][11] = 446; - Big5PFreq[37][172] = 445; - Big5PFreq[37][29] = 444; - Big5PFreq[44][107] = 443; - Big5PFreq[50][17] = 442; - Big5PFreq[39][107] = 441; - Big5PFreq[19][109] = 440; - Big5PFreq[36][60] = 439; - Big5PFreq[49][132] = 438; - Big5PFreq[26][16] = 437; - Big5PFreq[43][155] = 436; - Big5PFreq[37][120] = 435; - Big5PFreq[15][159] = 434; - Big5PFreq[43][6] = 433; - Big5PFreq[45][188] = 432; - Big5PFreq[35][38] = 431; - Big5PFreq[39][143] = 430; - Big5PFreq[48][144] = 429; - Big5PFreq[37][168] = 428; - Big5PFreq[37][1] = 427; - Big5PFreq[36][109] = 426; - Big5PFreq[46][53] = 425; - Big5PFreq[38][54] = 424; - Big5PFreq[36][0] = 423; - Big5PFreq[72][33] = 422; - Big5PFreq[42][8] = 421; - Big5PFreq[36][31] = 420; - Big5PFreq[35][150] = 419; - Big5PFreq[118][93] = 418; - Big5PFreq[37][61] = 417; - Big5PFreq[0][85] = 416; - Big5PFreq[36][27] = 415; - Big5PFreq[35][134] = 414; - Big5PFreq[36][145] = 413; - Big5PFreq[6][96] = 412; - Big5PFreq[36][14] = 411; - Big5PFreq[16][36] = 410; - Big5PFreq[15][175] = 409; - Big5PFreq[35][10] = 408; - Big5PFreq[36][189] = 407; - Big5PFreq[35][51] = 406; - Big5PFreq[35][109] = 405; - Big5PFreq[35][147] = 404; - Big5PFreq[35][180] = 403; - Big5PFreq[72][5] = 402; - Big5PFreq[36][107] = 401; - Big5PFreq[49][116] = 400; - Big5PFreq[73][30] = 399; - Big5PFreq[6][90] = 398; - Big5PFreq[2][70] = 397; - Big5PFreq[17][141] = 396; - Big5PFreq[35][62] = 395; - Big5PFreq[16][180] = 394; - Big5PFreq[4][91] = 393; - Big5PFreq[15][171] = 392; - Big5PFreq[35][177] = 391; - Big5PFreq[37][173] = 390; - Big5PFreq[16][121] = 389; - Big5PFreq[35][5] = 388; - Big5PFreq[46][122] = 387; - Big5PFreq[40][138] = 386; - Big5PFreq[50][49] = 385; - Big5PFreq[36][152] = 384; - Big5PFreq[13][43] = 383; - Big5PFreq[9][88] = 382; - Big5PFreq[36][159] = 381; - Big5PFreq[27][62] = 380; - Big5PFreq[40][18] = 379; - Big5PFreq[17][129] = 378; - Big5PFreq[43][97] = 377; - Big5PFreq[13][131] = 376; - Big5PFreq[46][107] = 375; - Big5PFreq[60][64] = 374; - Big5PFreq[36][179] = 373; - Big5PFreq[37][55] = 372; - Big5PFreq[41][173] = 371; - Big5PFreq[44][172] = 370; - Big5PFreq[23][187] = 369; - Big5PFreq[36][149] = 368; - Big5PFreq[17][125] = 367; - Big5PFreq[55][180] = 366; - Big5PFreq[51][129] = 365; - Big5PFreq[36][51] = 364; - Big5PFreq[37][122] = 363; - Big5PFreq[48][32] = 362; - Big5PFreq[51][99] = 361; - Big5PFreq[54][16] = 360; - Big5PFreq[41][183] = 359; - Big5PFreq[37][179] = 358; - Big5PFreq[38][179] = 357; - Big5PFreq[35][143] = 356; - Big5PFreq[37][24] = 355; - Big5PFreq[40][177] = 354; - Big5PFreq[47][117] = 353; - Big5PFreq[39][52] = 352; - Big5PFreq[22][99] = 351; - Big5PFreq[40][142] = 350; - Big5PFreq[36][49] = 349; - Big5PFreq[38][17] = 348; - Big5PFreq[39][188] = 347; - Big5PFreq[36][186] = 346; - Big5PFreq[35][189] = 345; - Big5PFreq[41][7] = 344; - Big5PFreq[18][91] = 343; - Big5PFreq[43][137] = 342; - Big5PFreq[35][142] = 341; - Big5PFreq[35][117] = 340; - Big5PFreq[39][138] = 339; - Big5PFreq[16][59] = 338; - Big5PFreq[39][174] = 337; - Big5PFreq[55][145] = 336; - Big5PFreq[37][21] = 335; - Big5PFreq[36][180] = 334; - Big5PFreq[37][156] = 333; - Big5PFreq[49][13] = 332; - Big5PFreq[41][107] = 331; - Big5PFreq[36][56] = 330; - Big5PFreq[53][8] = 329; - Big5PFreq[22][114] = 328; - Big5PFreq[5][95] = 327; - Big5PFreq[37][0] = 326; - Big5PFreq[26][183] = 325; - Big5PFreq[22][66] = 324; - Big5PFreq[35][58] = 323; - Big5PFreq[48][117] = 322; - Big5PFreq[36][102] = 321; - Big5PFreq[22][122] = 320; - Big5PFreq[35][11] = 319; - Big5PFreq[46][19] = 318; - Big5PFreq[22][49] = 317; - Big5PFreq[48][166] = 316; - Big5PFreq[41][125] = 315; - Big5PFreq[41][1] = 314; - Big5PFreq[35][178] = 313; - Big5PFreq[41][12] = 312; - Big5PFreq[26][167] = 311; - Big5PFreq[42][152] = 310; - Big5PFreq[42][46] = 309; - Big5PFreq[42][151] = 308; - Big5PFreq[20][135] = 307; - Big5PFreq[37][162] = 306; - Big5PFreq[37][50] = 305; - Big5PFreq[22][185] = 304; - Big5PFreq[36][166] = 303; - Big5PFreq[19][40] = 302; - Big5PFreq[22][107] = 301; - Big5PFreq[22][102] = 300; - Big5PFreq[57][162] = 299; - Big5PFreq[22][124] = 298; - Big5PFreq[37][138] = 297; - Big5PFreq[37][25] = 296; - Big5PFreq[0][69] = 295; - Big5PFreq[43][172] = 294; - Big5PFreq[42][167] = 293; - Big5PFreq[35][120] = 292; - Big5PFreq[41][128] = 291; - Big5PFreq[2][88] = 290; - Big5PFreq[20][123] = 289; - Big5PFreq[35][123] = 288; - Big5PFreq[36][28] = 287; - Big5PFreq[42][188] = 286; - Big5PFreq[42][164] = 285; - Big5PFreq[42][4] = 284; - Big5PFreq[43][57] = 283; - Big5PFreq[39][3] = 282; - Big5PFreq[42][3] = 281; - Big5PFreq[57][158] = 280; - Big5PFreq[35][146] = 279; - Big5PFreq[24][54] = 278; - Big5PFreq[13][110] = 277; - Big5PFreq[23][132] = 276; - Big5PFreq[26][102] = 275; - Big5PFreq[55][178] = 274; - Big5PFreq[17][117] = 273; - Big5PFreq[41][161] = 272; - Big5PFreq[38][150] = 271; - Big5PFreq[10][71] = 270; - Big5PFreq[47][60] = 269; - Big5PFreq[16][114] = 268; - Big5PFreq[21][47] = 267; - Big5PFreq[39][101] = 266; - Big5PFreq[18][45] = 265; - Big5PFreq[40][121] = 264; - Big5PFreq[45][41] = 263; - Big5PFreq[22][167] = 262; - Big5PFreq[26][149] = 261; - Big5PFreq[15][189] = 260; - Big5PFreq[41][177] = 259; - Big5PFreq[46][36] = 258; - Big5PFreq[20][40] = 257; - Big5PFreq[41][54] = 256; - Big5PFreq[3][87] = 255; - Big5PFreq[40][16] = 254; - Big5PFreq[42][15] = 253; - Big5PFreq[11][83] = 252; - Big5PFreq[0][94] = 251; - Big5PFreq[122][81] = 250; - Big5PFreq[41][26] = 249; - Big5PFreq[36][34] = 248; - Big5PFreq[44][148] = 247; - Big5PFreq[35][3] = 246; - Big5PFreq[36][114] = 245; - Big5PFreq[42][112] = 244; - Big5PFreq[35][183] = 243; - Big5PFreq[49][73] = 242; - Big5PFreq[39][2] = 241; - Big5PFreq[38][121] = 240; - Big5PFreq[44][114] = 239; - Big5PFreq[49][32] = 238; - Big5PFreq[1][65] = 237; - Big5PFreq[38][25] = 236; - Big5PFreq[39][4] = 235; - Big5PFreq[42][62] = 234; - Big5PFreq[35][40] = 233; - Big5PFreq[24][2] = 232; - Big5PFreq[53][49] = 231; - Big5PFreq[41][133] = 230; - Big5PFreq[43][134] = 229; - Big5PFreq[3][83] = 228; - Big5PFreq[38][158] = 227; - Big5PFreq[24][17] = 226; - Big5PFreq[52][59] = 225; - Big5PFreq[38][41] = 224; - Big5PFreq[37][127] = 223; - Big5PFreq[22][175] = 222; - Big5PFreq[44][30] = 221; - Big5PFreq[47][178] = 220; - Big5PFreq[43][99] = 219; - Big5PFreq[19][4] = 218; - Big5PFreq[37][97] = 217; - Big5PFreq[38][181] = 216; - Big5PFreq[45][103] = 215; - Big5PFreq[1][86] = 214; - Big5PFreq[40][15] = 213; - Big5PFreq[22][136] = 212; - Big5PFreq[75][165] = 211; - Big5PFreq[36][15] = 210; - Big5PFreq[46][80] = 209; - Big5PFreq[59][55] = 208; - Big5PFreq[37][108] = 207; - Big5PFreq[21][109] = 206; - Big5PFreq[24][165] = 205; - Big5PFreq[79][158] = 204; - Big5PFreq[44][139] = 203; - Big5PFreq[36][124] = 202; - Big5PFreq[42][185] = 201; - Big5PFreq[39][186] = 200; - Big5PFreq[22][128] = 199; - Big5PFreq[40][44] = 198; - Big5PFreq[41][105] = 197; - Big5PFreq[1][70] = 196; - Big5PFreq[1][68] = 195; - Big5PFreq[53][22] = 194; - Big5PFreq[36][54] = 193; - Big5PFreq[47][147] = 192; - Big5PFreq[35][36] = 191; - Big5PFreq[35][185] = 190; - Big5PFreq[45][37] = 189; - Big5PFreq[43][163] = 188; - Big5PFreq[56][115] = 187; - Big5PFreq[38][164] = 186; - Big5PFreq[35][141] = 185; - Big5PFreq[42][132] = 184; - Big5PFreq[46][120] = 183; - Big5PFreq[69][142] = 182; - Big5PFreq[38][175] = 181; - Big5PFreq[22][112] = 180; - Big5PFreq[38][142] = 179; - Big5PFreq[40][37] = 178; - Big5PFreq[37][109] = 177; - Big5PFreq[40][144] = 176; - Big5PFreq[44][117] = 175; - Big5PFreq[35][181] = 174; - Big5PFreq[26][105] = 173; - Big5PFreq[16][48] = 172; - Big5PFreq[44][122] = 171; - Big5PFreq[12][86] = 170; - Big5PFreq[84][53] = 169; - Big5PFreq[17][44] = 168; - Big5PFreq[59][54] = 167; - Big5PFreq[36][98] = 166; - Big5PFreq[45][115] = 165; - Big5PFreq[73][9] = 164; - Big5PFreq[44][123] = 163; - Big5PFreq[37][188] = 162; - Big5PFreq[51][117] = 161; - Big5PFreq[15][156] = 160; - Big5PFreq[36][155] = 159; - Big5PFreq[44][25] = 158; - Big5PFreq[38][12] = 157; - Big5PFreq[38][140] = 156; - Big5PFreq[23][4] = 155; - Big5PFreq[45][149] = 154; - Big5PFreq[22][189] = 153; - Big5PFreq[38][147] = 152; - Big5PFreq[27][5] = 151; - Big5PFreq[22][42] = 150; - Big5PFreq[3][68] = 149; - Big5PFreq[39][51] = 148; - Big5PFreq[36][29] = 147; - Big5PFreq[20][108] = 146; - Big5PFreq[50][57] = 145; - Big5PFreq[55][104] = 144; - Big5PFreq[22][46] = 143; - Big5PFreq[18][164] = 142; - Big5PFreq[50][159] = 141; - Big5PFreq[85][131] = 140; - Big5PFreq[26][79] = 139; - Big5PFreq[38][100] = 138; - Big5PFreq[53][112] = 137; - Big5PFreq[20][190] = 136; - Big5PFreq[14][69] = 135; - Big5PFreq[23][11] = 134; - Big5PFreq[40][114] = 133; - Big5PFreq[40][148] = 132; - Big5PFreq[53][130] = 131; - Big5PFreq[36][2] = 130; - Big5PFreq[66][82] = 129; - Big5PFreq[45][166] = 128; - Big5PFreq[4][88] = 127; - Big5PFreq[16][57] = 126; - Big5PFreq[22][116] = 125; - Big5PFreq[36][108] = 124; - Big5PFreq[13][48] = 123; - Big5PFreq[54][12] = 122; - Big5PFreq[40][136] = 121; - Big5PFreq[36][128] = 120; - Big5PFreq[23][6] = 119; - Big5PFreq[38][125] = 118; - Big5PFreq[45][154] = 117; - Big5PFreq[51][127] = 116; - Big5PFreq[44][163] = 115; - Big5PFreq[16][173] = 114; - Big5PFreq[43][49] = 113; - Big5PFreq[20][112] = 112; - Big5PFreq[15][168] = 111; - Big5PFreq[35][129] = 110; - Big5PFreq[20][45] = 109; - Big5PFreq[38][10] = 108; - Big5PFreq[57][171] = 107; - Big5PFreq[44][190] = 106; - Big5PFreq[40][56] = 105; - Big5PFreq[36][156] = 104; - Big5PFreq[3][88] = 103; - Big5PFreq[50][122] = 102; - Big5PFreq[36][7] = 101; - Big5PFreq[39][43] = 100; - Big5PFreq[15][166] = 99; - Big5PFreq[42][136] = 98; - Big5PFreq[22][131] = 97; - Big5PFreq[44][23] = 96; - Big5PFreq[54][147] = 95; - Big5PFreq[41][32] = 94; - Big5PFreq[23][121] = 93; - Big5PFreq[39][108] = 92; - Big5PFreq[2][78] = 91; - Big5PFreq[40][155] = 90; - Big5PFreq[55][51] = 89; - Big5PFreq[19][34] = 88; - Big5PFreq[48][128] = 87; - Big5PFreq[48][159] = 86; - Big5PFreq[20][70] = 85; - Big5PFreq[34][71] = 84; - Big5PFreq[16][31] = 83; - Big5PFreq[42][157] = 82; - Big5PFreq[20][44] = 81; - Big5PFreq[11][92] = 80; - Big5PFreq[44][180] = 79; - Big5PFreq[84][33] = 78; - Big5PFreq[16][116] = 77; - Big5PFreq[61][163] = 76; - Big5PFreq[35][164] = 75; - Big5PFreq[36][42] = 74; - Big5PFreq[13][40] = 73; - Big5PFreq[43][176] = 72; - Big5PFreq[2][66] = 71; - Big5PFreq[20][133] = 70; - Big5PFreq[36][65] = 69; - Big5PFreq[38][33] = 68; - Big5PFreq[12][91] = 67; - Big5PFreq[36][26] = 66; - Big5PFreq[15][174] = 65; - Big5PFreq[77][32] = 64; - Big5PFreq[16][1] = 63; - Big5PFreq[25][86] = 62; - Big5PFreq[17][13] = 61; - Big5PFreq[5][75] = 60; - Big5PFreq[36][52] = 59; - Big5PFreq[51][164] = 58; - Big5PFreq[12][85] = 57; - Big5PFreq[39][168] = 56; - Big5PFreq[43][16] = 55; - Big5PFreq[40][69] = 54; - Big5PFreq[26][108] = 53; - Big5PFreq[51][56] = 52; - Big5PFreq[16][37] = 51; - Big5PFreq[40][29] = 50; - Big5PFreq[46][171] = 49; - Big5PFreq[40][128] = 48; - Big5PFreq[72][114] = 47; - Big5PFreq[21][103] = 46; - Big5PFreq[22][44] = 45; - Big5PFreq[40][115] = 44; - Big5PFreq[43][7] = 43; - Big5PFreq[43][153] = 42; - Big5PFreq[17][20] = 41; - Big5PFreq[16][49] = 40; - Big5PFreq[36][57] = 39; - Big5PFreq[18][38] = 38; - Big5PFreq[45][184] = 37; - Big5PFreq[37][167] = 36; - Big5PFreq[26][106] = 35; - Big5PFreq[61][121] = 34; - Big5PFreq[89][140] = 33; - Big5PFreq[46][61] = 32; - Big5PFreq[39][163] = 31; - Big5PFreq[40][62] = 30; - Big5PFreq[38][165] = 29; - Big5PFreq[47][37] = 28; - Big5PFreq[18][155] = 27; - Big5PFreq[20][33] = 26; - Big5PFreq[29][90] = 25; - Big5PFreq[20][103] = 24; - Big5PFreq[37][51] = 23; - Big5PFreq[57][0] = 22; - Big5PFreq[40][31] = 21; - Big5PFreq[45][32] = 20; - Big5PFreq[59][23] = 19; - Big5PFreq[18][47] = 18; - Big5PFreq[45][134] = 17; - Big5PFreq[37][59] = 16; - Big5PFreq[21][128] = 15; - Big5PFreq[36][106] = 14; - Big5PFreq[31][39] = 13; - Big5PFreq[40][182] = 12; - Big5PFreq[52][155] = 11; - Big5PFreq[42][166] = 10; - Big5PFreq[35][27] = 9; - Big5PFreq[38][3] = 8; - Big5PFreq[13][44] = 7; - Big5PFreq[58][157] = 6; - Big5PFreq[47][51] = 5; - Big5PFreq[41][37] = 4; - Big5PFreq[41][172] = 3; - Big5PFreq[51][165] = 2; - Big5PFreq[15][161] = 1; - Big5PFreq[24][181] = 0; - EUC_TWFreq[48][49] = 599; - EUC_TWFreq[35][65] = 598; - EUC_TWFreq[41][27] = 597; - EUC_TWFreq[35][0] = 596; - EUC_TWFreq[39][19] = 595; - EUC_TWFreq[35][42] = 594; - EUC_TWFreq[38][66] = 593; - EUC_TWFreq[35][8] = 592; - EUC_TWFreq[35][6] = 591; - EUC_TWFreq[35][66] = 590; - EUC_TWFreq[43][14] = 589; - EUC_TWFreq[69][80] = 588; - EUC_TWFreq[50][48] = 587; - EUC_TWFreq[36][71] = 586; - EUC_TWFreq[37][10] = 585; - EUC_TWFreq[60][52] = 584; - EUC_TWFreq[51][21] = 583; - EUC_TWFreq[40][2] = 582; - EUC_TWFreq[67][35] = 581; - EUC_TWFreq[38][78] = 580; - EUC_TWFreq[49][18] = 579; - EUC_TWFreq[35][23] = 578; - EUC_TWFreq[42][83] = 577; - EUC_TWFreq[79][47] = 576; - EUC_TWFreq[61][82] = 575; - EUC_TWFreq[38][7] = 574; - EUC_TWFreq[35][29] = 573; - EUC_TWFreq[37][77] = 572; - EUC_TWFreq[54][67] = 571; - EUC_TWFreq[38][80] = 570; - EUC_TWFreq[52][74] = 569; - EUC_TWFreq[36][37] = 568; - EUC_TWFreq[74][8] = 567; - EUC_TWFreq[41][83] = 566; - EUC_TWFreq[36][75] = 565; - EUC_TWFreq[49][63] = 564; - EUC_TWFreq[42][58] = 563; - EUC_TWFreq[56][33] = 562; - EUC_TWFreq[37][76] = 561; - EUC_TWFreq[62][39] = 560; - EUC_TWFreq[35][21] = 559; - EUC_TWFreq[70][19] = 558; - EUC_TWFreq[77][88] = 557; - EUC_TWFreq[51][14] = 556; - EUC_TWFreq[36][17] = 555; - EUC_TWFreq[44][51] = 554; - EUC_TWFreq[38][72] = 553; - EUC_TWFreq[74][90] = 552; - EUC_TWFreq[35][48] = 551; - EUC_TWFreq[35][69] = 550; - EUC_TWFreq[66][86] = 549; - EUC_TWFreq[57][20] = 548; - EUC_TWFreq[35][53] = 547; - EUC_TWFreq[36][87] = 546; - EUC_TWFreq[84][67] = 545; - EUC_TWFreq[70][56] = 544; - EUC_TWFreq[71][54] = 543; - EUC_TWFreq[60][70] = 542; - EUC_TWFreq[80][1] = 541; - EUC_TWFreq[39][59] = 540; - EUC_TWFreq[39][51] = 539; - EUC_TWFreq[35][44] = 538; - EUC_TWFreq[48][4] = 537; - EUC_TWFreq[55][24] = 536; - EUC_TWFreq[52][4] = 535; - EUC_TWFreq[54][26] = 534; - EUC_TWFreq[36][31] = 533; - EUC_TWFreq[37][22] = 532; - EUC_TWFreq[37][9] = 531; - EUC_TWFreq[46][0] = 530; - EUC_TWFreq[56][46] = 529; - EUC_TWFreq[47][93] = 528; - EUC_TWFreq[37][25] = 527; - EUC_TWFreq[39][8] = 526; - EUC_TWFreq[46][73] = 525; - EUC_TWFreq[38][48] = 524; - EUC_TWFreq[39][83] = 523; - EUC_TWFreq[60][92] = 522; - EUC_TWFreq[70][11] = 521; - EUC_TWFreq[63][84] = 520; - EUC_TWFreq[38][65] = 519; - EUC_TWFreq[45][45] = 518; - EUC_TWFreq[63][49] = 517; - EUC_TWFreq[63][50] = 516; - EUC_TWFreq[39][93] = 515; - EUC_TWFreq[68][20] = 514; - EUC_TWFreq[44][84] = 513; - EUC_TWFreq[66][34] = 512; - EUC_TWFreq[37][58] = 511; - EUC_TWFreq[39][0] = 510; - EUC_TWFreq[59][1] = 509; - EUC_TWFreq[47][8] = 508; - EUC_TWFreq[61][17] = 507; - EUC_TWFreq[53][87] = 506; - EUC_TWFreq[67][26] = 505; - EUC_TWFreq[43][46] = 504; - EUC_TWFreq[38][61] = 503; - EUC_TWFreq[45][9] = 502; - EUC_TWFreq[66][83] = 501; - EUC_TWFreq[43][88] = 500; - EUC_TWFreq[85][20] = 499; - EUC_TWFreq[57][36] = 498; - EUC_TWFreq[43][6] = 497; - EUC_TWFreq[86][77] = 496; - EUC_TWFreq[42][70] = 495; - EUC_TWFreq[49][78] = 494; - EUC_TWFreq[36][40] = 493; - EUC_TWFreq[42][71] = 492; - EUC_TWFreq[58][49] = 491; - EUC_TWFreq[35][20] = 490; - EUC_TWFreq[76][20] = 489; - EUC_TWFreq[39][25] = 488; - EUC_TWFreq[40][34] = 487; - EUC_TWFreq[39][76] = 486; - EUC_TWFreq[40][1] = 485; - EUC_TWFreq[59][0] = 484; - EUC_TWFreq[39][70] = 483; - EUC_TWFreq[46][14] = 482; - EUC_TWFreq[68][77] = 481; - EUC_TWFreq[38][55] = 480; - EUC_TWFreq[35][78] = 479; - EUC_TWFreq[84][44] = 478; - EUC_TWFreq[36][41] = 477; - EUC_TWFreq[37][62] = 476; - EUC_TWFreq[65][67] = 475; - EUC_TWFreq[69][66] = 474; - EUC_TWFreq[73][55] = 473; - EUC_TWFreq[71][49] = 472; - EUC_TWFreq[66][87] = 471; - EUC_TWFreq[38][33] = 470; - EUC_TWFreq[64][61] = 469; - EUC_TWFreq[35][7] = 468; - EUC_TWFreq[47][49] = 467; - EUC_TWFreq[56][14] = 466; - EUC_TWFreq[36][49] = 465; - EUC_TWFreq[50][81] = 464; - EUC_TWFreq[55][76] = 463; - EUC_TWFreq[35][19] = 462; - EUC_TWFreq[44][47] = 461; - EUC_TWFreq[35][15] = 460; - EUC_TWFreq[82][59] = 459; - EUC_TWFreq[35][43] = 458; - EUC_TWFreq[73][0] = 457; - EUC_TWFreq[57][83] = 456; - EUC_TWFreq[42][46] = 455; - EUC_TWFreq[36][0] = 454; - EUC_TWFreq[70][88] = 453; - EUC_TWFreq[42][22] = 452; - EUC_TWFreq[46][58] = 451; - EUC_TWFreq[36][34] = 450; - EUC_TWFreq[39][24] = 449; - EUC_TWFreq[35][55] = 448; - EUC_TWFreq[44][91] = 447; - EUC_TWFreq[37][51] = 446; - EUC_TWFreq[36][19] = 445; - EUC_TWFreq[69][90] = 444; - EUC_TWFreq[55][35] = 443; - EUC_TWFreq[35][54] = 442; - EUC_TWFreq[49][61] = 441; - EUC_TWFreq[36][67] = 440; - EUC_TWFreq[88][34] = 439; - EUC_TWFreq[35][17] = 438; - EUC_TWFreq[65][69] = 437; - EUC_TWFreq[74][89] = 436; - EUC_TWFreq[37][31] = 435; - EUC_TWFreq[43][48] = 434; - EUC_TWFreq[89][27] = 433; - EUC_TWFreq[42][79] = 432; - EUC_TWFreq[69][57] = 431; - EUC_TWFreq[36][13] = 430; - EUC_TWFreq[35][62] = 429; - EUC_TWFreq[65][47] = 428; - EUC_TWFreq[56][8] = 427; - EUC_TWFreq[38][79] = 426; - EUC_TWFreq[37][64] = 425; - EUC_TWFreq[64][64] = 424; - EUC_TWFreq[38][53] = 423; - EUC_TWFreq[38][31] = 422; - EUC_TWFreq[56][81] = 421; - EUC_TWFreq[36][22] = 420; - EUC_TWFreq[43][4] = 419; - EUC_TWFreq[36][90] = 418; - EUC_TWFreq[38][62] = 417; - EUC_TWFreq[66][85] = 416; - EUC_TWFreq[39][1] = 415; - EUC_TWFreq[59][40] = 414; - EUC_TWFreq[58][93] = 413; - EUC_TWFreq[44][43] = 412; - EUC_TWFreq[39][49] = 411; - EUC_TWFreq[64][2] = 410; - EUC_TWFreq[41][35] = 409; - EUC_TWFreq[60][22] = 408; - EUC_TWFreq[35][91] = 407; - EUC_TWFreq[78][1] = 406; - EUC_TWFreq[36][14] = 405; - EUC_TWFreq[82][29] = 404; - EUC_TWFreq[52][86] = 403; - EUC_TWFreq[40][16] = 402; - EUC_TWFreq[91][52] = 401; - EUC_TWFreq[50][75] = 400; - EUC_TWFreq[64][30] = 399; - EUC_TWFreq[90][78] = 398; - EUC_TWFreq[36][52] = 397; - EUC_TWFreq[55][87] = 396; - EUC_TWFreq[57][5] = 395; - EUC_TWFreq[57][31] = 394; - EUC_TWFreq[42][35] = 393; - EUC_TWFreq[69][50] = 392; - EUC_TWFreq[45][8] = 391; - EUC_TWFreq[50][87] = 390; - EUC_TWFreq[69][55] = 389; - EUC_TWFreq[92][3] = 388; - EUC_TWFreq[36][43] = 387; - EUC_TWFreq[64][10] = 386; - EUC_TWFreq[56][25] = 385; - EUC_TWFreq[60][68] = 384; - EUC_TWFreq[51][46] = 383; - EUC_TWFreq[50][0] = 382; - EUC_TWFreq[38][30] = 381; - EUC_TWFreq[50][85] = 380; - EUC_TWFreq[60][54] = 379; - EUC_TWFreq[73][6] = 378; - EUC_TWFreq[73][28] = 377; - EUC_TWFreq[56][19] = 376; - EUC_TWFreq[62][69] = 375; - EUC_TWFreq[81][66] = 374; - EUC_TWFreq[40][32] = 373; - EUC_TWFreq[76][31] = 372; - EUC_TWFreq[35][10] = 371; - EUC_TWFreq[41][37] = 370; - EUC_TWFreq[52][82] = 369; - EUC_TWFreq[91][72] = 368; - EUC_TWFreq[37][29] = 367; - EUC_TWFreq[56][30] = 366; - EUC_TWFreq[37][80] = 365; - EUC_TWFreq[81][56] = 364; - EUC_TWFreq[70][3] = 363; - EUC_TWFreq[76][15] = 362; - EUC_TWFreq[46][47] = 361; - EUC_TWFreq[35][88] = 360; - EUC_TWFreq[61][58] = 359; - EUC_TWFreq[37][37] = 358; - EUC_TWFreq[57][22] = 357; - EUC_TWFreq[41][23] = 356; - EUC_TWFreq[90][66] = 355; - EUC_TWFreq[39][60] = 354; - EUC_TWFreq[38][0] = 353; - EUC_TWFreq[37][87] = 352; - EUC_TWFreq[46][2] = 351; - EUC_TWFreq[38][56] = 350; - EUC_TWFreq[58][11] = 349; - EUC_TWFreq[48][10] = 348; - EUC_TWFreq[74][4] = 347; - EUC_TWFreq[40][42] = 346; - EUC_TWFreq[41][52] = 345; - EUC_TWFreq[61][92] = 344; - EUC_TWFreq[39][50] = 343; - EUC_TWFreq[47][88] = 342; - EUC_TWFreq[88][36] = 341; - EUC_TWFreq[45][73] = 340; - EUC_TWFreq[82][3] = 339; - EUC_TWFreq[61][36] = 338; - EUC_TWFreq[60][33] = 337; - EUC_TWFreq[38][27] = 336; - EUC_TWFreq[35][83] = 335; - EUC_TWFreq[65][24] = 334; - EUC_TWFreq[73][10] = 333; - EUC_TWFreq[41][13] = 332; - EUC_TWFreq[50][27] = 331; - EUC_TWFreq[59][50] = 330; - EUC_TWFreq[42][45] = 329; - EUC_TWFreq[55][19] = 328; - EUC_TWFreq[36][77] = 327; - EUC_TWFreq[69][31] = 326; - EUC_TWFreq[60][7] = 325; - EUC_TWFreq[40][88] = 324; - EUC_TWFreq[57][56] = 323; - EUC_TWFreq[50][50] = 322; - EUC_TWFreq[42][37] = 321; - EUC_TWFreq[38][82] = 320; - EUC_TWFreq[52][25] = 319; - EUC_TWFreq[42][67] = 318; - EUC_TWFreq[48][40] = 317; - EUC_TWFreq[45][81] = 316; - EUC_TWFreq[57][14] = 315; - EUC_TWFreq[42][13] = 314; - EUC_TWFreq[78][0] = 313; - EUC_TWFreq[35][51] = 312; - EUC_TWFreq[41][67] = 311; - EUC_TWFreq[64][23] = 310; - EUC_TWFreq[36][65] = 309; - EUC_TWFreq[48][50] = 308; - EUC_TWFreq[46][69] = 307; - EUC_TWFreq[47][89] = 306; - EUC_TWFreq[41][48] = 305; - EUC_TWFreq[60][56] = 304; - EUC_TWFreq[44][82] = 303; - EUC_TWFreq[47][35] = 302; - EUC_TWFreq[49][3] = 301; - EUC_TWFreq[49][69] = 300; - EUC_TWFreq[45][93] = 299; - EUC_TWFreq[60][34] = 298; - EUC_TWFreq[60][82] = 297; - EUC_TWFreq[61][61] = 296; - EUC_TWFreq[86][42] = 295; - EUC_TWFreq[89][60] = 294; - EUC_TWFreq[48][31] = 293; - EUC_TWFreq[35][75] = 292; - EUC_TWFreq[91][39] = 291; - EUC_TWFreq[53][19] = 290; - EUC_TWFreq[39][72] = 289; - EUC_TWFreq[69][59] = 288; - EUC_TWFreq[41][7] = 287; - EUC_TWFreq[54][13] = 286; - EUC_TWFreq[43][28] = 285; - EUC_TWFreq[36][6] = 284; - EUC_TWFreq[45][75] = 283; - EUC_TWFreq[36][61] = 282; - EUC_TWFreq[38][21] = 281; - EUC_TWFreq[45][14] = 280; - EUC_TWFreq[61][43] = 279; - EUC_TWFreq[36][63] = 278; - EUC_TWFreq[43][30] = 277; - EUC_TWFreq[46][51] = 276; - EUC_TWFreq[68][87] = 275; - EUC_TWFreq[39][26] = 274; - EUC_TWFreq[46][76] = 273; - EUC_TWFreq[36][15] = 272; - EUC_TWFreq[35][40] = 271; - EUC_TWFreq[79][60] = 270; - EUC_TWFreq[46][7] = 269; - EUC_TWFreq[65][72] = 268; - EUC_TWFreq[69][88] = 267; - EUC_TWFreq[47][18] = 266; - EUC_TWFreq[37][0] = 265; - EUC_TWFreq[37][49] = 264; - EUC_TWFreq[67][37] = 263; - EUC_TWFreq[36][91] = 262; - EUC_TWFreq[75][48] = 261; - EUC_TWFreq[75][63] = 260; - EUC_TWFreq[83][87] = 259; - EUC_TWFreq[37][44] = 258; - EUC_TWFreq[73][54] = 257; - EUC_TWFreq[51][61] = 256; - EUC_TWFreq[46][57] = 255; - EUC_TWFreq[55][21] = 254; - EUC_TWFreq[39][66] = 253; - EUC_TWFreq[47][11] = 252; - EUC_TWFreq[52][8] = 251; - EUC_TWFreq[82][81] = 250; - EUC_TWFreq[36][57] = 249; - EUC_TWFreq[38][54] = 248; - EUC_TWFreq[43][81] = 247; - EUC_TWFreq[37][42] = 246; - EUC_TWFreq[40][18] = 245; - EUC_TWFreq[80][90] = 244; - EUC_TWFreq[37][84] = 243; - EUC_TWFreq[57][15] = 242; - EUC_TWFreq[38][87] = 241; - EUC_TWFreq[37][32] = 240; - EUC_TWFreq[53][53] = 239; - EUC_TWFreq[89][29] = 238; - EUC_TWFreq[81][53] = 237; - EUC_TWFreq[75][3] = 236; - EUC_TWFreq[83][73] = 235; - EUC_TWFreq[66][13] = 234; - EUC_TWFreq[48][7] = 233; - EUC_TWFreq[46][35] = 232; - EUC_TWFreq[35][86] = 231; - EUC_TWFreq[37][20] = 230; - EUC_TWFreq[46][80] = 229; - EUC_TWFreq[38][24] = 228; - EUC_TWFreq[41][68] = 227; - EUC_TWFreq[42][21] = 226; - EUC_TWFreq[43][32] = 225; - EUC_TWFreq[38][20] = 224; - EUC_TWFreq[37][59] = 223; - EUC_TWFreq[41][77] = 222; - EUC_TWFreq[59][57] = 221; - EUC_TWFreq[68][59] = 220; - EUC_TWFreq[39][43] = 219; - EUC_TWFreq[54][39] = 218; - EUC_TWFreq[48][28] = 217; - EUC_TWFreq[54][28] = 216; - EUC_TWFreq[41][44] = 215; - EUC_TWFreq[51][64] = 214; - EUC_TWFreq[47][72] = 213; - EUC_TWFreq[62][67] = 212; - EUC_TWFreq[42][43] = 211; - EUC_TWFreq[61][38] = 210; - EUC_TWFreq[76][25] = 209; - EUC_TWFreq[48][91] = 208; - EUC_TWFreq[36][36] = 207; - EUC_TWFreq[80][32] = 206; - EUC_TWFreq[81][40] = 205; - EUC_TWFreq[37][5] = 204; - EUC_TWFreq[74][69] = 203; - EUC_TWFreq[36][82] = 202; - EUC_TWFreq[46][59] = 201; - /* - * EUC_TWFreq[38][32] = 200; EUC_TWFreq[74][2] = 199; EUC_TWFreq[53][31] - * = 198; EUC_TWFreq[35][38] = 197; EUC_TWFreq[46][62] = 196; - * EUC_TWFreq[77][31] = 195; EUC_TWFreq[55][74] = 194; EUC_TWFreq[66][6] - * = 193; EUC_TWFreq[56][21] = 192; EUC_TWFreq[54][78] = 191; - * EUC_TWFreq[43][51] = 190; EUC_TWFreq[64][93] = 189; EUC_TWFreq[92][7] - * = 188; EUC_TWFreq[83][89] = 187; EUC_TWFreq[69][9] = 186; - * EUC_TWFreq[45][4] = 185; EUC_TWFreq[53][9] = 184; EUC_TWFreq[43][2] = - * 183; EUC_TWFreq[35][11] = 182; EUC_TWFreq[51][25] = 181; - * EUC_TWFreq[52][71] = 180; EUC_TWFreq[81][67] = 179; - * EUC_TWFreq[37][33] = 178; EUC_TWFreq[38][57] = 177; - * EUC_TWFreq[39][77] = 176; EUC_TWFreq[40][26] = 175; - * EUC_TWFreq[37][21] = 174; EUC_TWFreq[81][70] = 173; - * EUC_TWFreq[56][80] = 172; EUC_TWFreq[65][14] = 171; - * EUC_TWFreq[62][47] = 170; EUC_TWFreq[56][54] = 169; - * EUC_TWFreq[45][17] = 168; EUC_TWFreq[52][52] = 167; - * EUC_TWFreq[74][30] = 166; EUC_TWFreq[60][57] = 165; - * EUC_TWFreq[41][15] = 164; EUC_TWFreq[47][69] = 163; - * EUC_TWFreq[61][11] = 162; EUC_TWFreq[72][25] = 161; - * EUC_TWFreq[82][56] = 160; EUC_TWFreq[76][92] = 159; - * EUC_TWFreq[51][22] = 158; EUC_TWFreq[55][69] = 157; - * EUC_TWFreq[49][43] = 156; EUC_TWFreq[69][49] = 155; - * EUC_TWFreq[88][42] = 154; EUC_TWFreq[84][41] = 153; - * EUC_TWFreq[79][33] = 152; EUC_TWFreq[47][17] = 151; - * EUC_TWFreq[52][88] = 150; EUC_TWFreq[63][74] = 149; - * EUC_TWFreq[50][32] = 148; EUC_TWFreq[65][10] = 147; EUC_TWFreq[57][6] - * = 146; EUC_TWFreq[52][23] = 145; EUC_TWFreq[36][70] = 144; - * EUC_TWFreq[65][55] = 143; EUC_TWFreq[35][27] = 142; - * EUC_TWFreq[57][63] = 141; EUC_TWFreq[39][92] = 140; - * EUC_TWFreq[79][75] = 139; EUC_TWFreq[36][30] = 138; - * EUC_TWFreq[53][60] = 137; EUC_TWFreq[55][43] = 136; - * EUC_TWFreq[71][22] = 135; EUC_TWFreq[43][16] = 134; - * EUC_TWFreq[65][21] = 133; EUC_TWFreq[84][51] = 132; - * EUC_TWFreq[43][64] = 131; EUC_TWFreq[87][91] = 130; - * EUC_TWFreq[47][45] = 129; EUC_TWFreq[65][29] = 128; - * EUC_TWFreq[88][16] = 127; EUC_TWFreq[50][5] = 126; EUC_TWFreq[47][33] - * = 125; EUC_TWFreq[46][27] = 124; EUC_TWFreq[85][2] = 123; - * EUC_TWFreq[43][77] = 122; EUC_TWFreq[70][9] = 121; EUC_TWFreq[41][54] - * = 120; EUC_TWFreq[56][12] = 119; EUC_TWFreq[90][65] = 118; - * EUC_TWFreq[91][50] = 117; EUC_TWFreq[48][41] = 116; - * EUC_TWFreq[35][89] = 115; EUC_TWFreq[90][83] = 114; - * EUC_TWFreq[44][40] = 113; EUC_TWFreq[50][88] = 112; - * EUC_TWFreq[72][39] = 111; EUC_TWFreq[45][3] = 110; EUC_TWFreq[71][33] - * = 109; EUC_TWFreq[39][12] = 108; EUC_TWFreq[59][24] = 107; - * EUC_TWFreq[60][62] = 106; EUC_TWFreq[44][33] = 105; - * EUC_TWFreq[53][70] = 104; EUC_TWFreq[77][90] = 103; - * EUC_TWFreq[50][58] = 102; EUC_TWFreq[54][1] = 101; EUC_TWFreq[73][19] - * = 100; EUC_TWFreq[37][3] = 99; EUC_TWFreq[49][91] = 98; - * EUC_TWFreq[88][43] = 97; EUC_TWFreq[36][78] = 96; EUC_TWFreq[44][20] - * = 95; EUC_TWFreq[64][15] = 94; EUC_TWFreq[72][28] = 93; - * EUC_TWFreq[70][13] = 92; EUC_TWFreq[65][83] = 91; EUC_TWFreq[58][68] - * = 90; EUC_TWFreq[59][32] = 89; EUC_TWFreq[39][13] = 88; - * EUC_TWFreq[55][64] = 87; EUC_TWFreq[56][59] = 86; EUC_TWFreq[39][17] - * = 85; EUC_TWFreq[55][84] = 84; EUC_TWFreq[77][85] = 83; - * EUC_TWFreq[60][19] = 82; EUC_TWFreq[62][82] = 81; EUC_TWFreq[78][16] - * = 80; EUC_TWFreq[66][8] = 79; EUC_TWFreq[39][42] = 78; - * EUC_TWFreq[61][24] = 77; EUC_TWFreq[57][67] = 76; EUC_TWFreq[38][83] - * = 75; EUC_TWFreq[36][53] = 74; EUC_TWFreq[67][76] = 73; - * EUC_TWFreq[37][91] = 72; EUC_TWFreq[44][26] = 71; EUC_TWFreq[72][86] - * = 70; EUC_TWFreq[44][87] = 69; EUC_TWFreq[45][50] = 68; - * EUC_TWFreq[58][4] = 67; EUC_TWFreq[86][65] = 66; EUC_TWFreq[45][56] = - * 65; EUC_TWFreq[79][49] = 64; EUC_TWFreq[35][3] = 63; - * EUC_TWFreq[48][83] = 62; EUC_TWFreq[71][21] = 61; EUC_TWFreq[77][93] - * = 60; EUC_TWFreq[87][92] = 59; EUC_TWFreq[38][35] = 58; - * EUC_TWFreq[66][17] = 57; EUC_TWFreq[37][66] = 56; EUC_TWFreq[51][42] - * = 55; EUC_TWFreq[57][73] = 54; EUC_TWFreq[51][54] = 53; - * EUC_TWFreq[75][64] = 52; EUC_TWFreq[35][5] = 51; EUC_TWFreq[49][40] = - * 50; EUC_TWFreq[58][35] = 49; EUC_TWFreq[67][88] = 48; - * EUC_TWFreq[60][51] = 47; EUC_TWFreq[36][92] = 46; EUC_TWFreq[44][41] - * = 45; EUC_TWFreq[58][29] = 44; EUC_TWFreq[43][62] = 43; - * EUC_TWFreq[56][23] = 42; EUC_TWFreq[67][44] = 41; EUC_TWFreq[52][91] - * = 40; EUC_TWFreq[42][81] = 39; EUC_TWFreq[64][25] = 38; - * EUC_TWFreq[35][36] = 37; EUC_TWFreq[47][73] = 36; EUC_TWFreq[36][1] = - * 35; EUC_TWFreq[65][84] = 34; EUC_TWFreq[73][1] = 33; - * EUC_TWFreq[79][66] = 32; EUC_TWFreq[69][14] = 31; EUC_TWFreq[65][28] - * = 30; EUC_TWFreq[60][93] = 29; EUC_TWFreq[72][79] = 28; - * EUC_TWFreq[48][0] = 27; EUC_TWFreq[73][43] = 26; EUC_TWFreq[66][47] = - * 25; EUC_TWFreq[41][18] = 24; EUC_TWFreq[51][10] = 23; - * EUC_TWFreq[59][7] = 22; EUC_TWFreq[53][27] = 21; EUC_TWFreq[86][67] = - * 20; EUC_TWFreq[49][87] = 19; EUC_TWFreq[52][28] = 18; - * EUC_TWFreq[52][12] = 17; EUC_TWFreq[42][30] = 16; EUC_TWFreq[65][35] - * = 15; EUC_TWFreq[46][64] = 14; EUC_TWFreq[71][7] = 13; - * EUC_TWFreq[56][57] = 12; EUC_TWFreq[56][31] = 11; EUC_TWFreq[41][31] - * = 10; EUC_TWFreq[48][59] = 9; EUC_TWFreq[63][92] = 8; - * EUC_TWFreq[62][57] = 7; EUC_TWFreq[65][87] = 6; EUC_TWFreq[70][10] = - * 5; EUC_TWFreq[52][40] = 4; EUC_TWFreq[40][22] = 3; EUC_TWFreq[65][91] - * = 2; EUC_TWFreq[50][25] = 1; EUC_TWFreq[35][84] = 0; - */ - GBKFreq[52][132] = 600; - GBKFreq[73][135] = 599; - GBKFreq[49][123] = 598; - GBKFreq[77][146] = 597; - GBKFreq[81][123] = 596; - GBKFreq[82][144] = 595; - GBKFreq[51][179] = 594; - GBKFreq[83][154] = 593; - GBKFreq[71][139] = 592; - GBKFreq[64][139] = 591; - GBKFreq[85][144] = 590; - GBKFreq[52][125] = 589; - GBKFreq[88][25] = 588; - GBKFreq[81][106] = 587; - GBKFreq[81][148] = 586; - GBKFreq[62][137] = 585; - GBKFreq[94][0] = 584; - GBKFreq[1][64] = 583; - GBKFreq[67][163] = 582; - GBKFreq[20][190] = 581; - GBKFreq[57][131] = 580; - GBKFreq[29][169] = 579; - GBKFreq[72][143] = 578; - GBKFreq[0][173] = 577; - GBKFreq[11][23] = 576; - GBKFreq[61][141] = 575; - GBKFreq[60][123] = 574; - GBKFreq[81][114] = 573; - GBKFreq[82][131] = 572; - GBKFreq[67][156] = 571; - GBKFreq[71][167] = 570; - GBKFreq[20][50] = 569; - GBKFreq[77][132] = 568; - GBKFreq[84][38] = 567; - GBKFreq[26][29] = 566; - GBKFreq[74][187] = 565; - GBKFreq[62][116] = 564; - GBKFreq[67][135] = 563; - GBKFreq[5][86] = 562; - GBKFreq[72][186] = 561; - GBKFreq[75][161] = 560; - GBKFreq[78][130] = 559; - GBKFreq[94][30] = 558; - GBKFreq[84][72] = 557; - GBKFreq[1][67] = 556; - GBKFreq[75][172] = 555; - GBKFreq[74][185] = 554; - GBKFreq[53][160] = 553; - GBKFreq[123][14] = 552; - GBKFreq[79][97] = 551; - GBKFreq[85][110] = 550; - GBKFreq[78][171] = 549; - GBKFreq[52][131] = 548; - GBKFreq[56][100] = 547; - GBKFreq[50][182] = 546; - GBKFreq[94][64] = 545; - GBKFreq[106][74] = 544; - GBKFreq[11][102] = 543; - GBKFreq[53][124] = 542; - GBKFreq[24][3] = 541; - GBKFreq[86][148] = 540; - GBKFreq[53][184] = 539; - GBKFreq[86][147] = 538; - GBKFreq[96][161] = 537; - GBKFreq[82][77] = 536; - GBKFreq[59][146] = 535; - GBKFreq[84][126] = 534; - GBKFreq[79][132] = 533; - GBKFreq[85][123] = 532; - GBKFreq[71][101] = 531; - GBKFreq[85][106] = 530; - GBKFreq[6][184] = 529; - GBKFreq[57][156] = 528; - GBKFreq[75][104] = 527; - GBKFreq[50][137] = 526; - GBKFreq[79][133] = 525; - GBKFreq[76][108] = 524; - GBKFreq[57][142] = 523; - GBKFreq[84][130] = 522; - GBKFreq[52][128] = 521; - GBKFreq[47][44] = 520; - GBKFreq[52][152] = 519; - GBKFreq[54][104] = 518; - GBKFreq[30][47] = 517; - GBKFreq[71][123] = 516; - GBKFreq[52][107] = 515; - GBKFreq[45][84] = 514; - GBKFreq[107][118] = 513; - GBKFreq[5][161] = 512; - GBKFreq[48][126] = 511; - GBKFreq[67][170] = 510; - GBKFreq[43][6] = 509; - GBKFreq[70][112] = 508; - GBKFreq[86][174] = 507; - GBKFreq[84][166] = 506; - GBKFreq[79][130] = 505; - GBKFreq[57][141] = 504; - GBKFreq[81][178] = 503; - GBKFreq[56][187] = 502; - GBKFreq[81][162] = 501; - GBKFreq[53][104] = 500; - GBKFreq[123][35] = 499; - GBKFreq[70][169] = 498; - GBKFreq[69][164] = 497; - GBKFreq[109][61] = 496; - GBKFreq[73][130] = 495; - GBKFreq[62][134] = 494; - GBKFreq[54][125] = 493; - GBKFreq[79][105] = 492; - GBKFreq[70][165] = 491; - GBKFreq[71][189] = 490; - GBKFreq[23][147] = 489; - GBKFreq[51][139] = 488; - GBKFreq[47][137] = 487; - GBKFreq[77][123] = 486; - GBKFreq[86][183] = 485; - GBKFreq[63][173] = 484; - GBKFreq[79][144] = 483; - GBKFreq[84][159] = 482; - GBKFreq[60][91] = 481; - GBKFreq[66][187] = 480; - GBKFreq[73][114] = 479; - GBKFreq[85][56] = 478; - GBKFreq[71][149] = 477; - GBKFreq[84][189] = 476; - GBKFreq[104][31] = 475; - GBKFreq[83][82] = 474; - GBKFreq[68][35] = 473; - GBKFreq[11][77] = 472; - GBKFreq[15][155] = 471; - GBKFreq[83][153] = 470; - GBKFreq[71][1] = 469; - GBKFreq[53][190] = 468; - GBKFreq[50][135] = 467; - GBKFreq[3][147] = 466; - GBKFreq[48][136] = 465; - GBKFreq[66][166] = 464; - GBKFreq[55][159] = 463; - GBKFreq[82][150] = 462; - GBKFreq[58][178] = 461; - GBKFreq[64][102] = 460; - GBKFreq[16][106] = 459; - GBKFreq[68][110] = 458; - GBKFreq[54][14] = 457; - GBKFreq[60][140] = 456; - GBKFreq[91][71] = 455; - GBKFreq[54][150] = 454; - GBKFreq[78][177] = 453; - GBKFreq[78][117] = 452; - GBKFreq[104][12] = 451; - GBKFreq[73][150] = 450; - GBKFreq[51][142] = 449; - GBKFreq[81][145] = 448; - GBKFreq[66][183] = 447; - GBKFreq[51][178] = 446; - GBKFreq[75][107] = 445; - GBKFreq[65][119] = 444; - GBKFreq[69][176] = 443; - GBKFreq[59][122] = 442; - GBKFreq[78][160] = 441; - GBKFreq[85][183] = 440; - GBKFreq[105][16] = 439; - GBKFreq[73][110] = 438; - GBKFreq[104][39] = 437; - GBKFreq[119][16] = 436; - GBKFreq[76][162] = 435; - GBKFreq[67][152] = 434; - GBKFreq[82][24] = 433; - GBKFreq[73][121] = 432; - GBKFreq[83][83] = 431; - GBKFreq[82][145] = 430; - GBKFreq[49][133] = 429; - GBKFreq[94][13] = 428; - GBKFreq[58][139] = 427; - GBKFreq[74][189] = 426; - GBKFreq[66][177] = 425; - GBKFreq[85][184] = 424; - GBKFreq[55][183] = 423; - GBKFreq[71][107] = 422; - GBKFreq[11][98] = 421; - GBKFreq[72][153] = 420; - GBKFreq[2][137] = 419; - GBKFreq[59][147] = 418; - GBKFreq[58][152] = 417; - GBKFreq[55][144] = 416; - GBKFreq[73][125] = 415; - GBKFreq[52][154] = 414; - GBKFreq[70][178] = 413; - GBKFreq[79][148] = 412; - GBKFreq[63][143] = 411; - GBKFreq[50][140] = 410; - GBKFreq[47][145] = 409; - GBKFreq[48][123] = 408; - GBKFreq[56][107] = 407; - GBKFreq[84][83] = 406; - GBKFreq[59][112] = 405; - GBKFreq[124][72] = 404; - GBKFreq[79][99] = 403; - GBKFreq[3][37] = 402; - GBKFreq[114][55] = 401; - GBKFreq[85][152] = 400; - GBKFreq[60][47] = 399; - GBKFreq[65][96] = 398; - GBKFreq[74][110] = 397; - GBKFreq[86][182] = 396; - GBKFreq[50][99] = 395; - GBKFreq[67][186] = 394; - GBKFreq[81][74] = 393; - GBKFreq[80][37] = 392; - GBKFreq[21][60] = 391; - GBKFreq[110][12] = 390; - GBKFreq[60][162] = 389; - GBKFreq[29][115] = 388; - GBKFreq[83][130] = 387; - GBKFreq[52][136] = 386; - GBKFreq[63][114] = 385; - GBKFreq[49][127] = 384; - GBKFreq[83][109] = 383; - GBKFreq[66][128] = 382; - GBKFreq[78][136] = 381; - GBKFreq[81][180] = 380; - GBKFreq[76][104] = 379; - GBKFreq[56][156] = 378; - GBKFreq[61][23] = 377; - GBKFreq[4][30] = 376; - GBKFreq[69][154] = 375; - GBKFreq[100][37] = 374; - GBKFreq[54][177] = 373; - GBKFreq[23][119] = 372; - GBKFreq[71][171] = 371; - GBKFreq[84][146] = 370; - GBKFreq[20][184] = 369; - GBKFreq[86][76] = 368; - GBKFreq[74][132] = 367; - GBKFreq[47][97] = 366; - GBKFreq[82][137] = 365; - GBKFreq[94][56] = 364; - GBKFreq[92][30] = 363; - GBKFreq[19][117] = 362; - GBKFreq[48][173] = 361; - GBKFreq[2][136] = 360; - GBKFreq[7][182] = 359; - GBKFreq[74][188] = 358; - GBKFreq[14][132] = 357; - GBKFreq[62][172] = 356; - GBKFreq[25][39] = 355; - GBKFreq[85][129] = 354; - GBKFreq[64][98] = 353; - GBKFreq[67][127] = 352; - GBKFreq[72][167] = 351; - GBKFreq[57][143] = 350; - GBKFreq[76][187] = 349; - GBKFreq[83][181] = 348; - GBKFreq[84][10] = 347; - GBKFreq[55][166] = 346; - GBKFreq[55][188] = 345; - GBKFreq[13][151] = 344; - GBKFreq[62][124] = 343; - GBKFreq[53][136] = 342; - GBKFreq[106][57] = 341; - GBKFreq[47][166] = 340; - GBKFreq[109][30] = 339; - GBKFreq[78][114] = 338; - GBKFreq[83][19] = 337; - GBKFreq[56][162] = 336; - GBKFreq[60][177] = 335; - GBKFreq[88][9] = 334; - GBKFreq[74][163] = 333; - GBKFreq[52][156] = 332; - GBKFreq[71][180] = 331; - GBKFreq[60][57] = 330; - GBKFreq[72][173] = 329; - GBKFreq[82][91] = 328; - GBKFreq[51][186] = 327; - GBKFreq[75][86] = 326; - GBKFreq[75][78] = 325; - GBKFreq[76][170] = 324; - GBKFreq[60][147] = 323; - GBKFreq[82][75] = 322; - GBKFreq[80][148] = 321; - GBKFreq[86][150] = 320; - GBKFreq[13][95] = 319; - GBKFreq[0][11] = 318; - GBKFreq[84][190] = 317; - GBKFreq[76][166] = 316; - GBKFreq[14][72] = 315; - GBKFreq[67][144] = 314; - GBKFreq[84][44] = 313; - GBKFreq[72][125] = 312; - GBKFreq[66][127] = 311; - GBKFreq[60][25] = 310; - GBKFreq[70][146] = 309; - GBKFreq[79][135] = 308; - GBKFreq[54][135] = 307; - GBKFreq[60][104] = 306; - GBKFreq[55][132] = 305; - GBKFreq[94][2] = 304; - GBKFreq[54][133] = 303; - GBKFreq[56][190] = 302; - GBKFreq[58][174] = 301; - GBKFreq[80][144] = 300; - GBKFreq[85][113] = 299; - /* - * GBKFreq[83][15] = 298; GBKFreq[105][80] = 297; GBKFreq[7][179] = 296; - * GBKFreq[93][4] = 295; GBKFreq[123][40] = 294; GBKFreq[85][120] = 293; - * GBKFreq[77][165] = 292; GBKFreq[86][67] = 291; GBKFreq[25][162] = - * 290; GBKFreq[77][183] = 289; GBKFreq[83][71] = 288; GBKFreq[78][99] = - * 287; GBKFreq[72][177] = 286; GBKFreq[71][97] = 285; GBKFreq[58][111] - * = 284; GBKFreq[77][175] = 283; GBKFreq[76][181] = 282; - * GBKFreq[71][142] = 281; GBKFreq[64][150] = 280; GBKFreq[5][142] = - * 279; GBKFreq[73][128] = 278; GBKFreq[73][156] = 277; GBKFreq[60][188] - * = 276; GBKFreq[64][56] = 275; GBKFreq[74][128] = 274; - * GBKFreq[48][163] = 273; GBKFreq[54][116] = 272; GBKFreq[73][127] = - * 271; GBKFreq[16][176] = 270; GBKFreq[62][149] = 269; GBKFreq[105][96] - * = 268; GBKFreq[55][186] = 267; GBKFreq[4][51] = 266; GBKFreq[48][113] - * = 265; GBKFreq[48][152] = 264; GBKFreq[23][9] = 263; GBKFreq[56][102] - * = 262; GBKFreq[11][81] = 261; GBKFreq[82][112] = 260; GBKFreq[65][85] - * = 259; GBKFreq[69][125] = 258; GBKFreq[68][31] = 257; GBKFreq[5][20] - * = 256; GBKFreq[60][176] = 255; GBKFreq[82][81] = 254; - * GBKFreq[72][107] = 253; GBKFreq[3][52] = 252; GBKFreq[71][157] = 251; - * GBKFreq[24][46] = 250; GBKFreq[69][108] = 249; GBKFreq[78][178] = - * 248; GBKFreq[9][69] = 247; GBKFreq[73][144] = 246; GBKFreq[63][187] = - * 245; GBKFreq[68][36] = 244; GBKFreq[47][151] = 243; GBKFreq[14][74] = - * 242; GBKFreq[47][114] = 241; GBKFreq[80][171] = 240; GBKFreq[75][152] - * = 239; GBKFreq[86][40] = 238; GBKFreq[93][43] = 237; GBKFreq[2][50] = - * 236; GBKFreq[62][66] = 235; GBKFreq[1][183] = 234; GBKFreq[74][124] = - * 233; GBKFreq[58][104] = 232; GBKFreq[83][106] = 231; GBKFreq[60][144] - * = 230; GBKFreq[48][99] = 229; GBKFreq[54][157] = 228; - * GBKFreq[70][179] = 227; GBKFreq[61][127] = 226; GBKFreq[57][135] = - * 225; GBKFreq[59][190] = 224; GBKFreq[77][116] = 223; GBKFreq[26][17] - * = 222; GBKFreq[60][13] = 221; GBKFreq[71][38] = 220; GBKFreq[85][177] - * = 219; GBKFreq[59][73] = 218; GBKFreq[50][150] = 217; - * GBKFreq[79][102] = 216; GBKFreq[76][118] = 215; GBKFreq[67][132] = - * 214; GBKFreq[73][146] = 213; GBKFreq[83][184] = 212; GBKFreq[86][159] - * = 211; GBKFreq[95][120] = 210; GBKFreq[23][139] = 209; - * GBKFreq[64][183] = 208; GBKFreq[85][103] = 207; GBKFreq[41][90] = - * 206; GBKFreq[87][72] = 205; GBKFreq[62][104] = 204; GBKFreq[79][168] - * = 203; GBKFreq[79][150] = 202; GBKFreq[104][20] = 201; - * GBKFreq[56][114] = 200; GBKFreq[84][26] = 199; GBKFreq[57][99] = 198; - * GBKFreq[62][154] = 197; GBKFreq[47][98] = 196; GBKFreq[61][64] = 195; - * GBKFreq[112][18] = 194; GBKFreq[123][19] = 193; GBKFreq[4][98] = 192; - * GBKFreq[47][163] = 191; GBKFreq[66][188] = 190; GBKFreq[81][85] = - * 189; GBKFreq[82][30] = 188; GBKFreq[65][83] = 187; GBKFreq[67][24] = - * 186; GBKFreq[68][179] = 185; GBKFreq[55][177] = 184; GBKFreq[2][122] - * = 183; GBKFreq[47][139] = 182; GBKFreq[79][158] = 181; - * GBKFreq[64][143] = 180; GBKFreq[100][24] = 179; GBKFreq[73][103] = - * 178; GBKFreq[50][148] = 177; GBKFreq[86][97] = 176; GBKFreq[59][116] - * = 175; GBKFreq[64][173] = 174; GBKFreq[99][91] = 173; GBKFreq[11][99] - * = 172; GBKFreq[78][179] = 171; GBKFreq[18][17] = 170; - * GBKFreq[58][185] = 169; GBKFreq[47][165] = 168; GBKFreq[67][131] = - * 167; GBKFreq[94][40] = 166; GBKFreq[74][153] = 165; GBKFreq[79][142] - * = 164; GBKFreq[57][98] = 163; GBKFreq[1][164] = 162; GBKFreq[55][168] - * = 161; GBKFreq[13][141] = 160; GBKFreq[51][31] = 159; - * GBKFreq[57][178] = 158; GBKFreq[50][189] = 157; GBKFreq[60][167] = - * 156; GBKFreq[80][34] = 155; GBKFreq[109][80] = 154; GBKFreq[85][54] = - * 153; GBKFreq[69][183] = 152; GBKFreq[67][143] = 151; GBKFreq[47][120] - * = 150; GBKFreq[45][75] = 149; GBKFreq[82][98] = 148; GBKFreq[83][22] - * = 147; GBKFreq[13][103] = 146; GBKFreq[49][174] = 145; - * GBKFreq[57][181] = 144; GBKFreq[64][127] = 143; GBKFreq[61][131] = - * 142; GBKFreq[52][180] = 141; GBKFreq[74][134] = 140; GBKFreq[84][187] - * = 139; GBKFreq[81][189] = 138; GBKFreq[47][160] = 137; - * GBKFreq[66][148] = 136; GBKFreq[7][4] = 135; GBKFreq[85][134] = 134; - * GBKFreq[88][13] = 133; GBKFreq[88][80] = 132; GBKFreq[69][166] = 131; - * GBKFreq[86][18] = 130; GBKFreq[79][141] = 129; GBKFreq[50][108] = - * 128; GBKFreq[94][69] = 127; GBKFreq[81][110] = 126; GBKFreq[69][119] - * = 125; GBKFreq[72][161] = 124; GBKFreq[106][45] = 123; - * GBKFreq[73][124] = 122; GBKFreq[94][28] = 121; GBKFreq[63][174] = - * 120; GBKFreq[3][149] = 119; GBKFreq[24][160] = 118; GBKFreq[113][94] - * = 117; GBKFreq[56][138] = 116; GBKFreq[64][185] = 115; - * GBKFreq[86][56] = 114; GBKFreq[56][150] = 113; GBKFreq[110][55] = - * 112; GBKFreq[28][13] = 111; GBKFreq[54][190] = 110; GBKFreq[8][180] = - * 109; GBKFreq[73][149] = 108; GBKFreq[80][155] = 107; GBKFreq[83][172] - * = 106; GBKFreq[67][174] = 105; GBKFreq[64][180] = 104; - * GBKFreq[84][46] = 103; GBKFreq[91][74] = 102; GBKFreq[69][134] = 101; - * GBKFreq[61][107] = 100; GBKFreq[47][171] = 99; GBKFreq[59][51] = 98; - * GBKFreq[109][74] = 97; GBKFreq[64][174] = 96; GBKFreq[52][151] = 95; - * GBKFreq[51][176] = 94; GBKFreq[80][157] = 93; GBKFreq[94][31] = 92; - * GBKFreq[79][155] = 91; GBKFreq[72][174] = 90; GBKFreq[69][113] = 89; - * GBKFreq[83][167] = 88; GBKFreq[83][122] = 87; GBKFreq[8][178] = 86; - * GBKFreq[70][186] = 85; GBKFreq[59][153] = 84; GBKFreq[84][68] = 83; - * GBKFreq[79][39] = 82; GBKFreq[47][180] = 81; GBKFreq[88][53] = 80; - * GBKFreq[57][154] = 79; GBKFreq[47][153] = 78; GBKFreq[3][153] = 77; - * GBKFreq[76][134] = 76; GBKFreq[51][166] = 75; GBKFreq[58][176] = 74; - * GBKFreq[27][138] = 73; GBKFreq[73][126] = 72; GBKFreq[76][185] = 71; - * GBKFreq[52][186] = 70; GBKFreq[81][151] = 69; GBKFreq[26][50] = 68; - * GBKFreq[76][173] = 67; GBKFreq[106][56] = 66; GBKFreq[85][142] = 65; - * GBKFreq[11][103] = 64; GBKFreq[69][159] = 63; GBKFreq[53][142] = 62; - * GBKFreq[7][6] = 61; GBKFreq[84][59] = 60; GBKFreq[86][3] = 59; - * GBKFreq[64][144] = 58; GBKFreq[1][187] = 57; GBKFreq[82][128] = 56; - * GBKFreq[3][66] = 55; GBKFreq[68][133] = 54; GBKFreq[55][167] = 53; - * GBKFreq[52][130] = 52; GBKFreq[61][133] = 51; GBKFreq[72][181] = 50; - * GBKFreq[25][98] = 49; GBKFreq[84][149] = 48; GBKFreq[91][91] = 47; - * GBKFreq[47][188] = 46; GBKFreq[68][130] = 45; GBKFreq[22][44] = 44; - * GBKFreq[81][121] = 43; GBKFreq[72][140] = 42; GBKFreq[55][133] = 41; - * GBKFreq[55][185] = 40; GBKFreq[56][105] = 39; GBKFreq[60][30] = 38; - * GBKFreq[70][103] = 37; GBKFreq[62][141] = 36; GBKFreq[70][144] = 35; - * GBKFreq[59][111] = 34; GBKFreq[54][17] = 33; GBKFreq[18][190] = 32; - * GBKFreq[65][164] = 31; GBKFreq[83][125] = 30; GBKFreq[61][121] = 29; - * GBKFreq[48][13] = 28; GBKFreq[51][189] = 27; GBKFreq[65][68] = 26; - * GBKFreq[7][0] = 25; GBKFreq[76][188] = 24; GBKFreq[85][117] = 23; - * GBKFreq[45][33] = 22; GBKFreq[78][187] = 21; GBKFreq[106][48] = 20; - * GBKFreq[59][52] = 19; GBKFreq[86][185] = 18; GBKFreq[84][121] = 17; - * GBKFreq[82][189] = 16; GBKFreq[68][156] = 15; GBKFreq[55][125] = 14; - * GBKFreq[65][175] = 13; GBKFreq[7][140] = 12; GBKFreq[50][106] = 11; - * GBKFreq[59][124] = 10; GBKFreq[67][115] = 9; GBKFreq[82][114] = 8; - * GBKFreq[74][121] = 7; GBKFreq[106][69] = 6; GBKFreq[94][27] = 5; - * GBKFreq[78][98] = 4; GBKFreq[85][186] = 3; GBKFreq[108][90] = 2; - * GBKFreq[62][160] = 1; GBKFreq[60][169] = 0; - */ - KRFreq[31][43] = 600; - KRFreq[19][56] = 599; - KRFreq[38][46] = 598; - KRFreq[3][3] = 597; - KRFreq[29][77] = 596; - KRFreq[19][33] = 595; - KRFreq[30][0] = 594; - KRFreq[29][89] = 593; - KRFreq[31][26] = 592; - KRFreq[31][38] = 591; - KRFreq[32][85] = 590; - KRFreq[15][0] = 589; - KRFreq[16][54] = 588; - KRFreq[15][76] = 587; - KRFreq[31][25] = 586; - KRFreq[23][13] = 585; - KRFreq[28][34] = 584; - KRFreq[18][9] = 583; - KRFreq[29][37] = 582; - KRFreq[22][45] = 581; - KRFreq[19][46] = 580; - KRFreq[16][65] = 579; - KRFreq[23][5] = 578; - KRFreq[26][70] = 577; - KRFreq[31][53] = 576; - KRFreq[27][12] = 575; - KRFreq[30][67] = 574; - KRFreq[31][57] = 573; - KRFreq[20][20] = 572; - KRFreq[30][31] = 571; - KRFreq[20][72] = 570; - KRFreq[15][51] = 569; - KRFreq[3][8] = 568; - KRFreq[32][53] = 567; - KRFreq[27][85] = 566; - KRFreq[25][23] = 565; - KRFreq[15][44] = 564; - KRFreq[32][3] = 563; - KRFreq[31][68] = 562; - KRFreq[30][24] = 561; - KRFreq[29][49] = 560; - KRFreq[27][49] = 559; - KRFreq[23][23] = 558; - KRFreq[31][91] = 557; - KRFreq[31][46] = 556; - KRFreq[19][74] = 555; - KRFreq[27][27] = 554; - KRFreq[3][17] = 553; - KRFreq[20][38] = 552; - KRFreq[21][82] = 551; - KRFreq[28][25] = 550; - KRFreq[32][5] = 549; - KRFreq[31][23] = 548; - KRFreq[25][45] = 547; - KRFreq[32][87] = 546; - KRFreq[18][26] = 545; - KRFreq[24][10] = 544; - KRFreq[26][82] = 543; - KRFreq[15][89] = 542; - KRFreq[28][36] = 541; - KRFreq[28][31] = 540; - KRFreq[16][23] = 539; - KRFreq[16][77] = 538; - KRFreq[19][84] = 537; - KRFreq[23][72] = 536; - KRFreq[38][48] = 535; - KRFreq[23][2] = 534; - KRFreq[30][20] = 533; - KRFreq[38][47] = 532; - KRFreq[39][12] = 531; - KRFreq[23][21] = 530; - KRFreq[18][17] = 529; - KRFreq[30][87] = 528; - KRFreq[29][62] = 527; - KRFreq[29][87] = 526; - KRFreq[34][53] = 525; - KRFreq[32][29] = 524; - KRFreq[35][0] = 523; - KRFreq[24][43] = 522; - KRFreq[36][44] = 521; - KRFreq[20][30] = 520; - KRFreq[39][86] = 519; - KRFreq[22][14] = 518; - KRFreq[29][39] = 517; - KRFreq[28][38] = 516; - KRFreq[23][79] = 515; - KRFreq[24][56] = 514; - KRFreq[29][63] = 513; - KRFreq[31][45] = 512; - KRFreq[23][26] = 511; - KRFreq[15][87] = 510; - KRFreq[30][74] = 509; - KRFreq[24][69] = 508; - KRFreq[20][4] = 507; - KRFreq[27][50] = 506; - KRFreq[30][75] = 505; - KRFreq[24][13] = 504; - KRFreq[30][8] = 503; - KRFreq[31][6] = 502; - KRFreq[25][80] = 501; - KRFreq[36][8] = 500; - KRFreq[15][18] = 499; - KRFreq[39][23] = 498; - KRFreq[16][24] = 497; - KRFreq[31][89] = 496; - KRFreq[15][71] = 495; - KRFreq[15][57] = 494; - KRFreq[30][11] = 493; - KRFreq[15][36] = 492; - KRFreq[16][60] = 491; - KRFreq[24][45] = 490; - KRFreq[37][35] = 489; - KRFreq[24][87] = 488; - KRFreq[20][45] = 487; - KRFreq[31][90] = 486; - KRFreq[32][21] = 485; - KRFreq[19][70] = 484; - KRFreq[24][15] = 483; - KRFreq[26][92] = 482; - KRFreq[37][13] = 481; - KRFreq[39][2] = 480; - KRFreq[23][70] = 479; - KRFreq[27][25] = 478; - KRFreq[15][69] = 477; - KRFreq[19][61] = 476; - KRFreq[31][58] = 475; - KRFreq[24][57] = 474; - KRFreq[36][74] = 473; - KRFreq[21][6] = 472; - KRFreq[30][44] = 471; - KRFreq[15][91] = 470; - KRFreq[27][16] = 469; - KRFreq[29][42] = 468; - KRFreq[33][86] = 467; - KRFreq[29][41] = 466; - KRFreq[20][68] = 465; - KRFreq[25][47] = 464; - KRFreq[22][0] = 463; - KRFreq[18][14] = 462; - KRFreq[31][28] = 461; - KRFreq[15][2] = 460; - KRFreq[23][76] = 459; - KRFreq[38][32] = 458; - KRFreq[29][82] = 457; - KRFreq[21][86] = 456; - KRFreq[24][62] = 455; - KRFreq[31][64] = 454; - KRFreq[38][26] = 453; - KRFreq[32][86] = 452; - KRFreq[22][32] = 451; - KRFreq[19][59] = 450; - KRFreq[34][18] = 449; - KRFreq[18][54] = 448; - KRFreq[38][63] = 447; - KRFreq[36][23] = 446; - KRFreq[35][35] = 445; - KRFreq[32][62] = 444; - KRFreq[28][35] = 443; - KRFreq[27][13] = 442; - KRFreq[31][59] = 441; - KRFreq[29][29] = 440; - KRFreq[15][64] = 439; - KRFreq[26][84] = 438; - KRFreq[21][90] = 437; - KRFreq[20][24] = 436; - KRFreq[16][18] = 435; - KRFreq[22][23] = 434; - KRFreq[31][14] = 433; - KRFreq[15][1] = 432; - KRFreq[18][63] = 431; - KRFreq[19][10] = 430; - KRFreq[25][49] = 429; - KRFreq[36][57] = 428; - KRFreq[20][22] = 427; - KRFreq[15][15] = 426; - KRFreq[31][51] = 425; - KRFreq[24][60] = 424; - KRFreq[31][70] = 423; - KRFreq[15][7] = 422; - KRFreq[28][40] = 421; - KRFreq[18][41] = 420; - KRFreq[15][38] = 419; - KRFreq[32][0] = 418; - KRFreq[19][51] = 417; - KRFreq[34][62] = 416; - KRFreq[16][27] = 415; - KRFreq[20][70] = 414; - KRFreq[22][33] = 413; - KRFreq[26][73] = 412; - KRFreq[20][79] = 411; - KRFreq[23][6] = 410; - KRFreq[24][85] = 409; - KRFreq[38][51] = 408; - KRFreq[29][88] = 407; - KRFreq[38][55] = 406; - KRFreq[32][32] = 405; - KRFreq[27][18] = 404; - KRFreq[23][87] = 403; - KRFreq[35][6] = 402; - KRFreq[34][27] = 401; - KRFreq[39][35] = 400; - KRFreq[30][88] = 399; - KRFreq[32][92] = 398; - KRFreq[32][49] = 397; - KRFreq[24][61] = 396; - KRFreq[18][74] = 395; - KRFreq[23][77] = 394; - KRFreq[23][50] = 393; - KRFreq[23][32] = 392; - KRFreq[23][36] = 391; - KRFreq[38][38] = 390; - KRFreq[29][86] = 389; - KRFreq[36][15] = 388; - KRFreq[31][50] = 387; - KRFreq[15][86] = 386; - KRFreq[39][13] = 385; - KRFreq[34][26] = 384; - KRFreq[19][34] = 383; - KRFreq[16][3] = 382; - KRFreq[26][93] = 381; - KRFreq[19][67] = 380; - KRFreq[24][72] = 379; - KRFreq[29][17] = 378; - KRFreq[23][24] = 377; - KRFreq[25][19] = 376; - KRFreq[18][65] = 375; - KRFreq[30][78] = 374; - KRFreq[27][52] = 373; - KRFreq[22][18] = 372; - KRFreq[16][38] = 371; - KRFreq[21][26] = 370; - KRFreq[34][20] = 369; - KRFreq[15][42] = 368; - KRFreq[16][71] = 367; - KRFreq[17][17] = 366; - KRFreq[24][71] = 365; - KRFreq[18][84] = 364; - KRFreq[15][40] = 363; - KRFreq[31][62] = 362; - KRFreq[15][8] = 361; - KRFreq[16][69] = 360; - KRFreq[29][79] = 359; - KRFreq[38][91] = 358; - KRFreq[31][92] = 357; - KRFreq[20][77] = 356; - KRFreq[3][16] = 355; - KRFreq[27][87] = 354; - KRFreq[16][25] = 353; - KRFreq[36][33] = 352; - KRFreq[37][76] = 351; - KRFreq[30][12] = 350; - KRFreq[26][75] = 349; - KRFreq[25][14] = 348; - KRFreq[32][26] = 347; - KRFreq[23][22] = 346; - KRFreq[20][90] = 345; - KRFreq[19][8] = 344; - KRFreq[38][41] = 343; - KRFreq[34][2] = 342; - KRFreq[39][4] = 341; - KRFreq[27][89] = 340; - KRFreq[28][41] = 339; - KRFreq[28][44] = 338; - KRFreq[24][92] = 337; - KRFreq[34][65] = 336; - KRFreq[39][14] = 335; - KRFreq[21][38] = 334; - KRFreq[19][31] = 333; - KRFreq[37][39] = 332; - KRFreq[33][41] = 331; - KRFreq[38][4] = 330; - KRFreq[23][80] = 329; - KRFreq[25][24] = 328; - KRFreq[37][17] = 327; - KRFreq[22][16] = 326; - KRFreq[22][46] = 325; - KRFreq[33][91] = 324; - KRFreq[24][89] = 323; - KRFreq[30][52] = 322; - KRFreq[29][38] = 321; - KRFreq[38][85] = 320; - KRFreq[15][12] = 319; - KRFreq[27][58] = 318; - KRFreq[29][52] = 317; - KRFreq[37][38] = 316; - KRFreq[34][41] = 315; - KRFreq[31][65] = 314; - KRFreq[29][53] = 313; - KRFreq[22][47] = 312; - KRFreq[22][19] = 311; - KRFreq[26][0] = 310; - KRFreq[37][86] = 309; - KRFreq[35][4] = 308; - KRFreq[36][54] = 307; - KRFreq[20][76] = 306; - KRFreq[30][9] = 305; - KRFreq[30][33] = 304; - KRFreq[23][17] = 303; - KRFreq[23][33] = 302; - KRFreq[38][52] = 301; - KRFreq[15][19] = 300; - KRFreq[28][45] = 299; - KRFreq[29][78] = 298; - KRFreq[23][15] = 297; - KRFreq[33][5] = 296; - KRFreq[17][40] = 295; - KRFreq[30][83] = 294; - KRFreq[18][1] = 293; - KRFreq[30][81] = 292; - KRFreq[19][40] = 291; - KRFreq[24][47] = 290; - KRFreq[17][56] = 289; - KRFreq[39][80] = 288; - KRFreq[30][46] = 287; - KRFreq[16][61] = 286; - KRFreq[26][78] = 285; - KRFreq[26][57] = 284; - KRFreq[20][46] = 283; - KRFreq[25][15] = 282; - KRFreq[25][91] = 281; - KRFreq[21][83] = 280; - KRFreq[30][77] = 279; - KRFreq[35][30] = 278; - KRFreq[30][34] = 277; - KRFreq[20][69] = 276; - KRFreq[35][10] = 275; - KRFreq[29][70] = 274; - KRFreq[22][50] = 273; - KRFreq[18][0] = 272; - KRFreq[22][64] = 271; - KRFreq[38][65] = 270; - KRFreq[22][70] = 269; - KRFreq[24][58] = 268; - KRFreq[19][66] = 267; - KRFreq[30][59] = 266; - KRFreq[37][14] = 265; - KRFreq[16][56] = 264; - KRFreq[29][85] = 263; - KRFreq[31][15] = 262; - KRFreq[36][84] = 261; - KRFreq[39][15] = 260; - KRFreq[39][90] = 259; - KRFreq[18][12] = 258; - KRFreq[21][93] = 257; - KRFreq[24][66] = 256; - KRFreq[27][90] = 255; - KRFreq[25][90] = 254; - KRFreq[22][24] = 253; - KRFreq[36][67] = 252; - KRFreq[33][90] = 251; - KRFreq[15][60] = 250; - KRFreq[23][85] = 249; - KRFreq[34][1] = 248; - KRFreq[39][37] = 247; - KRFreq[21][18] = 246; - KRFreq[34][4] = 245; - KRFreq[28][33] = 244; - KRFreq[15][13] = 243; - KRFreq[32][22] = 242; - KRFreq[30][76] = 241; - KRFreq[20][21] = 240; - KRFreq[38][66] = 239; - KRFreq[32][55] = 238; - KRFreq[32][89] = 237; - KRFreq[25][26] = 236; - KRFreq[16][80] = 235; - KRFreq[15][43] = 234; - KRFreq[38][54] = 233; - KRFreq[39][68] = 232; - KRFreq[22][88] = 231; - KRFreq[21][84] = 230; - KRFreq[21][17] = 229; - KRFreq[20][28] = 228; - KRFreq[32][1] = 227; - KRFreq[33][87] = 226; - KRFreq[38][71] = 225; - KRFreq[37][47] = 224; - KRFreq[18][77] = 223; - KRFreq[37][58] = 222; - KRFreq[34][74] = 221; - KRFreq[32][54] = 220; - KRFreq[27][33] = 219; - KRFreq[32][93] = 218; - KRFreq[23][51] = 217; - KRFreq[20][57] = 216; - KRFreq[22][37] = 215; - KRFreq[39][10] = 214; - KRFreq[39][17] = 213; - KRFreq[33][4] = 212; - KRFreq[32][84] = 211; - KRFreq[34][3] = 210; - KRFreq[28][27] = 209; - KRFreq[15][79] = 208; - KRFreq[34][21] = 207; - KRFreq[34][69] = 206; - KRFreq[21][62] = 205; - KRFreq[36][24] = 204; - KRFreq[16][89] = 203; - KRFreq[18][48] = 202; - KRFreq[38][15] = 201; - KRFreq[36][58] = 200; - KRFreq[21][56] = 199; - KRFreq[34][48] = 198; - KRFreq[21][15] = 197; - KRFreq[39][3] = 196; - KRFreq[16][44] = 195; - KRFreq[18][79] = 194; - KRFreq[25][13] = 193; - KRFreq[29][47] = 192; - KRFreq[38][88] = 191; - KRFreq[20][71] = 190; - KRFreq[16][58] = 189; - KRFreq[35][57] = 188; - KRFreq[29][30] = 187; - KRFreq[29][23] = 186; - KRFreq[34][93] = 185; - KRFreq[30][85] = 184; - KRFreq[15][80] = 183; - KRFreq[32][78] = 182; - KRFreq[37][82] = 181; - KRFreq[22][40] = 180; - KRFreq[21][69] = 179; - KRFreq[26][85] = 178; - KRFreq[31][31] = 177; - KRFreq[28][64] = 176; - KRFreq[38][13] = 175; - KRFreq[25][2] = 174; - KRFreq[22][34] = 173; - KRFreq[28][28] = 172; - KRFreq[24][91] = 171; - KRFreq[33][74] = 170; - KRFreq[29][40] = 169; - KRFreq[15][77] = 168; - KRFreq[32][80] = 167; - KRFreq[30][41] = 166; - KRFreq[23][30] = 165; - KRFreq[24][63] = 164; - KRFreq[30][53] = 163; - KRFreq[39][70] = 162; - KRFreq[23][61] = 161; - KRFreq[37][27] = 160; - KRFreq[16][55] = 159; - KRFreq[22][74] = 158; - KRFreq[26][50] = 157; - KRFreq[16][10] = 156; - KRFreq[34][63] = 155; - KRFreq[35][14] = 154; - KRFreq[17][7] = 153; - KRFreq[15][59] = 152; - KRFreq[27][23] = 151; - KRFreq[18][70] = 150; - KRFreq[32][56] = 149; - KRFreq[37][87] = 148; - KRFreq[17][61] = 147; - KRFreq[18][83] = 146; - KRFreq[23][86] = 145; - KRFreq[17][31] = 144; - KRFreq[23][83] = 143; - KRFreq[35][2] = 142; - KRFreq[18][64] = 141; - KRFreq[27][43] = 140; - KRFreq[32][42] = 139; - KRFreq[25][76] = 138; - KRFreq[19][85] = 137; - KRFreq[37][81] = 136; - KRFreq[38][83] = 135; - KRFreq[35][7] = 134; - KRFreq[16][51] = 133; - KRFreq[27][22] = 132; - KRFreq[16][76] = 131; - KRFreq[22][4] = 130; - KRFreq[38][84] = 129; - KRFreq[17][83] = 128; - KRFreq[24][46] = 127; - KRFreq[33][15] = 126; - KRFreq[20][48] = 125; - KRFreq[17][30] = 124; - KRFreq[30][93] = 123; - KRFreq[28][11] = 122; - KRFreq[28][30] = 121; - KRFreq[15][62] = 120; - KRFreq[17][87] = 119; - KRFreq[32][81] = 118; - KRFreq[23][37] = 117; - KRFreq[30][22] = 116; - KRFreq[32][66] = 115; - KRFreq[33][78] = 114; - KRFreq[21][4] = 113; - KRFreq[31][17] = 112; - KRFreq[39][61] = 111; - KRFreq[18][76] = 110; - KRFreq[15][85] = 109; - KRFreq[31][47] = 108; - KRFreq[19][57] = 107; - KRFreq[23][55] = 106; - KRFreq[27][29] = 105; - KRFreq[29][46] = 104; - KRFreq[33][0] = 103; - KRFreq[16][83] = 102; - KRFreq[39][78] = 101; - KRFreq[32][77] = 100; - KRFreq[36][25] = 99; - KRFreq[34][19] = 98; - KRFreq[38][49] = 97; - KRFreq[19][25] = 96; - KRFreq[23][53] = 95; - KRFreq[28][43] = 94; - KRFreq[31][44] = 93; - KRFreq[36][34] = 92; - KRFreq[16][34] = 91; - KRFreq[35][1] = 90; - KRFreq[19][87] = 89; - KRFreq[18][53] = 88; - KRFreq[29][54] = 87; - KRFreq[22][41] = 86; - KRFreq[38][18] = 85; - KRFreq[22][2] = 84; - KRFreq[20][3] = 83; - KRFreq[39][69] = 82; - KRFreq[30][29] = 81; - KRFreq[28][19] = 80; - KRFreq[29][90] = 79; - KRFreq[17][86] = 78; - KRFreq[15][9] = 77; - KRFreq[39][73] = 76; - KRFreq[15][37] = 75; - KRFreq[35][40] = 74; - KRFreq[33][77] = 73; - KRFreq[27][86] = 72; - KRFreq[36][79] = 71; - KRFreq[23][18] = 70; - KRFreq[34][87] = 69; - KRFreq[39][24] = 68; - KRFreq[26][8] = 67; - KRFreq[33][48] = 66; - KRFreq[39][30] = 65; - KRFreq[33][28] = 64; - KRFreq[16][67] = 63; - KRFreq[31][78] = 62; - KRFreq[32][23] = 61; - KRFreq[24][55] = 60; - KRFreq[30][68] = 59; - KRFreq[18][60] = 58; - KRFreq[15][17] = 57; - KRFreq[23][34] = 56; - KRFreq[20][49] = 55; - KRFreq[15][78] = 54; - KRFreq[24][14] = 53; - KRFreq[19][41] = 52; - KRFreq[31][55] = 51; - KRFreq[21][39] = 50; - KRFreq[35][9] = 49; - KRFreq[30][15] = 48; - KRFreq[20][52] = 47; - KRFreq[35][71] = 46; - KRFreq[20][7] = 45; - KRFreq[29][72] = 44; - KRFreq[37][77] = 43; - KRFreq[22][35] = 42; - KRFreq[20][61] = 41; - KRFreq[31][60] = 40; - KRFreq[20][93] = 39; - KRFreq[27][92] = 38; - KRFreq[28][16] = 37; - KRFreq[36][26] = 36; - KRFreq[18][89] = 35; - KRFreq[21][63] = 34; - KRFreq[22][52] = 33; - KRFreq[24][65] = 32; - KRFreq[31][8] = 31; - KRFreq[31][49] = 30; - KRFreq[33][30] = 29; - KRFreq[37][15] = 28; - KRFreq[18][18] = 27; - KRFreq[25][50] = 26; - KRFreq[29][20] = 25; - KRFreq[35][48] = 24; - KRFreq[38][75] = 23; - KRFreq[26][83] = 22; - KRFreq[21][87] = 21; - KRFreq[27][71] = 20; - KRFreq[32][91] = 19; - KRFreq[25][73] = 18; - KRFreq[16][84] = 17; - KRFreq[25][31] = 16; - KRFreq[17][90] = 15; - KRFreq[18][40] = 14; - KRFreq[17][77] = 13; - KRFreq[17][35] = 12; - KRFreq[23][52] = 11; - KRFreq[23][35] = 10; - KRFreq[16][5] = 9; - KRFreq[23][58] = 8; - KRFreq[19][60] = 7; - KRFreq[30][32] = 6; - KRFreq[38][34] = 5; - KRFreq[23][4] = 4; - KRFreq[23][1] = 3; - KRFreq[27][57] = 2; - KRFreq[39][38] = 1; - KRFreq[32][33] = 0; - JPFreq[3][74] = 600; - JPFreq[3][45] = 599; - JPFreq[3][3] = 598; - JPFreq[3][24] = 597; - JPFreq[3][30] = 596; - JPFreq[3][42] = 595; - JPFreq[3][46] = 594; - JPFreq[3][39] = 593; - JPFreq[3][11] = 592; - JPFreq[3][37] = 591; - JPFreq[3][38] = 590; - JPFreq[3][31] = 589; - JPFreq[3][41] = 588; - JPFreq[3][5] = 587; - JPFreq[3][10] = 586; - JPFreq[3][75] = 585; - JPFreq[3][65] = 584; - JPFreq[3][72] = 583; - JPFreq[37][91] = 582; - JPFreq[0][27] = 581; - JPFreq[3][18] = 580; - JPFreq[3][22] = 579; - JPFreq[3][61] = 578; - JPFreq[3][14] = 577; - JPFreq[24][80] = 576; - JPFreq[4][82] = 575; - JPFreq[17][80] = 574; - JPFreq[30][44] = 573; - JPFreq[3][73] = 572; - JPFreq[3][64] = 571; - JPFreq[38][14] = 570; - JPFreq[33][70] = 569; - JPFreq[3][1] = 568; - JPFreq[3][16] = 567; - JPFreq[3][35] = 566; - JPFreq[3][40] = 565; - JPFreq[4][74] = 564; - JPFreq[4][24] = 563; - JPFreq[42][59] = 562; - JPFreq[3][7] = 561; - JPFreq[3][71] = 560; - JPFreq[3][12] = 559; - JPFreq[15][75] = 558; - JPFreq[3][20] = 557; - JPFreq[4][39] = 556; - JPFreq[34][69] = 555; - JPFreq[3][28] = 554; - JPFreq[35][24] = 553; - JPFreq[3][82] = 552; - JPFreq[28][47] = 551; - JPFreq[3][67] = 550; - JPFreq[37][16] = 549; - JPFreq[26][93] = 548; - JPFreq[4][1] = 547; - JPFreq[26][85] = 546; - JPFreq[31][14] = 545; - JPFreq[4][3] = 544; - JPFreq[4][72] = 543; - JPFreq[24][51] = 542; - JPFreq[27][51] = 541; - JPFreq[27][49] = 540; - JPFreq[22][77] = 539; - JPFreq[27][10] = 538; - JPFreq[29][68] = 537; - JPFreq[20][35] = 536; - JPFreq[41][11] = 535; - JPFreq[24][70] = 534; - JPFreq[36][61] = 533; - JPFreq[31][23] = 532; - JPFreq[43][16] = 531; - JPFreq[23][68] = 530; - JPFreq[32][15] = 529; - JPFreq[3][32] = 528; - JPFreq[19][53] = 527; - JPFreq[40][83] = 526; - JPFreq[4][14] = 525; - JPFreq[36][9] = 524; - JPFreq[4][73] = 523; - JPFreq[23][10] = 522; - JPFreq[3][63] = 521; - JPFreq[39][14] = 520; - JPFreq[3][78] = 519; - JPFreq[33][47] = 518; - JPFreq[21][39] = 517; - JPFreq[34][46] = 516; - JPFreq[36][75] = 515; - JPFreq[41][92] = 514; - JPFreq[37][93] = 513; - JPFreq[4][34] = 512; - JPFreq[15][86] = 511; - JPFreq[46][1] = 510; - JPFreq[37][65] = 509; - JPFreq[3][62] = 508; - JPFreq[32][73] = 507; - JPFreq[21][65] = 506; - JPFreq[29][75] = 505; - JPFreq[26][51] = 504; - JPFreq[3][34] = 503; - JPFreq[4][10] = 502; - JPFreq[30][22] = 501; - JPFreq[35][73] = 500; - JPFreq[17][82] = 499; - JPFreq[45][8] = 498; - JPFreq[27][73] = 497; - JPFreq[18][55] = 496; - JPFreq[25][2] = 495; - JPFreq[3][26] = 494; - JPFreq[45][46] = 493; - JPFreq[4][22] = 492; - JPFreq[4][40] = 491; - JPFreq[18][10] = 490; - JPFreq[32][9] = 489; - JPFreq[26][49] = 488; - JPFreq[3][47] = 487; - JPFreq[24][65] = 486; - JPFreq[4][76] = 485; - JPFreq[43][67] = 484; - JPFreq[3][9] = 483; - JPFreq[41][37] = 482; - JPFreq[33][68] = 481; - JPFreq[43][31] = 480; - JPFreq[19][55] = 479; - JPFreq[4][30] = 478; - JPFreq[27][33] = 477; - JPFreq[16][62] = 476; - JPFreq[36][35] = 475; - JPFreq[37][15] = 474; - JPFreq[27][70] = 473; - JPFreq[22][71] = 472; - JPFreq[33][45] = 471; - JPFreq[31][78] = 470; - JPFreq[43][59] = 469; - JPFreq[32][19] = 468; - JPFreq[17][28] = 467; - JPFreq[40][28] = 466; - JPFreq[20][93] = 465; - JPFreq[18][15] = 464; - JPFreq[4][23] = 463; - JPFreq[3][23] = 462; - JPFreq[26][64] = 461; - JPFreq[44][92] = 460; - JPFreq[17][27] = 459; - JPFreq[3][56] = 458; - JPFreq[25][38] = 457; - JPFreq[23][31] = 456; - JPFreq[35][43] = 455; - JPFreq[4][54] = 454; - JPFreq[35][19] = 453; - JPFreq[22][47] = 452; - JPFreq[42][0] = 451; - JPFreq[23][28] = 450; - JPFreq[46][33] = 449; - JPFreq[36][85] = 448; - JPFreq[31][12] = 447; - JPFreq[3][76] = 446; - JPFreq[4][75] = 445; - JPFreq[36][56] = 444; - JPFreq[4][64] = 443; - JPFreq[25][77] = 442; - JPFreq[15][52] = 441; - JPFreq[33][73] = 440; - JPFreq[3][55] = 439; - JPFreq[43][82] = 438; - JPFreq[27][82] = 437; - JPFreq[20][3] = 436; - JPFreq[40][51] = 435; - JPFreq[3][17] = 434; - JPFreq[27][71] = 433; - JPFreq[4][52] = 432; - JPFreq[44][48] = 431; - JPFreq[27][2] = 430; - JPFreq[17][39] = 429; - JPFreq[31][8] = 428; - JPFreq[44][54] = 427; - JPFreq[43][18] = 426; - JPFreq[43][77] = 425; - JPFreq[4][61] = 424; - JPFreq[19][91] = 423; - JPFreq[31][13] = 422; - JPFreq[44][71] = 421; - JPFreq[20][0] = 420; - JPFreq[23][87] = 419; - JPFreq[21][14] = 418; - JPFreq[29][13] = 417; - JPFreq[3][58] = 416; - JPFreq[26][18] = 415; - JPFreq[4][47] = 414; - JPFreq[4][18] = 413; - JPFreq[3][53] = 412; - JPFreq[26][92] = 411; - JPFreq[21][7] = 410; - JPFreq[4][37] = 409; - JPFreq[4][63] = 408; - JPFreq[36][51] = 407; - JPFreq[4][32] = 406; - JPFreq[28][73] = 405; - JPFreq[4][50] = 404; - JPFreq[41][60] = 403; - JPFreq[23][1] = 402; - JPFreq[36][92] = 401; - JPFreq[15][41] = 400; - JPFreq[21][71] = 399; - JPFreq[41][30] = 398; - JPFreq[32][76] = 397; - JPFreq[17][34] = 396; - JPFreq[26][15] = 395; - JPFreq[26][25] = 394; - JPFreq[31][77] = 393; - JPFreq[31][3] = 392; - JPFreq[46][34] = 391; - JPFreq[27][84] = 390; - JPFreq[23][8] = 389; - JPFreq[16][0] = 388; - JPFreq[28][80] = 387; - JPFreq[26][54] = 386; - JPFreq[33][18] = 385; - JPFreq[31][20] = 384; - JPFreq[31][62] = 383; - JPFreq[30][41] = 382; - JPFreq[33][30] = 381; - JPFreq[45][45] = 380; - JPFreq[37][82] = 379; - JPFreq[15][33] = 378; - JPFreq[20][12] = 377; - JPFreq[18][5] = 376; - JPFreq[28][86] = 375; - JPFreq[30][19] = 374; - JPFreq[42][43] = 373; - JPFreq[36][31] = 372; - JPFreq[17][93] = 371; - JPFreq[4][15] = 370; - JPFreq[21][20] = 369; - JPFreq[23][21] = 368; - JPFreq[28][72] = 367; - JPFreq[4][20] = 366; - JPFreq[26][55] = 365; - JPFreq[21][5] = 364; - JPFreq[19][16] = 363; - JPFreq[23][64] = 362; - JPFreq[40][59] = 361; - JPFreq[37][26] = 360; - JPFreq[26][56] = 359; - JPFreq[4][12] = 358; - JPFreq[33][71] = 357; - JPFreq[32][39] = 356; - JPFreq[38][40] = 355; - JPFreq[22][74] = 354; - JPFreq[3][25] = 353; - JPFreq[15][48] = 352; - JPFreq[41][82] = 351; - JPFreq[41][9] = 350; - JPFreq[25][48] = 349; - JPFreq[31][71] = 348; - JPFreq[43][29] = 347; - JPFreq[26][80] = 346; - JPFreq[4][5] = 345; - JPFreq[18][71] = 344; - JPFreq[29][0] = 343; - JPFreq[43][43] = 342; - JPFreq[23][81] = 341; - JPFreq[4][42] = 340; - JPFreq[44][28] = 339; - JPFreq[23][93] = 338; - JPFreq[17][81] = 337; - JPFreq[25][25] = 336; - JPFreq[41][23] = 335; - JPFreq[34][35] = 334; - JPFreq[4][53] = 333; - JPFreq[28][36] = 332; - JPFreq[4][41] = 331; - JPFreq[25][60] = 330; - JPFreq[23][20] = 329; - JPFreq[3][43] = 328; - JPFreq[24][79] = 327; - JPFreq[29][41] = 326; - JPFreq[30][83] = 325; - JPFreq[3][50] = 324; - JPFreq[22][18] = 323; - JPFreq[18][3] = 322; - JPFreq[39][30] = 321; - JPFreq[4][28] = 320; - JPFreq[21][64] = 319; - JPFreq[4][68] = 318; - JPFreq[17][71] = 317; - JPFreq[27][0] = 316; - JPFreq[39][28] = 315; - JPFreq[30][13] = 314; - JPFreq[36][70] = 313; - JPFreq[20][82] = 312; - JPFreq[33][38] = 311; - JPFreq[44][87] = 310; - JPFreq[34][45] = 309; - JPFreq[4][26] = 308; - JPFreq[24][44] = 307; - JPFreq[38][67] = 306; - JPFreq[38][6] = 305; - JPFreq[30][68] = 304; - JPFreq[15][89] = 303; - JPFreq[24][93] = 302; - JPFreq[40][41] = 301; - JPFreq[38][3] = 300; - JPFreq[28][23] = 299; - JPFreq[26][17] = 298; - JPFreq[4][38] = 297; - JPFreq[22][78] = 296; - JPFreq[15][37] = 295; - JPFreq[25][85] = 294; - JPFreq[4][9] = 293; - JPFreq[4][7] = 292; - JPFreq[27][53] = 291; - JPFreq[39][29] = 290; - JPFreq[41][43] = 289; - JPFreq[25][62] = 288; - JPFreq[4][48] = 287; - JPFreq[28][28] = 286; - JPFreq[21][40] = 285; - JPFreq[36][73] = 284; - JPFreq[26][39] = 283; - JPFreq[22][54] = 282; - JPFreq[33][5] = 281; - JPFreq[19][21] = 280; - JPFreq[46][31] = 279; - JPFreq[20][64] = 278; - JPFreq[26][63] = 277; - JPFreq[22][23] = 276; - JPFreq[25][81] = 275; - JPFreq[4][62] = 274; - JPFreq[37][31] = 273; - JPFreq[40][52] = 272; - JPFreq[29][79] = 271; - JPFreq[41][48] = 270; - JPFreq[31][57] = 269; - JPFreq[32][92] = 268; - JPFreq[36][36] = 267; - JPFreq[27][7] = 266; - JPFreq[35][29] = 265; - JPFreq[37][34] = 264; - JPFreq[34][42] = 263; - JPFreq[27][15] = 262; - JPFreq[33][27] = 261; - JPFreq[31][38] = 260; - JPFreq[19][79] = 259; - JPFreq[4][31] = 258; - JPFreq[4][66] = 257; - JPFreq[17][32] = 256; - JPFreq[26][67] = 255; - JPFreq[16][30] = 254; - JPFreq[26][46] = 253; - JPFreq[24][26] = 252; - JPFreq[35][10] = 251; - JPFreq[18][37] = 250; - JPFreq[3][19] = 249; - JPFreq[33][69] = 248; - JPFreq[31][9] = 247; - JPFreq[45][29] = 246; - JPFreq[3][15] = 245; - JPFreq[18][54] = 244; - JPFreq[3][44] = 243; - JPFreq[31][29] = 242; - JPFreq[18][45] = 241; - JPFreq[38][28] = 240; - JPFreq[24][12] = 239; - JPFreq[35][82] = 238; - JPFreq[17][43] = 237; - JPFreq[28][9] = 236; - JPFreq[23][25] = 235; - JPFreq[44][37] = 234; - JPFreq[23][75] = 233; - JPFreq[23][92] = 232; - JPFreq[0][24] = 231; - JPFreq[19][74] = 230; - JPFreq[45][32] = 229; - JPFreq[16][72] = 228; - JPFreq[16][93] = 227; - JPFreq[45][13] = 226; - JPFreq[24][8] = 225; - JPFreq[25][47] = 224; - JPFreq[28][26] = 223; - JPFreq[43][81] = 222; - JPFreq[32][71] = 221; - JPFreq[18][41] = 220; - JPFreq[26][62] = 219; - JPFreq[41][24] = 218; - JPFreq[40][11] = 217; - JPFreq[43][57] = 216; - JPFreq[34][53] = 215; - JPFreq[20][32] = 214; - JPFreq[34][43] = 213; - JPFreq[41][91] = 212; - JPFreq[29][57] = 211; - JPFreq[15][43] = 210; - JPFreq[22][89] = 209; - JPFreq[33][83] = 208; - JPFreq[43][20] = 207; - JPFreq[25][58] = 206; - JPFreq[30][30] = 205; - JPFreq[4][56] = 204; - JPFreq[17][64] = 203; - JPFreq[23][0] = 202; - JPFreq[44][12] = 201; - JPFreq[25][37] = 200; - JPFreq[35][13] = 199; - JPFreq[20][30] = 198; - JPFreq[21][84] = 197; - JPFreq[29][14] = 196; - JPFreq[30][5] = 195; - JPFreq[37][2] = 194; - JPFreq[4][78] = 193; - JPFreq[29][78] = 192; - JPFreq[29][84] = 191; - JPFreq[32][86] = 190; - JPFreq[20][68] = 189; - JPFreq[30][39] = 188; - JPFreq[15][69] = 187; - JPFreq[4][60] = 186; - JPFreq[20][61] = 185; - JPFreq[41][67] = 184; - JPFreq[16][35] = 183; - JPFreq[36][57] = 182; - JPFreq[39][80] = 181; - JPFreq[4][59] = 180; - JPFreq[4][44] = 179; - JPFreq[40][54] = 178; - JPFreq[30][8] = 177; - JPFreq[44][30] = 176; - JPFreq[31][93] = 175; - JPFreq[31][47] = 174; - JPFreq[16][70] = 173; - JPFreq[21][0] = 172; - JPFreq[17][35] = 171; - JPFreq[21][67] = 170; - JPFreq[44][18] = 169; - JPFreq[36][29] = 168; - JPFreq[18][67] = 167; - JPFreq[24][28] = 166; - JPFreq[36][24] = 165; - JPFreq[23][5] = 164; - JPFreq[31][65] = 163; - JPFreq[26][59] = 162; - JPFreq[28][2] = 161; - JPFreq[39][69] = 160; - JPFreq[42][40] = 159; - JPFreq[37][80] = 158; - JPFreq[15][66] = 157; - JPFreq[34][38] = 156; - JPFreq[28][48] = 155; - JPFreq[37][77] = 154; - JPFreq[29][34] = 153; - JPFreq[33][12] = 152; - JPFreq[4][65] = 151; - JPFreq[30][31] = 150; - JPFreq[27][92] = 149; - JPFreq[4][2] = 148; - JPFreq[4][51] = 147; - JPFreq[23][77] = 146; - JPFreq[4][35] = 145; - JPFreq[3][13] = 144; - JPFreq[26][26] = 143; - JPFreq[44][4] = 142; - JPFreq[39][53] = 141; - JPFreq[20][11] = 140; - JPFreq[40][33] = 139; - JPFreq[45][7] = 138; - JPFreq[4][70] = 137; - JPFreq[3][49] = 136; - JPFreq[20][59] = 135; - JPFreq[21][12] = 134; - JPFreq[33][53] = 133; - JPFreq[20][14] = 132; - JPFreq[37][18] = 131; - JPFreq[18][17] = 130; - JPFreq[36][23] = 129; - JPFreq[18][57] = 128; - JPFreq[26][74] = 127; - JPFreq[35][2] = 126; - JPFreq[38][58] = 125; - JPFreq[34][68] = 124; - JPFreq[29][81] = 123; - JPFreq[20][69] = 122; - JPFreq[39][86] = 121; - JPFreq[4][16] = 120; - JPFreq[16][49] = 119; - JPFreq[15][72] = 118; - JPFreq[26][35] = 117; - JPFreq[32][14] = 116; - JPFreq[40][90] = 115; - JPFreq[33][79] = 114; - JPFreq[35][4] = 113; - JPFreq[23][33] = 112; - JPFreq[19][19] = 111; - JPFreq[31][41] = 110; - JPFreq[44][1] = 109; - JPFreq[22][56] = 108; - JPFreq[31][27] = 107; - JPFreq[32][18] = 106; - JPFreq[27][32] = 105; - JPFreq[37][39] = 104; - JPFreq[42][11] = 103; - JPFreq[29][71] = 102; - JPFreq[32][58] = 101; - JPFreq[46][10] = 100; - JPFreq[17][30] = 99; - JPFreq[38][15] = 98; - JPFreq[29][60] = 97; - JPFreq[4][11] = 96; - JPFreq[38][31] = 95; - JPFreq[40][79] = 94; - JPFreq[28][49] = 93; - JPFreq[28][84] = 92; - JPFreq[26][77] = 91; - JPFreq[22][32] = 90; - JPFreq[33][17] = 89; - JPFreq[23][18] = 88; - JPFreq[32][64] = 87; - JPFreq[4][6] = 86; - JPFreq[33][51] = 85; - JPFreq[44][77] = 84; - JPFreq[29][5] = 83; - JPFreq[46][25] = 82; - JPFreq[19][58] = 81; - JPFreq[4][46] = 80; - JPFreq[15][71] = 79; - JPFreq[18][58] = 78; - JPFreq[26][45] = 77; - JPFreq[45][66] = 76; - JPFreq[34][10] = 75; - JPFreq[19][37] = 74; - JPFreq[33][65] = 73; - JPFreq[44][52] = 72; - JPFreq[16][38] = 71; - JPFreq[36][46] = 70; - JPFreq[20][26] = 69; - JPFreq[30][37] = 68; - JPFreq[4][58] = 67; - JPFreq[43][2] = 66; - JPFreq[30][18] = 65; - JPFreq[19][35] = 64; - JPFreq[15][68] = 63; - JPFreq[3][36] = 62; - JPFreq[35][40] = 61; - JPFreq[36][32] = 60; - JPFreq[37][14] = 59; - JPFreq[17][11] = 58; - JPFreq[19][78] = 57; - JPFreq[37][11] = 56; - JPFreq[28][63] = 55; - JPFreq[29][61] = 54; - JPFreq[33][3] = 53; - JPFreq[41][52] = 52; - JPFreq[33][63] = 51; - JPFreq[22][41] = 50; - JPFreq[4][19] = 49; - JPFreq[32][41] = 48; - JPFreq[24][4] = 47; - JPFreq[31][28] = 46; - JPFreq[43][30] = 45; - JPFreq[17][3] = 44; - JPFreq[43][70] = 43; - JPFreq[34][19] = 42; - JPFreq[20][77] = 41; - JPFreq[18][83] = 40; - JPFreq[17][15] = 39; - JPFreq[23][61] = 38; - JPFreq[40][27] = 37; - JPFreq[16][48] = 36; - JPFreq[39][78] = 35; - JPFreq[41][53] = 34; - JPFreq[40][91] = 33; - JPFreq[40][72] = 32; - JPFreq[18][52] = 31; - JPFreq[35][66] = 30; - JPFreq[39][93] = 29; - JPFreq[19][48] = 28; - JPFreq[26][36] = 27; - JPFreq[27][25] = 26; - JPFreq[42][71] = 25; - JPFreq[42][85] = 24; - JPFreq[26][48] = 23; - JPFreq[28][15] = 22; - JPFreq[3][66] = 21; - JPFreq[25][24] = 20; - JPFreq[27][43] = 19; - JPFreq[27][78] = 18; - JPFreq[45][43] = 17; - JPFreq[27][72] = 16; - JPFreq[40][29] = 15; - JPFreq[41][0] = 14; - JPFreq[19][57] = 13; - JPFreq[15][59] = 12; - JPFreq[29][29] = 11; - JPFreq[4][25] = 10; - JPFreq[21][42] = 9; - JPFreq[23][35] = 8; - JPFreq[33][1] = 7; - JPFreq[4][57] = 6; - JPFreq[17][60] = 5; - JPFreq[25][19] = 4; - JPFreq[22][65] = 3; - JPFreq[42][29] = 2; - JPFreq[27][66] = 1; - JPFreq[26][89] = 0; - } -} - -class Encoding { - // Supported Encoding Types - - public static int GB2312 = 0; - - public static int GBK = 1; - - public static int GB18030 = 2; - - public static int HZ = 3; - - public static int BIG5 = 4; - - public static int CNS11643 = 5; - - public static int UTF8 = 6; - - public static int UTF8T = 7; - - public static int UTF8S = 8; - - public static int UNICODE = 9; - - public static int UNICODET = 10; - - public static int UNICODES = 11; - - public static int ISO2022CN = 12; - - public static int ISO2022CN_CNS = 13; - - public static int ISO2022CN_GB = 14; - - public static int EUC_KR = 15; - - public static int CP949 = 16; - - public static int ISO2022KR = 17; - - public static int JOHAB = 18; - - public static int SJIS = 19; - - public static int EUC_JP = 20; - - public static int ISO2022JP = 21; - - public static int ASCII = 22; - - public static int OTHER = 23; - - public static int TOTALTYPES = 24; - - public final static int SIMP = 0; - - public final static int TRAD = 1; - - // Names of the encodings as understood by Java - public static String[] javaname; - - // Names of the encodings for human viewing - public static String[] nicename; - - // Names of charsets as used in charset parameter of HTML Meta tag - public static String[] htmlname; - - // Constructor - public Encoding() { - javaname = new String[TOTALTYPES]; - nicename = new String[TOTALTYPES]; - htmlname = new String[TOTALTYPES]; - // Assign encoding names - javaname[GB2312] = "GB2312"; - javaname[GBK] = "GBK"; - javaname[GB18030] = "GB18030"; - javaname[HZ] = "ASCII"; // What to put here? Sun doesn't support HZ - javaname[ISO2022CN_GB] = "ISO2022CN_GB"; - javaname[BIG5] = "BIG5"; - javaname[CNS11643] = "EUC-TW"; - javaname[ISO2022CN_CNS] = "ISO2022CN_CNS"; - javaname[ISO2022CN] = "ISO2022CN"; - javaname[UTF8] = "UTF-8"; - javaname[UTF8T] = "UTF-8"; - javaname[UTF8S] = "UTF-8"; - javaname[UNICODE] = "Unicode"; - javaname[UNICODET] = "Unicode"; - javaname[UNICODES] = "Unicode"; - javaname[EUC_KR] = "EUC_KR"; - javaname[CP949] = "MS949"; - javaname[ISO2022KR] = "ISO2022KR"; - javaname[JOHAB] = "Johab"; - javaname[SJIS] = "SJIS"; - javaname[EUC_JP] = "EUC_JP"; - javaname[ISO2022JP] = "ISO2022JP"; - javaname[ASCII] = "ASCII"; - javaname[OTHER] = "ISO8859_1"; - // Assign encoding names - htmlname[GB2312] = "GB2312"; - htmlname[GBK] = "GBK"; - htmlname[GB18030] = "GB18030"; - htmlname[HZ] = "HZ-GB-2312"; - htmlname[ISO2022CN_GB] = "ISO-2022-CN-EXT"; - htmlname[BIG5] = "BIG5"; - htmlname[CNS11643] = "EUC-TW"; - htmlname[ISO2022CN_CNS] = "ISO-2022-CN-EXT"; - htmlname[ISO2022CN] = "ISO-2022-CN"; - htmlname[UTF8] = "UTF-8"; - htmlname[UTF8T] = "UTF-8"; - htmlname[UTF8S] = "UTF-8"; - htmlname[UNICODE] = "UTF-16"; - htmlname[UNICODET] = "UTF-16"; - htmlname[UNICODES] = "UTF-16"; - htmlname[EUC_KR] = "EUC-KR"; - htmlname[CP949] = "x-windows-949"; - htmlname[ISO2022KR] = "ISO-2022-KR"; - htmlname[JOHAB] = "x-Johab"; - htmlname[SJIS] = "Shift_JIS"; - htmlname[EUC_JP] = "EUC-JP"; - htmlname[ISO2022JP] = "ISO-2022-JP"; - htmlname[ASCII] = "ASCII"; - htmlname[OTHER] = "ISO8859-1"; - // Assign Human readable names - nicename[GB2312] = "GB-2312"; - nicename[GBK] = "GBK"; - nicename[GB18030] = "GB18030"; - nicename[HZ] = "HZ"; - nicename[ISO2022CN_GB] = "ISO2022CN-GB"; - nicename[BIG5] = "Big5"; - nicename[CNS11643] = "CNS11643"; - nicename[ISO2022CN_CNS] = "ISO2022CN-CNS"; - nicename[ISO2022CN] = "ISO2022 CN"; - nicename[UTF8] = "UTF-8"; - nicename[UTF8T] = "UTF-8 (Trad)"; - nicename[UTF8S] = "UTF-8 (Simp)"; - nicename[UNICODE] = "Unicode"; - nicename[UNICODET] = "Unicode (Trad)"; - nicename[UNICODES] = "Unicode (Simp)"; - nicename[EUC_KR] = "EUC-KR"; - nicename[CP949] = "CP949"; - nicename[ISO2022KR] = "ISO 2022 KR"; - nicename[JOHAB] = "Johab"; - nicename[SJIS] = "Shift-JIS"; - nicename[EUC_JP] = "EUC-JP"; - nicename[ISO2022JP] = "ISO 2022 JP"; - nicename[ASCII] = "ASCII"; - nicename[OTHER] = "OTHER"; - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; + +/** + * (Detect encoding .) Copyright (C) (2009) (Fluck,ACC http://androidos.cc/dev ) + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * @author Billows.Van + * @since Create on 2010-01-27 11:19:00 + * @version 1.0 + */ +public class EncodingDetect extends Encoding { + + public static void main(String argc[]) { + if (argc.length == 0) { + System.out.println("Usage: EncodingDetect ... [-d]"); + System.exit(1); + } + EncodingDetect sinodetector; + int result = OTHER; + int i; + sinodetector = new EncodingDetect(); + for (i = 0; i < argc.length; i++) { + if (argc[i].startsWith("http://") == true) { + try { + result = sinodetector.detectEncoding(new URL(argc[i])); + } catch (Exception e) { + System.err.println("Bad URL " + e.toString()); + } + } else if (argc[i].equals("-d")) { + sinodetector.debug = true; + continue; + } else { + result = sinodetector.detectEncoding(new File(argc[i])); + } + System.out.println(nicename[result]); + } + } + + // Frequency tables to hold the GB, Big5, and EUC-TW character + // frequencies + int GBFreq[][]; + + int GBKFreq[][]; + + int Big5Freq[][]; + + int Big5PFreq[][]; + + int EUC_TWFreq[][]; + + int KRFreq[][]; + + int JPFreq[][]; + + // int UnicodeFreq[94][128]; + // public static String[] nicename; + // public static String[] codings; + public boolean debug; + + public EncodingDetect() { + super(); + debug = false; + GBFreq = new int[94][94]; + GBKFreq = new int[126][191]; + Big5Freq = new int[94][158]; + Big5PFreq = new int[126][191]; + EUC_TWFreq = new int[94][94]; + KRFreq = new int[94][94]; + JPFreq = new int[94][94]; + // Initialize the Frequency Table for GB, GBK, Big5, EUC-TW, KR, JP + initialize_frequencies(); + } + + /** + * Function : detectEncoding Aruguments: URL Returns : One of the encodings + * from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, or OTHER) + * Description: This function looks at the URL contents and assigns it a + * probability score for each encoding type. The encoding type with the + * highest probability is returned. + */ + public int detectEncoding(URL testurl) { + byte[] rawtext = new byte[10000]; + int bytesread = 0, byteoffset = 0; + int guess = OTHER; + InputStream chinesestream; + try { + chinesestream = testurl.openStream(); + while ((bytesread = chinesestream.read(rawtext, byteoffset, rawtext.length - byteoffset)) > 0) { + byteoffset += bytesread; + } + ; + chinesestream.close(); + guess = detectEncoding(rawtext); + } catch (Exception e) { + System.err.println("Error loading or using URL " + e.toString()); + guess = -1; + } + return guess; + } + + /** + * Function : detectEncoding Aruguments: File Returns : One of the encodings + * from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, or OTHER) + * Description: This function looks at the file and assigns it a probability + * score for each encoding type. The encoding type with the highest + * probability is returned. + */ + public int detectEncoding(File testfile) { + FileInputStream chinesefile; + byte[] rawtext; + rawtext = new byte[(int) testfile.length()]; + try { + chinesefile = new FileInputStream(testfile); + chinesefile.read(rawtext); + chinesefile.close(); + } catch (Exception e) { + System.err.println("Error: " + e); + e.printStackTrace(); + } + return detectEncoding(rawtext); + } + + /** + * Function : detectEncoding Aruguments: byte array Returns : One of the + * encodings from the Encoding enumeration (GB2312, HZ, BIG5, EUC_TW, ASCII, + * or OTHER) Description: This function looks at the byte array and assigns + * it a probability score for each encoding type. The encoding type with the + * highest probability is returned. + */ + public int detectEncoding(byte[] rawtext) { + int[] scores; + int index, maxscore = 0; + int encoding_guess = OTHER; + scores = new int[TOTALTYPES]; + // Assign Scores + scores[GB2312] = gb2312_probability(rawtext); + scores[GBK] = gbk_probability(rawtext); + scores[GB18030] = gb18030_probability(rawtext); + scores[HZ] = hz_probability(rawtext); + scores[BIG5] = big5_probability(rawtext); + scores[CNS11643] = euc_tw_probability(rawtext); + scores[ISO2022CN] = iso_2022_cn_probability(rawtext); + scores[UTF8] = utf8_probability(rawtext); + scores[UNICODE] = utf16_probability(rawtext); + scores[EUC_KR] = euc_kr_probability(rawtext); + scores[CP949] = cp949_probability(rawtext); + scores[JOHAB] = 0; + scores[ISO2022KR] = iso_2022_kr_probability(rawtext); + scores[ASCII] = ascii_probability(rawtext); + scores[SJIS] = sjis_probability(rawtext); + scores[EUC_JP] = euc_jp_probability(rawtext); + scores[ISO2022JP] = iso_2022_jp_probability(rawtext); + scores[UNICODET] = 0; + scores[UNICODES] = 0; + scores[ISO2022CN_GB] = 0; + scores[ISO2022CN_CNS] = 0; + scores[OTHER] = 0; + // Tabulate Scores + for (index = 0; index < TOTALTYPES; index++) { + if (debug) { + System.err.println("Encoding " + nicename[index] + " score " + scores[index]); + } + if (scores[index] > maxscore) { + encoding_guess = index; + maxscore = scores[index]; + } + } + // Return OTHER if nothing scored above 50 + if (maxscore <= 50) { + encoding_guess = OTHER; + } + return encoding_guess; + } + + /* + * Function: gb2312_probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses GB-2312 + * encoding + */ + int gb2312_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, gbchars = 1; + long gbfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 && (byte) 0xA1 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0xFE) { + gbchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + if (GBFreq[row][column] != 0) { + gbfreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + // In GB high-freq character range + gbfreq += 200; + } + } + i++; + } + } + rangeval = 50 * ((float) gbchars / (float) dbchars); + freqval = 50 * ((float) gbfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + /* + * Function: gbk_probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses GBK + * encoding + */ + int gbk_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, gbchars = 1; + long gbfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 + && // Original + // GB + // range + (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { + gbchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + // System.out.println("original row " + row + " column " + + // column); + if (GBFreq[row][column] != 0) { + gbfreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + gbfreq += 200; + } + } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE + && // Extended + // GB + // range + (((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) + || ((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E))) { + gbchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0x81; + if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { + column = rawtext[i + 1] - 0x40; + } else { + column = rawtext[i + 1] + 256 - 0x40; + } + // System.out.println("extended row " + row + " column " + + // column + " rawtext[i] " + rawtext[i]); + if (GBKFreq[row][column] != 0) { + gbfreq += GBKFreq[row][column]; + } + } + i++; + } + } + rangeval = 50 * ((float) gbchars / (float) dbchars); + freqval = 50 * ((float) gbfreq / (float) totalfreq); + // For regular GB files, this would give the same score, so I handicap + // it slightly + return (int) (rangeval + freqval) - 1; + } + + /* + * Function: gb18030_probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses GBK + * encoding + */ + int gb18030_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, gbchars = 1; + long gbfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF7 + && // Original + // GB + // range + i + 1 < rawtextlen && (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { + gbchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + // System.out.println("original row " + row + " column " + + // column); + if (GBFreq[row][column] != 0) { + gbfreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + gbfreq += 200; + } + } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE + && // Extended + // GB + // range + i + 1 < rawtextlen && (((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) + || ((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E))) { + gbchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0x81; + if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { + column = rawtext[i + 1] - 0x40; + } else { + column = rawtext[i + 1] + 256 - 0x40; + } + // System.out.println("extended row " + row + " column " + + // column + " rawtext[i] " + rawtext[i]); + if (GBKFreq[row][column] != 0) { + gbfreq += GBKFreq[row][column]; + } + } else if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE + && // Extended + // GB + // range + i + 3 < rawtextlen && (byte) 0x30 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x39 + && (byte) 0x81 <= rawtext[i + 2] && rawtext[i + 2] <= (byte) 0xFE + && (byte) 0x30 <= rawtext[i + 3] && rawtext[i + 3] <= (byte) 0x39) { + gbchars++; + /* + * totalfreq += 500; row = rawtext[i] + 256 - 0x81; if (0x40 + * <= rawtext[i+1] && rawtext[i+1] <= 0x7E) { column = + * rawtext[i+1] - 0x40; } else { column = rawtext[i+1] + 256 + * - 0x40; } //System.out.println("extended row " + row + " + * column " + column + " rawtext[i] " + rawtext[i]); if + * (GBKFreq[row][column] != 0) { gbfreq += + * GBKFreq[row][column]; } + */ + } + i++; + } + } + rangeval = 50 * ((float) gbchars / (float) dbchars); + freqval = 50 * ((float) gbfreq / (float) totalfreq); + // For regular GB files, this would give the same score, so I handicap + // it slightly + return (int) (rangeval + freqval) - 1; + } + + /* + * Function: hz_probability Argument: byte array Returns : number from 0 to + * 100 representing probability text in array uses HZ encoding + */ + @SuppressWarnings("unused") + int hz_probability(byte[] rawtext) { + int i, rawtextlen; + int hzchars = 0, dbchars = 1; + long hzfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int hzstart = 0, hzend = 0; + int row, column; + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen; i++) { + if (rawtext[i] == '~') { + if (rawtext[i + 1] == '{') { + hzstart++; + i += 2; + while (i < rawtextlen - 1) { + if (rawtext[i] == 0x0A || rawtext[i] == 0x0D) { + break; + } else if (rawtext[i] == '~' && rawtext[i + 1] == '}') { + hzend++; + i++; + break; + } else if ((0x21 <= rawtext[i] && rawtext[i] <= 0x77) + && (0x21 <= rawtext[i + 1] && rawtext[i + 1] <= 0x77)) { + hzchars += 2; + row = rawtext[i] - 0x21; + column = rawtext[i + 1] - 0x21; + totalfreq += 500; + if (GBFreq[row][column] != 0) { + hzfreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + hzfreq += 200; + } + } else if ((0xA1 <= rawtext[i] && rawtext[i] <= 0xF7) + && (0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= 0xF7)) { + hzchars += 2; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + totalfreq += 500; + if (GBFreq[row][column] != 0) { + hzfreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + hzfreq += 200; + } + } + dbchars += 2; + i += 2; + } + } else if (rawtext[i + 1] == '}') { + hzend++; + i++; + } else if (rawtext[i + 1] == '~') { + i++; + } + } + } + if (hzstart > 4) { + rangeval = 50; + } else if (hzstart > 1) { + rangeval = 41; + } else if (hzstart > 0) { // Only 39 in case the sequence happened to + // occur + rangeval = 39; // in otherwise non-Hz text + } else { + rangeval = 0; + } + freqval = 50 * ((float) hzfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + /** + * Function: big5_probability Argument: byte array Returns : number from 0 + * to 100 representing probability text in array uses Big5 encoding + */ + int big5_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, bfchars = 1; + float rangeval = 0, freqval = 0; + long bffreq = 0, totalfreq = 1; + int row, column; + // Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xF9 + && (((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E) + || ((byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE))) { + bfchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { + column = rawtext[i + 1] - 0x40; + } else { + column = rawtext[i + 1] + 256 - 0x61; + } + if (Big5Freq[row][column] != 0) { + bffreq += Big5Freq[row][column]; + } else if (3 <= row && row <= 37) { + bffreq += 200; + } + } + i++; + } + } + rangeval = 50 * ((float) bfchars / (float) dbchars); + freqval = 50 * ((float) bffreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + /* + * Function: big5plus_probability Argument: pointer to unsigned char array + * Returns : number from 0 to 100 representing probability text in array + * uses Big5+ encoding + */ + int big5plus_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, bfchars = 1; + long bffreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 128) { + // asciichars++; + } else { + dbchars++; + if (0xA1 <= rawtext[i] && rawtext[i] <= 0xF9 + && // Original Big5 + // range + ((0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) + || (0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= 0xFE))) { + bfchars++; + totalfreq += 500; + row = rawtext[i] - 0xA1; + if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { + column = rawtext[i + 1] - 0x40; + } else { + column = rawtext[i + 1] - 0x61; + } + // System.out.println("original row " + row + " column " + + // column); + if (Big5Freq[row][column] != 0) { + bffreq += Big5Freq[row][column]; + } else if (3 <= row && row < 37) { + bffreq += 200; + } + } else if (0x81 <= rawtext[i] && rawtext[i] <= 0xFE + && // Extended + // Big5 + // range + ((0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) + || (0x80 <= rawtext[i + 1] && rawtext[i + 1] <= 0xFE))) { + bfchars++; + totalfreq += 500; + row = rawtext[i] - 0x81; + if (0x40 <= rawtext[i + 1] && rawtext[i + 1] <= 0x7E) { + column = rawtext[i + 1] - 0x40; + } else { + column = rawtext[i + 1] - 0x40; + } + // System.out.println("extended row " + row + " column " + + // column + " rawtext[i] " + rawtext[i]); + if (Big5PFreq[row][column] != 0) { + bffreq += Big5PFreq[row][column]; + } + } + i++; + } + } + rangeval = 50 * ((float) bfchars / (float) dbchars); + freqval = 50 * ((float) bffreq / (float) totalfreq); + // For regular Big5 files, this would give the same score, so I handicap + // it slightly + return (int) (rangeval + freqval) - 1; + } + + /* + * Function: euc_tw_probability Argument: byte array Returns : number from 0 + * to 100 representing probability text in array uses EUC-TW (CNS 11643) + * encoding + */ + int euc_tw_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, cnschars = 1; + long cnsfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Check to see if characters fit into acceptable ranges + // and have expected frequency of use + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + if (rawtext[i] >= 0) { // in ASCII range + // asciichars++; + } else { // high bit set + dbchars++; + if (i + 3 < rawtextlen && (byte) 0x8E == rawtext[i] && (byte) 0xA1 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0xB0 && (byte) 0xA1 <= rawtext[i + 2] + && rawtext[i + 2] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 3] + && rawtext[i + 3] <= (byte) 0xFE) { // Planes 1 - 16 + cnschars++; + // System.out.println("plane 2 or above CNS char"); + // These are all less frequent chars so just ignore freq + i += 3; + } else if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE + && // Plane + // 1 + (byte) 0xA1 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE) { + cnschars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + if (EUC_TWFreq[row][column] != 0) { + cnsfreq += EUC_TWFreq[row][column]; + } else if (35 <= row && row <= 92) { + cnsfreq += 150; + } + i++; + } + } + } + rangeval = 50 * ((float) cnschars / (float) dbchars); + freqval = 50 * ((float) cnsfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + /* + * Function: iso_2022_cn_probability Argument: byte array Returns : number + * from 0 to 100 representing probability text in array uses ISO 2022-CN + * encoding WORKS FOR BASIC CASES, BUT STILL NEEDS MORE WORK + */ + int iso_2022_cn_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, isochars = 1; + long isofreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Check to see if characters fit into acceptable ranges + // and have expected frequency of use + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + if (rawtext[i] == (byte) 0x1B && i + 3 < rawtextlen) { // Escape + // char ESC + if (rawtext[i + 1] == (byte) 0x24 && rawtext[i + 2] == 0x29 && rawtext[i + 3] == (byte) 0x41) { // GB + // Escape + // $ + // ) + // A + i += 4; + while (rawtext[i] != (byte) 0x1B) { + dbchars++; + if ((0x21 <= rawtext[i] && rawtext[i] <= 0x77) + && (0x21 <= rawtext[i + 1] && rawtext[i + 1] <= 0x77)) { + isochars++; + row = rawtext[i] - 0x21; + column = rawtext[i + 1] - 0x21; + totalfreq += 500; + if (GBFreq[row][column] != 0) { + isofreq += GBFreq[row][column]; + } else if (15 <= row && row < 55) { + isofreq += 200; + } + i++; + } + i++; + } + } else if (i + 3 < rawtextlen && rawtext[i + 1] == (byte) 0x24 && rawtext[i + 2] == (byte) 0x29 + && rawtext[i + 3] == (byte) 0x47) { + // CNS Escape $ ) G + i += 4; + while (rawtext[i] != (byte) 0x1B) { + dbchars++; + if ((byte) 0x21 <= rawtext[i] && rawtext[i] <= (byte) 0x7E && (byte) 0x21 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0x7E) { + isochars++; + totalfreq += 500; + row = rawtext[i] - 0x21; + column = rawtext[i + 1] - 0x21; + if (EUC_TWFreq[row][column] != 0) { + isofreq += EUC_TWFreq[row][column]; + } else if (35 <= row && row <= 92) { + isofreq += 150; + } + i++; + } + i++; + } + } + if (rawtext[i] == (byte) 0x1B && i + 2 < rawtextlen && rawtext[i + 1] == (byte) 0x28 + && rawtext[i + 2] == (byte) 0x42) { // ASCII: + // ESC + // ( B + i += 2; + } + } + } + rangeval = 50 * ((float) isochars / (float) dbchars); + freqval = 50 * ((float) isofreq / (float) totalfreq); + // System.out.println("isochars dbchars isofreq totalfreq " + isochars + + // " " + dbchars + " " + isofreq + " " + totalfreq + " + // " + rangeval + " " + freqval); + return (int) (rangeval + freqval); + // return 0; + } + + /* + * Function: utf8_probability Argument: byte array Returns : number from 0 + * to 100 representing probability text in array uses UTF-8 encoding of + * Unicode + */ + int utf8_probability(byte[] rawtext) { + int score = 0; + int i, rawtextlen = 0; + int goodbytes = 0, asciibytes = 0; + // Maybe also use UTF8 Byte Order Mark: EF BB BF + // Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen; i++) { + if ((rawtext[i] & (byte) 0x7F) == rawtext[i]) { // One byte + asciibytes++; + // Ignore ASCII, can throw off count + } else if (-64 <= rawtext[i] && rawtext[i] <= -33 + && // Two bytes + i + 1 < rawtextlen && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65) { + goodbytes += 2; + i++; + } else if (-32 <= rawtext[i] && rawtext[i] <= -17 + && // Three bytes + i + 2 < rawtextlen && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 && -128 <= rawtext[i + 2] + && rawtext[i + 2] <= -65) { + goodbytes += 3; + i += 2; + } + } + if (asciibytes == rawtextlen) { + return 0; + } + score = (int) (100 * ((float) goodbytes / (float) (rawtextlen - asciibytes))); + // System.out.println("rawtextlen " + rawtextlen + " goodbytes " + + // goodbytes + " asciibytes " + asciibytes + " score " + + // score); + // If not above 98, reduce to zero to prevent coincidental matches + // Allows for some (few) bad formed sequences + if (score > 98) { + return score; + } else if (score > 95 && goodbytes > 30) { + return score; + } else { + return 0; + } + } + + /* + * Function: utf16_probability Argument: byte array Returns : number from 0 + * to 100 representing probability text in array uses UTF-16 encoding of + * Unicode, guess based on BOM // NOT VERY GENERAL, NEEDS MUCH MORE WORK + */ + int utf16_probability(byte[] rawtext) { + // int score = 0; + // int i, rawtextlen = 0; + // int goodbytes = 0, asciibytes = 0; + if (rawtext.length > 1 && ((byte) 0xFE == rawtext[0] && (byte) 0xFF == rawtext[1]) + || // Big-endian + ((byte) 0xFF == rawtext[0] && (byte) 0xFE == rawtext[1])) { // Little-endian + return 100; + } + return 0; + /* + * // Check to see if characters fit into acceptable ranges rawtextlen = + * rawtext.length; for (i = 0; i < rawtextlen; i++) { if ((rawtext[i] & + * (byte)0x7F) == rawtext[i]) { // One byte goodbytes += 1; + * asciibytes++; } else if ((rawtext[i] & (byte)0xDF) == rawtext[i]) { + * // Two bytes if (i+1 < rawtextlen && (rawtext[i+1] & (byte)0xBF) == + * rawtext[i+1]) { goodbytes += 2; i++; } } else if ((rawtext[i] & + * (byte)0xEF) == rawtext[i]) { // Three bytes if (i+2 < rawtextlen && + * (rawtext[i+1] & (byte)0xBF) == rawtext[i+1] && (rawtext[i+2] & + * (byte)0xBF) == rawtext[i+2]) { goodbytes += 3; i+=2; } } } + * + * score = (int)(100 * ((float)goodbytes/(float)rawtext.length)); // An + * all ASCII file is also a good UTF8 file, but I'd rather it // get + * identified as ASCII. Can delete following 3 lines otherwise if + * (goodbytes == asciibytes) { score = 0; } // If not above 90, reduce + * to zero to prevent coincidental matches if (score > 90) { return + * score; } else { return 0; } + */ + } + + /* + * Function: ascii_probability Argument: byte array Returns : number from 0 + * to 100 representing probability text in array uses all ASCII Description: + * Sees if array has any characters not in ASCII range, if so, score is + * reduced + */ + int ascii_probability(byte[] rawtext) { + int score = 75; + int i, rawtextlen; + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen; i++) { + if (rawtext[i] < 0) { + score = score - 5; + } else if (rawtext[i] == (byte) 0x1B) { // ESC (used by ISO 2022) + score = score - 5; + } + if (score <= 0) { + return 0; + } + } + return score; + } + + /* + * Function: euc_kr__probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses EUC-KR + * encoding + */ + int euc_kr_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, krchars = 1; + long krfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0xFE) { + krchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + if (KRFreq[row][column] != 0) { + krfreq += KRFreq[row][column]; + } else if (15 <= row && row < 55) { + krfreq += 0; + } + } + i++; + } + } + rangeval = 50 * ((float) krchars / (float) dbchars); + freqval = 50 * ((float) krfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + /* + * Function: cp949__probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses Cp949 + * encoding + */ + int cp949_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, krchars = 1; + long krfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0xFE + && ((byte) 0x41 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x5A + || (byte) 0x61 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7A + || (byte) 0x81 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFE)) { + krchars++; + totalfreq += 500; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0xFE) { + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + if (KRFreq[row][column] != 0) { + krfreq += KRFreq[row][column]; + } + } + } + i++; + } + } + rangeval = 50 * ((float) krchars / (float) dbchars); + freqval = 50 * ((float) krfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + int iso_2022_kr_probability(byte[] rawtext) { + int i; + for (i = 0; i < rawtext.length; i++) { + if (i + 3 < rawtext.length && rawtext[i] == 0x1b && (char) rawtext[i + 1] == '$' + && (char) rawtext[i + 2] == ')' && (char) rawtext[i + 3] == 'C') { + return 100; + } + } + return 0; + } + + /* + * Function: euc_jp_probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses EUC-JP + * encoding + */ + int euc_jp_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, jpchars = 1; + long jpfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xFE && (byte) 0xA1 <= rawtext[i + 1] + && rawtext[i + 1] <= (byte) 0xFE) { + jpchars++; + totalfreq += 500; + row = rawtext[i] + 256 - 0xA1; + column = rawtext[i + 1] + 256 - 0xA1; + if (JPFreq[row][column] != 0) { + jpfreq += JPFreq[row][column]; + } else if (15 <= row && row < 55) { + jpfreq += 0; + } + } + i++; + } + } + rangeval = 50 * ((float) jpchars / (float) dbchars); + freqval = 50 * ((float) jpfreq / (float) totalfreq); + return (int) (rangeval + freqval); + } + + int iso_2022_jp_probability(byte[] rawtext) { + int i; + for (i = 0; i < rawtext.length; i++) { + if (i + 2 < rawtext.length && rawtext[i] == 0x1b && (char) rawtext[i + 1] == '$' + && (char) rawtext[i + 2] == 'B') { + return 100; + } + } + return 0; + } + + /* + * Function: sjis_probability Argument: pointer to byte array Returns : + * number from 0 to 100 representing probability text in array uses + * Shift-JIS encoding + */ + int sjis_probability(byte[] rawtext) { + int i, rawtextlen = 0; + int dbchars = 1, jpchars = 1; + long jpfreq = 0, totalfreq = 1; + float rangeval = 0, freqval = 0; + int row, column, adjust; + // Stage 1: Check to see if characters fit into acceptable ranges + rawtextlen = rawtext.length; + for (i = 0; i < rawtextlen - 1; i++) { + // System.err.println(rawtext[i]); + if (rawtext[i] >= 0) { + // asciichars++; + } else { + dbchars++; + if (i + 1 < rawtext.length + && (((byte) 0x81 <= rawtext[i] && rawtext[i] <= (byte) 0x9F) + || ((byte) 0xE0 <= rawtext[i] && rawtext[i] <= (byte) 0xEF)) + && (((byte) 0x40 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0x7E) + || ((byte) 0x80 <= rawtext[i + 1] && rawtext[i + 1] <= (byte) 0xFC))) { + jpchars++; + totalfreq += 500; + row = rawtext[i] + 256; + column = rawtext[i + 1] + 256; + if (column < 0x9f) { + adjust = 1; + if (column > 0x7f) { + column -= 0x20; + } else { + column -= 0x19; + } + } else { + adjust = 0; + column -= 0x7e; + } + if (row < 0xa0) { + row = ((row - 0x70) << 1) - adjust; + } else { + row = ((row - 0xb0) << 1) - adjust; + } + row -= 0x20; + column = 0x20; + // System.out.println("original row " + row + " column " + + // column); + if (row < JPFreq.length && column < JPFreq[row].length && JPFreq[row][column] != 0) { + jpfreq += JPFreq[row][column]; + } + i++; + } else if ((byte) 0xA1 <= rawtext[i] && rawtext[i] <= (byte) 0xDF) { + // half-width katakana, convert to full-width + } + } + } + rangeval = 50 * ((float) jpchars / (float) dbchars); + freqval = 50 * ((float) jpfreq / (float) totalfreq); + // For regular GB files, this would give the same score, so I handicap + // it slightly + return (int) (rangeval + freqval) - 1; + } + + void initialize_frequencies() { + int i, j; + for (i = 0; i < 94; i++) { + for (j = 0; j < 94; j++) { + GBFreq[i][j] = 0; + } + } + for (i = 0; i < 126; i++) { + for (j = 0; j < 191; j++) { + GBKFreq[i][j] = 0; + } + } + for (i = 0; i < 94; i++) { + for (j = 0; j < 158; j++) { + Big5Freq[i][j] = 0; + } + } + for (i = 0; i < 126; i++) { + for (j = 0; j < 191; j++) { + Big5PFreq[i][j] = 0; + } + } + for (i = 0; i < 94; i++) { + for (j = 0; j < 94; j++) { + EUC_TWFreq[i][j] = 0; + } + } + for (i = 0; i < 94; i++) { + for (j = 0; j < 94; j++) { + JPFreq[i][j] = 0; + } + } + GBFreq[20][35] = 599; + GBFreq[49][26] = 598; + GBFreq[41][38] = 597; + GBFreq[17][26] = 596; + GBFreq[32][42] = 595; + GBFreq[39][42] = 594; + GBFreq[45][49] = 593; + GBFreq[51][57] = 592; + GBFreq[50][47] = 591; + GBFreq[42][90] = 590; + GBFreq[52][65] = 589; + GBFreq[53][47] = 588; + GBFreq[19][82] = 587; + GBFreq[31][19] = 586; + GBFreq[40][46] = 585; + GBFreq[24][89] = 584; + GBFreq[23][85] = 583; + GBFreq[20][28] = 582; + GBFreq[42][20] = 581; + GBFreq[34][38] = 580; + GBFreq[45][9] = 579; + GBFreq[54][50] = 578; + GBFreq[25][44] = 577; + GBFreq[35][66] = 576; + GBFreq[20][55] = 575; + GBFreq[18][85] = 574; + GBFreq[20][31] = 573; + GBFreq[49][17] = 572; + GBFreq[41][16] = 571; + GBFreq[35][73] = 570; + GBFreq[20][34] = 569; + GBFreq[29][44] = 568; + GBFreq[35][38] = 567; + GBFreq[49][9] = 566; + GBFreq[46][33] = 565; + GBFreq[49][51] = 564; + GBFreq[40][89] = 563; + GBFreq[26][64] = 562; + GBFreq[54][51] = 561; + GBFreq[54][36] = 560; + GBFreq[39][4] = 559; + GBFreq[53][13] = 558; + GBFreq[24][92] = 557; + GBFreq[27][49] = 556; + GBFreq[48][6] = 555; + GBFreq[21][51] = 554; + GBFreq[30][40] = 553; + GBFreq[42][92] = 552; + GBFreq[31][78] = 551; + GBFreq[25][82] = 550; + GBFreq[47][0] = 549; + GBFreq[34][19] = 548; + GBFreq[47][35] = 547; + GBFreq[21][63] = 546; + GBFreq[43][75] = 545; + GBFreq[21][87] = 544; + GBFreq[35][59] = 543; + GBFreq[25][34] = 542; + GBFreq[21][27] = 541; + GBFreq[39][26] = 540; + GBFreq[34][26] = 539; + GBFreq[39][52] = 538; + GBFreq[50][57] = 537; + GBFreq[37][79] = 536; + GBFreq[26][24] = 535; + GBFreq[22][1] = 534; + GBFreq[18][40] = 533; + GBFreq[41][33] = 532; + GBFreq[53][26] = 531; + GBFreq[54][86] = 530; + GBFreq[20][16] = 529; + GBFreq[46][74] = 528; + GBFreq[30][19] = 527; + GBFreq[45][35] = 526; + GBFreq[45][61] = 525; + GBFreq[30][9] = 524; + GBFreq[41][53] = 523; + GBFreq[41][13] = 522; + GBFreq[50][34] = 521; + GBFreq[53][86] = 520; + GBFreq[47][47] = 519; + GBFreq[22][28] = 518; + GBFreq[50][53] = 517; + GBFreq[39][70] = 516; + GBFreq[38][15] = 515; + GBFreq[42][88] = 514; + GBFreq[16][29] = 513; + GBFreq[27][90] = 512; + GBFreq[29][12] = 511; + GBFreq[44][22] = 510; + GBFreq[34][69] = 509; + GBFreq[24][10] = 508; + GBFreq[44][11] = 507; + GBFreq[39][92] = 506; + GBFreq[49][48] = 505; + GBFreq[31][46] = 504; + GBFreq[19][50] = 503; + GBFreq[21][14] = 502; + GBFreq[32][28] = 501; + GBFreq[18][3] = 500; + GBFreq[53][9] = 499; + GBFreq[34][80] = 498; + GBFreq[48][88] = 497; + GBFreq[46][53] = 496; + GBFreq[22][53] = 495; + GBFreq[28][10] = 494; + GBFreq[44][65] = 493; + GBFreq[20][10] = 492; + GBFreq[40][76] = 491; + GBFreq[47][8] = 490; + GBFreq[50][74] = 489; + GBFreq[23][62] = 488; + GBFreq[49][65] = 487; + GBFreq[28][87] = 486; + GBFreq[15][48] = 485; + GBFreq[22][7] = 484; + GBFreq[19][42] = 483; + GBFreq[41][20] = 482; + GBFreq[26][55] = 481; + GBFreq[21][93] = 480; + GBFreq[31][76] = 479; + GBFreq[34][31] = 478; + GBFreq[20][66] = 477; + GBFreq[51][33] = 476; + GBFreq[34][86] = 475; + GBFreq[37][67] = 474; + GBFreq[53][53] = 473; + GBFreq[40][88] = 472; + GBFreq[39][10] = 471; + GBFreq[24][3] = 470; + GBFreq[27][25] = 469; + GBFreq[26][15] = 468; + GBFreq[21][88] = 467; + GBFreq[52][62] = 466; + GBFreq[46][81] = 465; + GBFreq[38][72] = 464; + GBFreq[17][30] = 463; + GBFreq[52][92] = 462; + GBFreq[34][90] = 461; + GBFreq[21][7] = 460; + GBFreq[36][13] = 459; + GBFreq[45][41] = 458; + GBFreq[32][5] = 457; + GBFreq[26][89] = 456; + GBFreq[23][87] = 455; + GBFreq[20][39] = 454; + GBFreq[27][23] = 453; + GBFreq[25][59] = 452; + GBFreq[49][20] = 451; + GBFreq[54][77] = 450; + GBFreq[27][67] = 449; + GBFreq[47][33] = 448; + GBFreq[41][17] = 447; + GBFreq[19][81] = 446; + GBFreq[16][66] = 445; + GBFreq[45][26] = 444; + GBFreq[49][81] = 443; + GBFreq[53][55] = 442; + GBFreq[16][26] = 441; + GBFreq[54][62] = 440; + GBFreq[20][70] = 439; + GBFreq[42][35] = 438; + GBFreq[20][57] = 437; + GBFreq[34][36] = 436; + GBFreq[46][63] = 435; + GBFreq[19][45] = 434; + GBFreq[21][10] = 433; + GBFreq[52][93] = 432; + GBFreq[25][2] = 431; + GBFreq[30][57] = 430; + GBFreq[41][24] = 429; + GBFreq[28][43] = 428; + GBFreq[45][86] = 427; + GBFreq[51][56] = 426; + GBFreq[37][28] = 425; + GBFreq[52][69] = 424; + GBFreq[43][92] = 423; + GBFreq[41][31] = 422; + GBFreq[37][87] = 421; + GBFreq[47][36] = 420; + GBFreq[16][16] = 419; + GBFreq[40][56] = 418; + GBFreq[24][55] = 417; + GBFreq[17][1] = 416; + GBFreq[35][57] = 415; + GBFreq[27][50] = 414; + GBFreq[26][14] = 413; + GBFreq[50][40] = 412; + GBFreq[39][19] = 411; + GBFreq[19][89] = 410; + GBFreq[29][91] = 409; + GBFreq[17][89] = 408; + GBFreq[39][74] = 407; + GBFreq[46][39] = 406; + GBFreq[40][28] = 405; + GBFreq[45][68] = 404; + GBFreq[43][10] = 403; + GBFreq[42][13] = 402; + GBFreq[44][81] = 401; + GBFreq[41][47] = 400; + GBFreq[48][58] = 399; + GBFreq[43][68] = 398; + GBFreq[16][79] = 397; + GBFreq[19][5] = 396; + GBFreq[54][59] = 395; + GBFreq[17][36] = 394; + GBFreq[18][0] = 393; + GBFreq[41][5] = 392; + GBFreq[41][72] = 391; + GBFreq[16][39] = 390; + GBFreq[54][0] = 389; + GBFreq[51][16] = 388; + GBFreq[29][36] = 387; + GBFreq[47][5] = 386; + GBFreq[47][51] = 385; + GBFreq[44][7] = 384; + GBFreq[35][30] = 383; + GBFreq[26][9] = 382; + GBFreq[16][7] = 381; + GBFreq[32][1] = 380; + GBFreq[33][76] = 379; + GBFreq[34][91] = 378; + GBFreq[52][36] = 377; + GBFreq[26][77] = 376; + GBFreq[35][48] = 375; + GBFreq[40][80] = 374; + GBFreq[41][92] = 373; + GBFreq[27][93] = 372; + GBFreq[15][17] = 371; + GBFreq[16][76] = 370; + GBFreq[51][12] = 369; + GBFreq[18][20] = 368; + GBFreq[15][54] = 367; + GBFreq[50][5] = 366; + GBFreq[33][22] = 365; + GBFreq[37][57] = 364; + GBFreq[28][47] = 363; + GBFreq[42][31] = 362; + GBFreq[18][2] = 361; + GBFreq[43][64] = 360; + GBFreq[23][47] = 359; + GBFreq[28][79] = 358; + GBFreq[25][45] = 357; + GBFreq[23][91] = 356; + GBFreq[22][19] = 355; + GBFreq[25][46] = 354; + GBFreq[22][36] = 353; + GBFreq[54][85] = 352; + GBFreq[46][20] = 351; + GBFreq[27][37] = 350; + GBFreq[26][81] = 349; + GBFreq[42][29] = 348; + GBFreq[31][90] = 347; + GBFreq[41][59] = 346; + GBFreq[24][65] = 345; + GBFreq[44][84] = 344; + GBFreq[24][90] = 343; + GBFreq[38][54] = 342; + GBFreq[28][70] = 341; + GBFreq[27][15] = 340; + GBFreq[28][80] = 339; + GBFreq[29][8] = 338; + GBFreq[45][80] = 337; + GBFreq[53][37] = 336; + GBFreq[28][65] = 335; + GBFreq[23][86] = 334; + GBFreq[39][45] = 333; + GBFreq[53][32] = 332; + GBFreq[38][68] = 331; + GBFreq[45][78] = 330; + GBFreq[43][7] = 329; + GBFreq[46][82] = 328; + GBFreq[27][38] = 327; + GBFreq[16][62] = 326; + GBFreq[24][17] = 325; + GBFreq[22][70] = 324; + GBFreq[52][28] = 323; + GBFreq[23][40] = 322; + GBFreq[28][50] = 321; + GBFreq[42][91] = 320; + GBFreq[47][76] = 319; + GBFreq[15][42] = 318; + GBFreq[43][55] = 317; + GBFreq[29][84] = 316; + GBFreq[44][90] = 315; + GBFreq[53][16] = 314; + GBFreq[22][93] = 313; + GBFreq[34][10] = 312; + GBFreq[32][53] = 311; + GBFreq[43][65] = 310; + GBFreq[28][7] = 309; + GBFreq[35][46] = 308; + GBFreq[21][39] = 307; + GBFreq[44][18] = 306; + GBFreq[40][10] = 305; + GBFreq[54][53] = 304; + GBFreq[38][74] = 303; + GBFreq[28][26] = 302; + GBFreq[15][13] = 301; + GBFreq[39][34] = 300; + GBFreq[39][46] = 299; + GBFreq[42][66] = 298; + GBFreq[33][58] = 297; + GBFreq[15][56] = 296; + GBFreq[18][51] = 295; + GBFreq[49][68] = 294; + GBFreq[30][37] = 293; + GBFreq[51][84] = 292; + GBFreq[51][9] = 291; + GBFreq[40][70] = 290; + GBFreq[41][84] = 289; + GBFreq[28][64] = 288; + GBFreq[32][88] = 287; + GBFreq[24][5] = 286; + GBFreq[53][23] = 285; + GBFreq[42][27] = 284; + GBFreq[22][38] = 283; + GBFreq[32][86] = 282; + GBFreq[34][30] = 281; + GBFreq[38][63] = 280; + GBFreq[24][59] = 279; + GBFreq[22][81] = 278; + GBFreq[32][11] = 277; + GBFreq[51][21] = 276; + GBFreq[54][41] = 275; + GBFreq[21][50] = 274; + GBFreq[23][89] = 273; + GBFreq[19][87] = 272; + GBFreq[26][7] = 271; + GBFreq[30][75] = 270; + GBFreq[43][84] = 269; + GBFreq[51][25] = 268; + GBFreq[16][67] = 267; + GBFreq[32][9] = 266; + GBFreq[48][51] = 265; + GBFreq[39][7] = 264; + GBFreq[44][88] = 263; + GBFreq[52][24] = 262; + GBFreq[23][34] = 261; + GBFreq[32][75] = 260; + GBFreq[19][10] = 259; + GBFreq[28][91] = 258; + GBFreq[32][83] = 257; + GBFreq[25][75] = 256; + GBFreq[53][45] = 255; + GBFreq[29][85] = 254; + GBFreq[53][59] = 253; + GBFreq[16][2] = 252; + GBFreq[19][78] = 251; + GBFreq[15][75] = 250; + GBFreq[51][42] = 249; + GBFreq[45][67] = 248; + GBFreq[15][74] = 247; + GBFreq[25][81] = 246; + GBFreq[37][62] = 245; + GBFreq[16][55] = 244; + GBFreq[18][38] = 243; + GBFreq[23][23] = 242; + GBFreq[38][30] = 241; + GBFreq[17][28] = 240; + GBFreq[44][73] = 239; + GBFreq[23][78] = 238; + GBFreq[40][77] = 237; + GBFreq[38][87] = 236; + GBFreq[27][19] = 235; + GBFreq[38][82] = 234; + GBFreq[37][22] = 233; + GBFreq[41][30] = 232; + GBFreq[54][9] = 231; + GBFreq[32][30] = 230; + GBFreq[30][52] = 229; + GBFreq[40][84] = 228; + GBFreq[53][57] = 227; + GBFreq[27][27] = 226; + GBFreq[38][64] = 225; + GBFreq[18][43] = 224; + GBFreq[23][69] = 223; + GBFreq[28][12] = 222; + GBFreq[50][78] = 221; + GBFreq[50][1] = 220; + GBFreq[26][88] = 219; + GBFreq[36][40] = 218; + GBFreq[33][89] = 217; + GBFreq[41][28] = 216; + GBFreq[31][77] = 215; + GBFreq[46][1] = 214; + GBFreq[47][19] = 213; + GBFreq[35][55] = 212; + GBFreq[41][21] = 211; + GBFreq[27][10] = 210; + GBFreq[32][77] = 209; + GBFreq[26][37] = 208; + GBFreq[20][33] = 207; + GBFreq[41][52] = 206; + GBFreq[32][18] = 205; + GBFreq[38][13] = 204; + GBFreq[20][18] = 203; + GBFreq[20][24] = 202; + GBFreq[45][19] = 201; + GBFreq[18][53] = 200; + /* + * GBFreq[39][0] = 199; GBFreq[40][71] = 198; GBFreq[41][27] = 197; + * GBFreq[15][69] = 196; GBFreq[42][10] = 195; GBFreq[31][89] = 194; + * GBFreq[51][28] = 193; GBFreq[41][22] = 192; GBFreq[40][43] = 191; + * GBFreq[38][6] = 190; GBFreq[37][11] = 189; GBFreq[39][60] = 188; + * GBFreq[48][47] = 187; GBFreq[46][80] = 186; GBFreq[52][49] = 185; + * GBFreq[50][48] = 184; GBFreq[25][1] = 183; GBFreq[52][29] = 182; + * GBFreq[24][66] = 181; GBFreq[23][35] = 180; GBFreq[49][72] = 179; + * GBFreq[47][45] = 178; GBFreq[45][14] = 177; GBFreq[51][70] = 176; + * GBFreq[22][30] = 175; GBFreq[49][83] = 174; GBFreq[26][79] = 173; + * GBFreq[27][41] = 172; GBFreq[51][81] = 171; GBFreq[41][54] = 170; + * GBFreq[20][4] = 169; GBFreq[29][60] = 168; GBFreq[20][27] = 167; + * GBFreq[50][15] = 166; GBFreq[41][6] = 165; GBFreq[35][34] = 164; + * GBFreq[44][87] = 163; GBFreq[46][66] = 162; GBFreq[42][37] = 161; + * GBFreq[42][24] = 160; GBFreq[54][7] = 159; GBFreq[41][14] = 158; + * GBFreq[39][83] = 157; GBFreq[16][87] = 156; GBFreq[20][59] = 155; + * GBFreq[42][12] = 154; GBFreq[47][2] = 153; GBFreq[21][32] = 152; + * GBFreq[53][29] = 151; GBFreq[22][40] = 150; GBFreq[24][58] = 149; + * GBFreq[52][88] = 148; GBFreq[29][30] = 147; GBFreq[15][91] = 146; + * GBFreq[54][72] = 145; GBFreq[51][75] = 144; GBFreq[33][67] = 143; + * GBFreq[41][50] = 142; GBFreq[27][34] = 141; GBFreq[46][17] = 140; + * GBFreq[31][74] = 139; GBFreq[42][67] = 138; GBFreq[54][87] = 137; + * GBFreq[27][14] = 136; GBFreq[16][63] = 135; GBFreq[16][5] = 134; + * GBFreq[43][23] = 133; GBFreq[23][13] = 132; GBFreq[31][12] = 131; + * GBFreq[25][57] = 130; GBFreq[38][49] = 129; GBFreq[42][69] = 128; + * GBFreq[23][80] = 127; GBFreq[29][0] = 126; GBFreq[28][2] = 125; + * GBFreq[28][17] = 124; GBFreq[17][27] = 123; GBFreq[40][16] = 122; + * GBFreq[45][1] = 121; GBFreq[36][33] = 120; GBFreq[35][23] = 119; + * GBFreq[20][86] = 118; GBFreq[29][53] = 117; GBFreq[23][88] = 116; + * GBFreq[51][87] = 115; GBFreq[54][27] = 114; GBFreq[44][36] = 113; + * GBFreq[21][45] = 112; GBFreq[53][52] = 111; GBFreq[31][53] = 110; + * GBFreq[38][47] = 109; GBFreq[27][21] = 108; GBFreq[30][42] = 107; + * GBFreq[29][10] = 106; GBFreq[35][35] = 105; GBFreq[24][56] = 104; + * GBFreq[41][29] = 103; GBFreq[18][68] = 102; GBFreq[29][24] = 101; + * GBFreq[25][84] = 100; GBFreq[35][47] = 99; GBFreq[29][56] = 98; + * GBFreq[30][44] = 97; GBFreq[53][3] = 96; GBFreq[30][63] = 95; + * GBFreq[52][52] = 94; GBFreq[54][1] = 93; GBFreq[22][48] = 92; + * GBFreq[54][66] = 91; GBFreq[21][90] = 90; GBFreq[52][47] = 89; + * GBFreq[39][25] = 88; GBFreq[39][39] = 87; GBFreq[44][37] = 86; + * GBFreq[44][76] = 85; GBFreq[46][75] = 84; GBFreq[18][37] = 83; + * GBFreq[47][42] = 82; GBFreq[19][92] = 81; GBFreq[51][27] = 80; + * GBFreq[48][83] = 79; GBFreq[23][70] = 78; GBFreq[29][9] = 77; + * GBFreq[33][79] = 76; GBFreq[52][90] = 75; GBFreq[53][6] = 74; + * GBFreq[24][36] = 73; GBFreq[25][25] = 72; GBFreq[44][26] = 71; + * GBFreq[25][36] = 70; GBFreq[29][87] = 69; GBFreq[48][0] = 68; + * GBFreq[15][40] = 67; GBFreq[17][45] = 66; GBFreq[30][14] = 65; + * GBFreq[48][38] = 64; GBFreq[23][19] = 63; GBFreq[40][42] = 62; + * GBFreq[31][63] = 61; GBFreq[16][23] = 60; GBFreq[26][21] = 59; + * GBFreq[32][76] = 58; GBFreq[23][58] = 57; GBFreq[41][37] = 56; + * GBFreq[30][43] = 55; GBFreq[47][38] = 54; GBFreq[21][46] = 53; + * GBFreq[18][33] = 52; GBFreq[52][37] = 51; GBFreq[36][8] = 50; + * GBFreq[49][24] = 49; GBFreq[15][66] = 48; GBFreq[35][77] = 47; + * GBFreq[27][58] = 46; GBFreq[35][51] = 45; GBFreq[24][69] = 44; + * GBFreq[20][54] = 43; GBFreq[24][41] = 42; GBFreq[41][0] = 41; + * GBFreq[33][71] = 40; GBFreq[23][52] = 39; GBFreq[29][67] = 38; + * GBFreq[46][51] = 37; GBFreq[46][90] = 36; GBFreq[49][33] = 35; + * GBFreq[33][28] = 34; GBFreq[37][86] = 33; GBFreq[39][22] = 32; + * GBFreq[37][37] = 31; GBFreq[29][62] = 30; GBFreq[29][50] = 29; + * GBFreq[36][89] = 28; GBFreq[42][44] = 27; GBFreq[51][82] = 26; + * GBFreq[28][83] = 25; GBFreq[15][78] = 24; GBFreq[46][62] = 23; + * GBFreq[19][69] = 22; GBFreq[51][23] = 21; GBFreq[37][69] = 20; + * GBFreq[25][5] = 19; GBFreq[51][85] = 18; GBFreq[48][77] = 17; + * GBFreq[32][46] = 16; GBFreq[53][60] = 15; GBFreq[28][57] = 14; + * GBFreq[54][82] = 13; GBFreq[54][15] = 12; GBFreq[49][54] = 11; + * GBFreq[53][87] = 10; GBFreq[27][16] = 9; GBFreq[29][34] = 8; + * GBFreq[20][44] = 7; GBFreq[42][73] = 6; GBFreq[47][71] = 5; + * GBFreq[29][37] = 4; GBFreq[25][50] = 3; GBFreq[18][84] = 2; + * GBFreq[50][45] = 1; GBFreq[48][46] = 0; + */ + // GBFreq[43][89] = -1; GBFreq[54][68] = -2; + Big5Freq[9][89] = 600; + Big5Freq[11][15] = 599; + Big5Freq[3][66] = 598; + Big5Freq[6][121] = 597; + Big5Freq[3][0] = 596; + Big5Freq[5][82] = 595; + Big5Freq[3][42] = 594; + Big5Freq[5][34] = 593; + Big5Freq[3][8] = 592; + Big5Freq[3][6] = 591; + Big5Freq[3][67] = 590; + Big5Freq[7][139] = 589; + Big5Freq[23][137] = 588; + Big5Freq[12][46] = 587; + Big5Freq[4][8] = 586; + Big5Freq[4][41] = 585; + Big5Freq[18][47] = 584; + Big5Freq[12][114] = 583; + Big5Freq[6][1] = 582; + Big5Freq[22][60] = 581; + Big5Freq[5][46] = 580; + Big5Freq[11][79] = 579; + Big5Freq[3][23] = 578; + Big5Freq[7][114] = 577; + Big5Freq[29][102] = 576; + Big5Freq[19][14] = 575; + Big5Freq[4][133] = 574; + Big5Freq[3][29] = 573; + Big5Freq[4][109] = 572; + Big5Freq[14][127] = 571; + Big5Freq[5][48] = 570; + Big5Freq[13][104] = 569; + Big5Freq[3][132] = 568; + Big5Freq[26][64] = 567; + Big5Freq[7][19] = 566; + Big5Freq[4][12] = 565; + Big5Freq[11][124] = 564; + Big5Freq[7][89] = 563; + Big5Freq[15][124] = 562; + Big5Freq[4][108] = 561; + Big5Freq[19][66] = 560; + Big5Freq[3][21] = 559; + Big5Freq[24][12] = 558; + Big5Freq[28][111] = 557; + Big5Freq[12][107] = 556; + Big5Freq[3][112] = 555; + Big5Freq[8][113] = 554; + Big5Freq[5][40] = 553; + Big5Freq[26][145] = 552; + Big5Freq[3][48] = 551; + Big5Freq[3][70] = 550; + Big5Freq[22][17] = 549; + Big5Freq[16][47] = 548; + Big5Freq[3][53] = 547; + Big5Freq[4][24] = 546; + Big5Freq[32][120] = 545; + Big5Freq[24][49] = 544; + Big5Freq[24][142] = 543; + Big5Freq[18][66] = 542; + Big5Freq[29][150] = 541; + Big5Freq[5][122] = 540; + Big5Freq[5][114] = 539; + Big5Freq[3][44] = 538; + Big5Freq[10][128] = 537; + Big5Freq[15][20] = 536; + Big5Freq[13][33] = 535; + Big5Freq[14][87] = 534; + Big5Freq[3][126] = 533; + Big5Freq[4][53] = 532; + Big5Freq[4][40] = 531; + Big5Freq[9][93] = 530; + Big5Freq[15][137] = 529; + Big5Freq[10][123] = 528; + Big5Freq[4][56] = 527; + Big5Freq[5][71] = 526; + Big5Freq[10][8] = 525; + Big5Freq[5][16] = 524; + Big5Freq[5][146] = 523; + Big5Freq[18][88] = 522; + Big5Freq[24][4] = 521; + Big5Freq[20][47] = 520; + Big5Freq[5][33] = 519; + Big5Freq[9][43] = 518; + Big5Freq[20][12] = 517; + Big5Freq[20][13] = 516; + Big5Freq[5][156] = 515; + Big5Freq[22][140] = 514; + Big5Freq[8][146] = 513; + Big5Freq[21][123] = 512; + Big5Freq[4][90] = 511; + Big5Freq[5][62] = 510; + Big5Freq[17][59] = 509; + Big5Freq[10][37] = 508; + Big5Freq[18][107] = 507; + Big5Freq[14][53] = 506; + Big5Freq[22][51] = 505; + Big5Freq[8][13] = 504; + Big5Freq[5][29] = 503; + Big5Freq[9][7] = 502; + Big5Freq[22][14] = 501; + Big5Freq[8][55] = 500; + Big5Freq[33][9] = 499; + Big5Freq[16][64] = 498; + Big5Freq[7][131] = 497; + Big5Freq[34][4] = 496; + Big5Freq[7][101] = 495; + Big5Freq[11][139] = 494; + Big5Freq[3][135] = 493; + Big5Freq[7][102] = 492; + Big5Freq[17][13] = 491; + Big5Freq[3][20] = 490; + Big5Freq[27][106] = 489; + Big5Freq[5][88] = 488; + Big5Freq[6][33] = 487; + Big5Freq[5][139] = 486; + Big5Freq[6][0] = 485; + Big5Freq[17][58] = 484; + Big5Freq[5][133] = 483; + Big5Freq[9][107] = 482; + Big5Freq[23][39] = 481; + Big5Freq[5][23] = 480; + Big5Freq[3][79] = 479; + Big5Freq[32][97] = 478; + Big5Freq[3][136] = 477; + Big5Freq[4][94] = 476; + Big5Freq[21][61] = 475; + Big5Freq[23][123] = 474; + Big5Freq[26][16] = 473; + Big5Freq[24][137] = 472; + Big5Freq[22][18] = 471; + Big5Freq[5][1] = 470; + Big5Freq[20][119] = 469; + Big5Freq[3][7] = 468; + Big5Freq[10][79] = 467; + Big5Freq[15][105] = 466; + Big5Freq[3][144] = 465; + Big5Freq[12][80] = 464; + Big5Freq[15][73] = 463; + Big5Freq[3][19] = 462; + Big5Freq[8][109] = 461; + Big5Freq[3][15] = 460; + Big5Freq[31][82] = 459; + Big5Freq[3][43] = 458; + Big5Freq[25][119] = 457; + Big5Freq[16][111] = 456; + Big5Freq[7][77] = 455; + Big5Freq[3][95] = 454; + Big5Freq[24][82] = 453; + Big5Freq[7][52] = 452; + Big5Freq[9][151] = 451; + Big5Freq[3][129] = 450; + Big5Freq[5][87] = 449; + Big5Freq[3][55] = 448; + Big5Freq[8][153] = 447; + Big5Freq[4][83] = 446; + Big5Freq[3][114] = 445; + Big5Freq[23][147] = 444; + Big5Freq[15][31] = 443; + Big5Freq[3][54] = 442; + Big5Freq[11][122] = 441; + Big5Freq[4][4] = 440; + Big5Freq[34][149] = 439; + Big5Freq[3][17] = 438; + Big5Freq[21][64] = 437; + Big5Freq[26][144] = 436; + Big5Freq[4][62] = 435; + Big5Freq[8][15] = 434; + Big5Freq[35][80] = 433; + Big5Freq[7][110] = 432; + Big5Freq[23][114] = 431; + Big5Freq[3][108] = 430; + Big5Freq[3][62] = 429; + Big5Freq[21][41] = 428; + Big5Freq[15][99] = 427; + Big5Freq[5][47] = 426; + Big5Freq[4][96] = 425; + Big5Freq[20][122] = 424; + Big5Freq[5][21] = 423; + Big5Freq[4][157] = 422; + Big5Freq[16][14] = 421; + Big5Freq[3][117] = 420; + Big5Freq[7][129] = 419; + Big5Freq[4][27] = 418; + Big5Freq[5][30] = 417; + Big5Freq[22][16] = 416; + Big5Freq[5][64] = 415; + Big5Freq[17][99] = 414; + Big5Freq[17][57] = 413; + Big5Freq[8][105] = 412; + Big5Freq[5][112] = 411; + Big5Freq[20][59] = 410; + Big5Freq[6][129] = 409; + Big5Freq[18][17] = 408; + Big5Freq[3][92] = 407; + Big5Freq[28][118] = 406; + Big5Freq[3][109] = 405; + Big5Freq[31][51] = 404; + Big5Freq[13][116] = 403; + Big5Freq[6][15] = 402; + Big5Freq[36][136] = 401; + Big5Freq[12][74] = 400; + Big5Freq[20][88] = 399; + Big5Freq[36][68] = 398; + Big5Freq[3][147] = 397; + Big5Freq[15][84] = 396; + Big5Freq[16][32] = 395; + Big5Freq[16][58] = 394; + Big5Freq[7][66] = 393; + Big5Freq[23][107] = 392; + Big5Freq[9][6] = 391; + Big5Freq[12][86] = 390; + Big5Freq[23][112] = 389; + Big5Freq[37][23] = 388; + Big5Freq[3][138] = 387; + Big5Freq[20][68] = 386; + Big5Freq[15][116] = 385; + Big5Freq[18][64] = 384; + Big5Freq[12][139] = 383; + Big5Freq[11][155] = 382; + Big5Freq[4][156] = 381; + Big5Freq[12][84] = 380; + Big5Freq[18][49] = 379; + Big5Freq[25][125] = 378; + Big5Freq[25][147] = 377; + Big5Freq[15][110] = 376; + Big5Freq[19][96] = 375; + Big5Freq[30][152] = 374; + Big5Freq[6][31] = 373; + Big5Freq[27][117] = 372; + Big5Freq[3][10] = 371; + Big5Freq[6][131] = 370; + Big5Freq[13][112] = 369; + Big5Freq[36][156] = 368; + Big5Freq[4][60] = 367; + Big5Freq[15][121] = 366; + Big5Freq[4][112] = 365; + Big5Freq[30][142] = 364; + Big5Freq[23][154] = 363; + Big5Freq[27][101] = 362; + Big5Freq[9][140] = 361; + Big5Freq[3][89] = 360; + Big5Freq[18][148] = 359; + Big5Freq[4][69] = 358; + Big5Freq[16][49] = 357; + Big5Freq[6][117] = 356; + Big5Freq[36][55] = 355; + Big5Freq[5][123] = 354; + Big5Freq[4][126] = 353; + Big5Freq[4][119] = 352; + Big5Freq[9][95] = 351; + Big5Freq[5][24] = 350; + Big5Freq[16][133] = 349; + Big5Freq[10][134] = 348; + Big5Freq[26][59] = 347; + Big5Freq[6][41] = 346; + Big5Freq[6][146] = 345; + Big5Freq[19][24] = 344; + Big5Freq[5][113] = 343; + Big5Freq[10][118] = 342; + Big5Freq[34][151] = 341; + Big5Freq[9][72] = 340; + Big5Freq[31][25] = 339; + Big5Freq[18][126] = 338; + Big5Freq[18][28] = 337; + Big5Freq[4][153] = 336; + Big5Freq[3][84] = 335; + Big5Freq[21][18] = 334; + Big5Freq[25][129] = 333; + Big5Freq[6][107] = 332; + Big5Freq[12][25] = 331; + Big5Freq[17][109] = 330; + Big5Freq[7][76] = 329; + Big5Freq[15][15] = 328; + Big5Freq[4][14] = 327; + Big5Freq[23][88] = 326; + Big5Freq[18][2] = 325; + Big5Freq[6][88] = 324; + Big5Freq[16][84] = 323; + Big5Freq[12][48] = 322; + Big5Freq[7][68] = 321; + Big5Freq[5][50] = 320; + Big5Freq[13][54] = 319; + Big5Freq[7][98] = 318; + Big5Freq[11][6] = 317; + Big5Freq[9][80] = 316; + Big5Freq[16][41] = 315; + Big5Freq[7][43] = 314; + Big5Freq[28][117] = 313; + Big5Freq[3][51] = 312; + Big5Freq[7][3] = 311; + Big5Freq[20][81] = 310; + Big5Freq[4][2] = 309; + Big5Freq[11][16] = 308; + Big5Freq[10][4] = 307; + Big5Freq[10][119] = 306; + Big5Freq[6][142] = 305; + Big5Freq[18][51] = 304; + Big5Freq[8][144] = 303; + Big5Freq[10][65] = 302; + Big5Freq[11][64] = 301; + Big5Freq[11][130] = 300; + Big5Freq[9][92] = 299; + Big5Freq[18][29] = 298; + Big5Freq[18][78] = 297; + Big5Freq[18][151] = 296; + Big5Freq[33][127] = 295; + Big5Freq[35][113] = 294; + Big5Freq[10][155] = 293; + Big5Freq[3][76] = 292; + Big5Freq[36][123] = 291; + Big5Freq[13][143] = 290; + Big5Freq[5][135] = 289; + Big5Freq[23][116] = 288; + Big5Freq[6][101] = 287; + Big5Freq[14][74] = 286; + Big5Freq[7][153] = 285; + Big5Freq[3][101] = 284; + Big5Freq[9][74] = 283; + Big5Freq[3][156] = 282; + Big5Freq[4][147] = 281; + Big5Freq[9][12] = 280; + Big5Freq[18][133] = 279; + Big5Freq[4][0] = 278; + Big5Freq[7][155] = 277; + Big5Freq[9][144] = 276; + Big5Freq[23][49] = 275; + Big5Freq[5][89] = 274; + Big5Freq[10][11] = 273; + Big5Freq[3][110] = 272; + Big5Freq[3][40] = 271; + Big5Freq[29][115] = 270; + Big5Freq[9][100] = 269; + Big5Freq[21][67] = 268; + Big5Freq[23][145] = 267; + Big5Freq[10][47] = 266; + Big5Freq[4][31] = 265; + Big5Freq[4][81] = 264; + Big5Freq[22][62] = 263; + Big5Freq[4][28] = 262; + Big5Freq[27][39] = 261; + Big5Freq[27][54] = 260; + Big5Freq[32][46] = 259; + Big5Freq[4][76] = 258; + Big5Freq[26][15] = 257; + Big5Freq[12][154] = 256; + Big5Freq[9][150] = 255; + Big5Freq[15][17] = 254; + Big5Freq[5][129] = 253; + Big5Freq[10][40] = 252; + Big5Freq[13][37] = 251; + Big5Freq[31][104] = 250; + Big5Freq[3][152] = 249; + Big5Freq[5][22] = 248; + Big5Freq[8][48] = 247; + Big5Freq[4][74] = 246; + Big5Freq[6][17] = 245; + Big5Freq[30][82] = 244; + Big5Freq[4][116] = 243; + Big5Freq[16][42] = 242; + Big5Freq[5][55] = 241; + Big5Freq[4][64] = 240; + Big5Freq[14][19] = 239; + Big5Freq[35][82] = 238; + Big5Freq[30][139] = 237; + Big5Freq[26][152] = 236; + Big5Freq[32][32] = 235; + Big5Freq[21][102] = 234; + Big5Freq[10][131] = 233; + Big5Freq[9][128] = 232; + Big5Freq[3][87] = 231; + Big5Freq[4][51] = 230; + Big5Freq[10][15] = 229; + Big5Freq[4][150] = 228; + Big5Freq[7][4] = 227; + Big5Freq[7][51] = 226; + Big5Freq[7][157] = 225; + Big5Freq[4][146] = 224; + Big5Freq[4][91] = 223; + Big5Freq[7][13] = 222; + Big5Freq[17][116] = 221; + Big5Freq[23][21] = 220; + Big5Freq[5][106] = 219; + Big5Freq[14][100] = 218; + Big5Freq[10][152] = 217; + Big5Freq[14][89] = 216; + Big5Freq[6][138] = 215; + Big5Freq[12][157] = 214; + Big5Freq[10][102] = 213; + Big5Freq[19][94] = 212; + Big5Freq[7][74] = 211; + Big5Freq[18][128] = 210; + Big5Freq[27][111] = 209; + Big5Freq[11][57] = 208; + Big5Freq[3][131] = 207; + Big5Freq[30][23] = 206; + Big5Freq[30][126] = 205; + Big5Freq[4][36] = 204; + Big5Freq[26][124] = 203; + Big5Freq[4][19] = 202; + Big5Freq[9][152] = 201; + /* + * Big5Freq[5][0] = 200; Big5Freq[26][57] = 199; Big5Freq[13][155] = + * 198; Big5Freq[3][38] = 197; Big5Freq[9][155] = 196; Big5Freq[28][53] + * = 195; Big5Freq[15][71] = 194; Big5Freq[21][95] = 193; + * Big5Freq[15][112] = 192; Big5Freq[14][138] = 191; Big5Freq[8][18] = + * 190; Big5Freq[20][151] = 189; Big5Freq[37][27] = 188; + * Big5Freq[32][48] = 187; Big5Freq[23][66] = 186; Big5Freq[9][2] = 185; + * Big5Freq[13][133] = 184; Big5Freq[7][127] = 183; Big5Freq[3][11] = + * 182; Big5Freq[12][118] = 181; Big5Freq[13][101] = 180; + * Big5Freq[30][153] = 179; Big5Freq[4][65] = 178; Big5Freq[5][25] = + * 177; Big5Freq[5][140] = 176; Big5Freq[6][25] = 175; Big5Freq[4][52] = + * 174; Big5Freq[30][156] = 173; Big5Freq[16][13] = 172; Big5Freq[21][8] + * = 171; Big5Freq[19][74] = 170; Big5Freq[15][145] = 169; + * Big5Freq[9][15] = 168; Big5Freq[13][82] = 167; Big5Freq[26][86] = + * 166; Big5Freq[18][52] = 165; Big5Freq[6][109] = 164; Big5Freq[10][99] + * = 163; Big5Freq[18][101] = 162; Big5Freq[25][49] = 161; + * Big5Freq[31][79] = 160; Big5Freq[28][20] = 159; Big5Freq[12][115] = + * 158; Big5Freq[15][66] = 157; Big5Freq[11][104] = 156; + * Big5Freq[23][106] = 155; Big5Freq[34][157] = 154; Big5Freq[32][94] = + * 153; Big5Freq[29][88] = 152; Big5Freq[10][46] = 151; + * Big5Freq[13][118] = 150; Big5Freq[20][37] = 149; Big5Freq[12][30] = + * 148; Big5Freq[21][4] = 147; Big5Freq[16][33] = 146; Big5Freq[13][52] + * = 145; Big5Freq[4][7] = 144; Big5Freq[21][49] = 143; Big5Freq[3][27] + * = 142; Big5Freq[16][91] = 141; Big5Freq[5][155] = 140; + * Big5Freq[29][130] = 139; Big5Freq[3][125] = 138; Big5Freq[14][26] = + * 137; Big5Freq[15][39] = 136; Big5Freq[24][110] = 135; + * Big5Freq[7][141] = 134; Big5Freq[21][15] = 133; Big5Freq[32][104] = + * 132; Big5Freq[8][31] = 131; Big5Freq[34][112] = 130; Big5Freq[10][75] + * = 129; Big5Freq[21][23] = 128; Big5Freq[34][131] = 127; + * Big5Freq[12][3] = 126; Big5Freq[10][62] = 125; Big5Freq[9][120] = + * 124; Big5Freq[32][149] = 123; Big5Freq[8][44] = 122; Big5Freq[24][2] + * = 121; Big5Freq[6][148] = 120; Big5Freq[15][103] = 119; + * Big5Freq[36][54] = 118; Big5Freq[36][134] = 117; Big5Freq[11][7] = + * 116; Big5Freq[3][90] = 115; Big5Freq[36][73] = 114; Big5Freq[8][102] + * = 113; Big5Freq[12][87] = 112; Big5Freq[25][64] = 111; Big5Freq[9][1] + * = 110; Big5Freq[24][121] = 109; Big5Freq[5][75] = 108; + * Big5Freq[17][83] = 107; Big5Freq[18][57] = 106; Big5Freq[8][95] = + * 105; Big5Freq[14][36] = 104; Big5Freq[28][113] = 103; + * Big5Freq[12][56] = 102; Big5Freq[14][61] = 101; Big5Freq[25][138] = + * 100; Big5Freq[4][34] = 99; Big5Freq[11][152] = 98; Big5Freq[35][0] = + * 97; Big5Freq[4][15] = 96; Big5Freq[8][82] = 95; Big5Freq[20][73] = + * 94; Big5Freq[25][52] = 93; Big5Freq[24][6] = 92; Big5Freq[21][78] = + * 91; Big5Freq[17][32] = 90; Big5Freq[17][91] = 89; Big5Freq[5][76] = + * 88; Big5Freq[15][60] = 87; Big5Freq[15][150] = 86; Big5Freq[5][80] = + * 85; Big5Freq[15][81] = 84; Big5Freq[28][108] = 83; Big5Freq[18][14] = + * 82; Big5Freq[19][109] = 81; Big5Freq[28][133] = 80; Big5Freq[21][97] + * = 79; Big5Freq[5][105] = 78; Big5Freq[18][114] = 77; Big5Freq[16][95] + * = 76; Big5Freq[5][51] = 75; Big5Freq[3][148] = 74; Big5Freq[22][102] + * = 73; Big5Freq[4][123] = 72; Big5Freq[8][88] = 71; Big5Freq[25][111] + * = 70; Big5Freq[8][149] = 69; Big5Freq[9][48] = 68; Big5Freq[16][126] + * = 67; Big5Freq[33][150] = 66; Big5Freq[9][54] = 65; Big5Freq[29][104] + * = 64; Big5Freq[3][3] = 63; Big5Freq[11][49] = 62; Big5Freq[24][109] = + * 61; Big5Freq[28][116] = 60; Big5Freq[34][113] = 59; Big5Freq[5][3] = + * 58; Big5Freq[21][106] = 57; Big5Freq[4][98] = 56; Big5Freq[12][135] = + * 55; Big5Freq[16][101] = 54; Big5Freq[12][147] = 53; Big5Freq[27][55] + * = 52; Big5Freq[3][5] = 51; Big5Freq[11][101] = 50; Big5Freq[16][157] + * = 49; Big5Freq[22][114] = 48; Big5Freq[18][46] = 47; Big5Freq[4][29] + * = 46; Big5Freq[8][103] = 45; Big5Freq[16][151] = 44; Big5Freq[8][29] + * = 43; Big5Freq[15][114] = 42; Big5Freq[22][70] = 41; + * Big5Freq[13][121] = 40; Big5Freq[7][112] = 39; Big5Freq[20][83] = 38; + * Big5Freq[3][36] = 37; Big5Freq[10][103] = 36; Big5Freq[3][96] = 35; + * Big5Freq[21][79] = 34; Big5Freq[25][120] = 33; Big5Freq[29][121] = + * 32; Big5Freq[23][71] = 31; Big5Freq[21][22] = 30; Big5Freq[18][89] = + * 29; Big5Freq[25][104] = 28; Big5Freq[10][124] = 27; Big5Freq[26][4] = + * 26; Big5Freq[21][136] = 25; Big5Freq[6][112] = 24; Big5Freq[12][103] + * = 23; Big5Freq[17][66] = 22; Big5Freq[13][151] = 21; + * Big5Freq[33][152] = 20; Big5Freq[11][148] = 19; Big5Freq[13][57] = + * 18; Big5Freq[13][41] = 17; Big5Freq[7][60] = 16; Big5Freq[21][29] = + * 15; Big5Freq[9][157] = 14; Big5Freq[24][95] = 13; Big5Freq[15][148] = + * 12; Big5Freq[15][122] = 11; Big5Freq[6][125] = 10; Big5Freq[11][25] = + * 9; Big5Freq[20][55] = 8; Big5Freq[19][84] = 7; Big5Freq[21][82] = 6; + * Big5Freq[24][3] = 5; Big5Freq[13][70] = 4; Big5Freq[6][21] = 3; + * Big5Freq[21][86] = 2; Big5Freq[12][23] = 1; Big5Freq[3][85] = 0; + * EUC_TWFreq[45][90] = 600; + */ + Big5PFreq[41][122] = 600; + Big5PFreq[35][0] = 599; + Big5PFreq[43][15] = 598; + Big5PFreq[35][99] = 597; + Big5PFreq[35][6] = 596; + Big5PFreq[35][8] = 595; + Big5PFreq[38][154] = 594; + Big5PFreq[37][34] = 593; + Big5PFreq[37][115] = 592; + Big5PFreq[36][12] = 591; + Big5PFreq[18][77] = 590; + Big5PFreq[35][100] = 589; + Big5PFreq[35][42] = 588; + Big5PFreq[120][75] = 587; + Big5PFreq[35][23] = 586; + Big5PFreq[13][72] = 585; + Big5PFreq[0][67] = 584; + Big5PFreq[39][172] = 583; + Big5PFreq[22][182] = 582; + Big5PFreq[15][186] = 581; + Big5PFreq[15][165] = 580; + Big5PFreq[35][44] = 579; + Big5PFreq[40][13] = 578; + Big5PFreq[38][1] = 577; + Big5PFreq[37][33] = 576; + Big5PFreq[36][24] = 575; + Big5PFreq[56][4] = 574; + Big5PFreq[35][29] = 573; + Big5PFreq[9][96] = 572; + Big5PFreq[37][62] = 571; + Big5PFreq[48][47] = 570; + Big5PFreq[51][14] = 569; + Big5PFreq[39][122] = 568; + Big5PFreq[44][46] = 567; + Big5PFreq[35][21] = 566; + Big5PFreq[36][8] = 565; + Big5PFreq[36][141] = 564; + Big5PFreq[3][81] = 563; + Big5PFreq[37][155] = 562; + Big5PFreq[42][84] = 561; + Big5PFreq[36][40] = 560; + Big5PFreq[35][103] = 559; + Big5PFreq[11][84] = 558; + Big5PFreq[45][33] = 557; + Big5PFreq[121][79] = 556; + Big5PFreq[2][77] = 555; + Big5PFreq[36][41] = 554; + Big5PFreq[37][47] = 553; + Big5PFreq[39][125] = 552; + Big5PFreq[37][26] = 551; + Big5PFreq[35][48] = 550; + Big5PFreq[35][28] = 549; + Big5PFreq[35][159] = 548; + Big5PFreq[37][40] = 547; + Big5PFreq[35][145] = 546; + Big5PFreq[37][147] = 545; + Big5PFreq[46][160] = 544; + Big5PFreq[37][46] = 543; + Big5PFreq[50][99] = 542; + Big5PFreq[52][13] = 541; + Big5PFreq[10][82] = 540; + Big5PFreq[35][169] = 539; + Big5PFreq[35][31] = 538; + Big5PFreq[47][31] = 537; + Big5PFreq[18][79] = 536; + Big5PFreq[16][113] = 535; + Big5PFreq[37][104] = 534; + Big5PFreq[39][134] = 533; + Big5PFreq[36][53] = 532; + Big5PFreq[38][0] = 531; + Big5PFreq[4][86] = 530; + Big5PFreq[54][17] = 529; + Big5PFreq[43][157] = 528; + Big5PFreq[35][165] = 527; + Big5PFreq[69][147] = 526; + Big5PFreq[117][95] = 525; + Big5PFreq[35][162] = 524; + Big5PFreq[35][17] = 523; + Big5PFreq[36][142] = 522; + Big5PFreq[36][4] = 521; + Big5PFreq[37][166] = 520; + Big5PFreq[35][168] = 519; + Big5PFreq[35][19] = 518; + Big5PFreq[37][48] = 517; + Big5PFreq[42][37] = 516; + Big5PFreq[40][146] = 515; + Big5PFreq[36][123] = 514; + Big5PFreq[22][41] = 513; + Big5PFreq[20][119] = 512; + Big5PFreq[2][74] = 511; + Big5PFreq[44][113] = 510; + Big5PFreq[35][125] = 509; + Big5PFreq[37][16] = 508; + Big5PFreq[35][20] = 507; + Big5PFreq[35][55] = 506; + Big5PFreq[37][145] = 505; + Big5PFreq[0][88] = 504; + Big5PFreq[3][94] = 503; + Big5PFreq[6][65] = 502; + Big5PFreq[26][15] = 501; + Big5PFreq[41][126] = 500; + Big5PFreq[36][129] = 499; + Big5PFreq[31][75] = 498; + Big5PFreq[19][61] = 497; + Big5PFreq[35][128] = 496; + Big5PFreq[29][79] = 495; + Big5PFreq[36][62] = 494; + Big5PFreq[37][189] = 493; + Big5PFreq[39][109] = 492; + Big5PFreq[39][135] = 491; + Big5PFreq[72][15] = 490; + Big5PFreq[47][106] = 489; + Big5PFreq[54][14] = 488; + Big5PFreq[24][52] = 487; + Big5PFreq[38][162] = 486; + Big5PFreq[41][43] = 485; + Big5PFreq[37][121] = 484; + Big5PFreq[14][66] = 483; + Big5PFreq[37][30] = 482; + Big5PFreq[35][7] = 481; + Big5PFreq[49][58] = 480; + Big5PFreq[43][188] = 479; + Big5PFreq[24][66] = 478; + Big5PFreq[35][171] = 477; + Big5PFreq[40][186] = 476; + Big5PFreq[39][164] = 475; + Big5PFreq[78][186] = 474; + Big5PFreq[8][72] = 473; + Big5PFreq[36][190] = 472; + Big5PFreq[35][53] = 471; + Big5PFreq[35][54] = 470; + Big5PFreq[22][159] = 469; + Big5PFreq[35][9] = 468; + Big5PFreq[41][140] = 467; + Big5PFreq[37][22] = 466; + Big5PFreq[48][97] = 465; + Big5PFreq[50][97] = 464; + Big5PFreq[36][127] = 463; + Big5PFreq[37][23] = 462; + Big5PFreq[40][55] = 461; + Big5PFreq[35][43] = 460; + Big5PFreq[26][22] = 459; + Big5PFreq[35][15] = 458; + Big5PFreq[72][179] = 457; + Big5PFreq[20][129] = 456; + Big5PFreq[52][101] = 455; + Big5PFreq[35][12] = 454; + Big5PFreq[42][156] = 453; + Big5PFreq[15][157] = 452; + Big5PFreq[50][140] = 451; + Big5PFreq[26][28] = 450; + Big5PFreq[54][51] = 449; + Big5PFreq[35][112] = 448; + Big5PFreq[36][116] = 447; + Big5PFreq[42][11] = 446; + Big5PFreq[37][172] = 445; + Big5PFreq[37][29] = 444; + Big5PFreq[44][107] = 443; + Big5PFreq[50][17] = 442; + Big5PFreq[39][107] = 441; + Big5PFreq[19][109] = 440; + Big5PFreq[36][60] = 439; + Big5PFreq[49][132] = 438; + Big5PFreq[26][16] = 437; + Big5PFreq[43][155] = 436; + Big5PFreq[37][120] = 435; + Big5PFreq[15][159] = 434; + Big5PFreq[43][6] = 433; + Big5PFreq[45][188] = 432; + Big5PFreq[35][38] = 431; + Big5PFreq[39][143] = 430; + Big5PFreq[48][144] = 429; + Big5PFreq[37][168] = 428; + Big5PFreq[37][1] = 427; + Big5PFreq[36][109] = 426; + Big5PFreq[46][53] = 425; + Big5PFreq[38][54] = 424; + Big5PFreq[36][0] = 423; + Big5PFreq[72][33] = 422; + Big5PFreq[42][8] = 421; + Big5PFreq[36][31] = 420; + Big5PFreq[35][150] = 419; + Big5PFreq[118][93] = 418; + Big5PFreq[37][61] = 417; + Big5PFreq[0][85] = 416; + Big5PFreq[36][27] = 415; + Big5PFreq[35][134] = 414; + Big5PFreq[36][145] = 413; + Big5PFreq[6][96] = 412; + Big5PFreq[36][14] = 411; + Big5PFreq[16][36] = 410; + Big5PFreq[15][175] = 409; + Big5PFreq[35][10] = 408; + Big5PFreq[36][189] = 407; + Big5PFreq[35][51] = 406; + Big5PFreq[35][109] = 405; + Big5PFreq[35][147] = 404; + Big5PFreq[35][180] = 403; + Big5PFreq[72][5] = 402; + Big5PFreq[36][107] = 401; + Big5PFreq[49][116] = 400; + Big5PFreq[73][30] = 399; + Big5PFreq[6][90] = 398; + Big5PFreq[2][70] = 397; + Big5PFreq[17][141] = 396; + Big5PFreq[35][62] = 395; + Big5PFreq[16][180] = 394; + Big5PFreq[4][91] = 393; + Big5PFreq[15][171] = 392; + Big5PFreq[35][177] = 391; + Big5PFreq[37][173] = 390; + Big5PFreq[16][121] = 389; + Big5PFreq[35][5] = 388; + Big5PFreq[46][122] = 387; + Big5PFreq[40][138] = 386; + Big5PFreq[50][49] = 385; + Big5PFreq[36][152] = 384; + Big5PFreq[13][43] = 383; + Big5PFreq[9][88] = 382; + Big5PFreq[36][159] = 381; + Big5PFreq[27][62] = 380; + Big5PFreq[40][18] = 379; + Big5PFreq[17][129] = 378; + Big5PFreq[43][97] = 377; + Big5PFreq[13][131] = 376; + Big5PFreq[46][107] = 375; + Big5PFreq[60][64] = 374; + Big5PFreq[36][179] = 373; + Big5PFreq[37][55] = 372; + Big5PFreq[41][173] = 371; + Big5PFreq[44][172] = 370; + Big5PFreq[23][187] = 369; + Big5PFreq[36][149] = 368; + Big5PFreq[17][125] = 367; + Big5PFreq[55][180] = 366; + Big5PFreq[51][129] = 365; + Big5PFreq[36][51] = 364; + Big5PFreq[37][122] = 363; + Big5PFreq[48][32] = 362; + Big5PFreq[51][99] = 361; + Big5PFreq[54][16] = 360; + Big5PFreq[41][183] = 359; + Big5PFreq[37][179] = 358; + Big5PFreq[38][179] = 357; + Big5PFreq[35][143] = 356; + Big5PFreq[37][24] = 355; + Big5PFreq[40][177] = 354; + Big5PFreq[47][117] = 353; + Big5PFreq[39][52] = 352; + Big5PFreq[22][99] = 351; + Big5PFreq[40][142] = 350; + Big5PFreq[36][49] = 349; + Big5PFreq[38][17] = 348; + Big5PFreq[39][188] = 347; + Big5PFreq[36][186] = 346; + Big5PFreq[35][189] = 345; + Big5PFreq[41][7] = 344; + Big5PFreq[18][91] = 343; + Big5PFreq[43][137] = 342; + Big5PFreq[35][142] = 341; + Big5PFreq[35][117] = 340; + Big5PFreq[39][138] = 339; + Big5PFreq[16][59] = 338; + Big5PFreq[39][174] = 337; + Big5PFreq[55][145] = 336; + Big5PFreq[37][21] = 335; + Big5PFreq[36][180] = 334; + Big5PFreq[37][156] = 333; + Big5PFreq[49][13] = 332; + Big5PFreq[41][107] = 331; + Big5PFreq[36][56] = 330; + Big5PFreq[53][8] = 329; + Big5PFreq[22][114] = 328; + Big5PFreq[5][95] = 327; + Big5PFreq[37][0] = 326; + Big5PFreq[26][183] = 325; + Big5PFreq[22][66] = 324; + Big5PFreq[35][58] = 323; + Big5PFreq[48][117] = 322; + Big5PFreq[36][102] = 321; + Big5PFreq[22][122] = 320; + Big5PFreq[35][11] = 319; + Big5PFreq[46][19] = 318; + Big5PFreq[22][49] = 317; + Big5PFreq[48][166] = 316; + Big5PFreq[41][125] = 315; + Big5PFreq[41][1] = 314; + Big5PFreq[35][178] = 313; + Big5PFreq[41][12] = 312; + Big5PFreq[26][167] = 311; + Big5PFreq[42][152] = 310; + Big5PFreq[42][46] = 309; + Big5PFreq[42][151] = 308; + Big5PFreq[20][135] = 307; + Big5PFreq[37][162] = 306; + Big5PFreq[37][50] = 305; + Big5PFreq[22][185] = 304; + Big5PFreq[36][166] = 303; + Big5PFreq[19][40] = 302; + Big5PFreq[22][107] = 301; + Big5PFreq[22][102] = 300; + Big5PFreq[57][162] = 299; + Big5PFreq[22][124] = 298; + Big5PFreq[37][138] = 297; + Big5PFreq[37][25] = 296; + Big5PFreq[0][69] = 295; + Big5PFreq[43][172] = 294; + Big5PFreq[42][167] = 293; + Big5PFreq[35][120] = 292; + Big5PFreq[41][128] = 291; + Big5PFreq[2][88] = 290; + Big5PFreq[20][123] = 289; + Big5PFreq[35][123] = 288; + Big5PFreq[36][28] = 287; + Big5PFreq[42][188] = 286; + Big5PFreq[42][164] = 285; + Big5PFreq[42][4] = 284; + Big5PFreq[43][57] = 283; + Big5PFreq[39][3] = 282; + Big5PFreq[42][3] = 281; + Big5PFreq[57][158] = 280; + Big5PFreq[35][146] = 279; + Big5PFreq[24][54] = 278; + Big5PFreq[13][110] = 277; + Big5PFreq[23][132] = 276; + Big5PFreq[26][102] = 275; + Big5PFreq[55][178] = 274; + Big5PFreq[17][117] = 273; + Big5PFreq[41][161] = 272; + Big5PFreq[38][150] = 271; + Big5PFreq[10][71] = 270; + Big5PFreq[47][60] = 269; + Big5PFreq[16][114] = 268; + Big5PFreq[21][47] = 267; + Big5PFreq[39][101] = 266; + Big5PFreq[18][45] = 265; + Big5PFreq[40][121] = 264; + Big5PFreq[45][41] = 263; + Big5PFreq[22][167] = 262; + Big5PFreq[26][149] = 261; + Big5PFreq[15][189] = 260; + Big5PFreq[41][177] = 259; + Big5PFreq[46][36] = 258; + Big5PFreq[20][40] = 257; + Big5PFreq[41][54] = 256; + Big5PFreq[3][87] = 255; + Big5PFreq[40][16] = 254; + Big5PFreq[42][15] = 253; + Big5PFreq[11][83] = 252; + Big5PFreq[0][94] = 251; + Big5PFreq[122][81] = 250; + Big5PFreq[41][26] = 249; + Big5PFreq[36][34] = 248; + Big5PFreq[44][148] = 247; + Big5PFreq[35][3] = 246; + Big5PFreq[36][114] = 245; + Big5PFreq[42][112] = 244; + Big5PFreq[35][183] = 243; + Big5PFreq[49][73] = 242; + Big5PFreq[39][2] = 241; + Big5PFreq[38][121] = 240; + Big5PFreq[44][114] = 239; + Big5PFreq[49][32] = 238; + Big5PFreq[1][65] = 237; + Big5PFreq[38][25] = 236; + Big5PFreq[39][4] = 235; + Big5PFreq[42][62] = 234; + Big5PFreq[35][40] = 233; + Big5PFreq[24][2] = 232; + Big5PFreq[53][49] = 231; + Big5PFreq[41][133] = 230; + Big5PFreq[43][134] = 229; + Big5PFreq[3][83] = 228; + Big5PFreq[38][158] = 227; + Big5PFreq[24][17] = 226; + Big5PFreq[52][59] = 225; + Big5PFreq[38][41] = 224; + Big5PFreq[37][127] = 223; + Big5PFreq[22][175] = 222; + Big5PFreq[44][30] = 221; + Big5PFreq[47][178] = 220; + Big5PFreq[43][99] = 219; + Big5PFreq[19][4] = 218; + Big5PFreq[37][97] = 217; + Big5PFreq[38][181] = 216; + Big5PFreq[45][103] = 215; + Big5PFreq[1][86] = 214; + Big5PFreq[40][15] = 213; + Big5PFreq[22][136] = 212; + Big5PFreq[75][165] = 211; + Big5PFreq[36][15] = 210; + Big5PFreq[46][80] = 209; + Big5PFreq[59][55] = 208; + Big5PFreq[37][108] = 207; + Big5PFreq[21][109] = 206; + Big5PFreq[24][165] = 205; + Big5PFreq[79][158] = 204; + Big5PFreq[44][139] = 203; + Big5PFreq[36][124] = 202; + Big5PFreq[42][185] = 201; + Big5PFreq[39][186] = 200; + Big5PFreq[22][128] = 199; + Big5PFreq[40][44] = 198; + Big5PFreq[41][105] = 197; + Big5PFreq[1][70] = 196; + Big5PFreq[1][68] = 195; + Big5PFreq[53][22] = 194; + Big5PFreq[36][54] = 193; + Big5PFreq[47][147] = 192; + Big5PFreq[35][36] = 191; + Big5PFreq[35][185] = 190; + Big5PFreq[45][37] = 189; + Big5PFreq[43][163] = 188; + Big5PFreq[56][115] = 187; + Big5PFreq[38][164] = 186; + Big5PFreq[35][141] = 185; + Big5PFreq[42][132] = 184; + Big5PFreq[46][120] = 183; + Big5PFreq[69][142] = 182; + Big5PFreq[38][175] = 181; + Big5PFreq[22][112] = 180; + Big5PFreq[38][142] = 179; + Big5PFreq[40][37] = 178; + Big5PFreq[37][109] = 177; + Big5PFreq[40][144] = 176; + Big5PFreq[44][117] = 175; + Big5PFreq[35][181] = 174; + Big5PFreq[26][105] = 173; + Big5PFreq[16][48] = 172; + Big5PFreq[44][122] = 171; + Big5PFreq[12][86] = 170; + Big5PFreq[84][53] = 169; + Big5PFreq[17][44] = 168; + Big5PFreq[59][54] = 167; + Big5PFreq[36][98] = 166; + Big5PFreq[45][115] = 165; + Big5PFreq[73][9] = 164; + Big5PFreq[44][123] = 163; + Big5PFreq[37][188] = 162; + Big5PFreq[51][117] = 161; + Big5PFreq[15][156] = 160; + Big5PFreq[36][155] = 159; + Big5PFreq[44][25] = 158; + Big5PFreq[38][12] = 157; + Big5PFreq[38][140] = 156; + Big5PFreq[23][4] = 155; + Big5PFreq[45][149] = 154; + Big5PFreq[22][189] = 153; + Big5PFreq[38][147] = 152; + Big5PFreq[27][5] = 151; + Big5PFreq[22][42] = 150; + Big5PFreq[3][68] = 149; + Big5PFreq[39][51] = 148; + Big5PFreq[36][29] = 147; + Big5PFreq[20][108] = 146; + Big5PFreq[50][57] = 145; + Big5PFreq[55][104] = 144; + Big5PFreq[22][46] = 143; + Big5PFreq[18][164] = 142; + Big5PFreq[50][159] = 141; + Big5PFreq[85][131] = 140; + Big5PFreq[26][79] = 139; + Big5PFreq[38][100] = 138; + Big5PFreq[53][112] = 137; + Big5PFreq[20][190] = 136; + Big5PFreq[14][69] = 135; + Big5PFreq[23][11] = 134; + Big5PFreq[40][114] = 133; + Big5PFreq[40][148] = 132; + Big5PFreq[53][130] = 131; + Big5PFreq[36][2] = 130; + Big5PFreq[66][82] = 129; + Big5PFreq[45][166] = 128; + Big5PFreq[4][88] = 127; + Big5PFreq[16][57] = 126; + Big5PFreq[22][116] = 125; + Big5PFreq[36][108] = 124; + Big5PFreq[13][48] = 123; + Big5PFreq[54][12] = 122; + Big5PFreq[40][136] = 121; + Big5PFreq[36][128] = 120; + Big5PFreq[23][6] = 119; + Big5PFreq[38][125] = 118; + Big5PFreq[45][154] = 117; + Big5PFreq[51][127] = 116; + Big5PFreq[44][163] = 115; + Big5PFreq[16][173] = 114; + Big5PFreq[43][49] = 113; + Big5PFreq[20][112] = 112; + Big5PFreq[15][168] = 111; + Big5PFreq[35][129] = 110; + Big5PFreq[20][45] = 109; + Big5PFreq[38][10] = 108; + Big5PFreq[57][171] = 107; + Big5PFreq[44][190] = 106; + Big5PFreq[40][56] = 105; + Big5PFreq[36][156] = 104; + Big5PFreq[3][88] = 103; + Big5PFreq[50][122] = 102; + Big5PFreq[36][7] = 101; + Big5PFreq[39][43] = 100; + Big5PFreq[15][166] = 99; + Big5PFreq[42][136] = 98; + Big5PFreq[22][131] = 97; + Big5PFreq[44][23] = 96; + Big5PFreq[54][147] = 95; + Big5PFreq[41][32] = 94; + Big5PFreq[23][121] = 93; + Big5PFreq[39][108] = 92; + Big5PFreq[2][78] = 91; + Big5PFreq[40][155] = 90; + Big5PFreq[55][51] = 89; + Big5PFreq[19][34] = 88; + Big5PFreq[48][128] = 87; + Big5PFreq[48][159] = 86; + Big5PFreq[20][70] = 85; + Big5PFreq[34][71] = 84; + Big5PFreq[16][31] = 83; + Big5PFreq[42][157] = 82; + Big5PFreq[20][44] = 81; + Big5PFreq[11][92] = 80; + Big5PFreq[44][180] = 79; + Big5PFreq[84][33] = 78; + Big5PFreq[16][116] = 77; + Big5PFreq[61][163] = 76; + Big5PFreq[35][164] = 75; + Big5PFreq[36][42] = 74; + Big5PFreq[13][40] = 73; + Big5PFreq[43][176] = 72; + Big5PFreq[2][66] = 71; + Big5PFreq[20][133] = 70; + Big5PFreq[36][65] = 69; + Big5PFreq[38][33] = 68; + Big5PFreq[12][91] = 67; + Big5PFreq[36][26] = 66; + Big5PFreq[15][174] = 65; + Big5PFreq[77][32] = 64; + Big5PFreq[16][1] = 63; + Big5PFreq[25][86] = 62; + Big5PFreq[17][13] = 61; + Big5PFreq[5][75] = 60; + Big5PFreq[36][52] = 59; + Big5PFreq[51][164] = 58; + Big5PFreq[12][85] = 57; + Big5PFreq[39][168] = 56; + Big5PFreq[43][16] = 55; + Big5PFreq[40][69] = 54; + Big5PFreq[26][108] = 53; + Big5PFreq[51][56] = 52; + Big5PFreq[16][37] = 51; + Big5PFreq[40][29] = 50; + Big5PFreq[46][171] = 49; + Big5PFreq[40][128] = 48; + Big5PFreq[72][114] = 47; + Big5PFreq[21][103] = 46; + Big5PFreq[22][44] = 45; + Big5PFreq[40][115] = 44; + Big5PFreq[43][7] = 43; + Big5PFreq[43][153] = 42; + Big5PFreq[17][20] = 41; + Big5PFreq[16][49] = 40; + Big5PFreq[36][57] = 39; + Big5PFreq[18][38] = 38; + Big5PFreq[45][184] = 37; + Big5PFreq[37][167] = 36; + Big5PFreq[26][106] = 35; + Big5PFreq[61][121] = 34; + Big5PFreq[89][140] = 33; + Big5PFreq[46][61] = 32; + Big5PFreq[39][163] = 31; + Big5PFreq[40][62] = 30; + Big5PFreq[38][165] = 29; + Big5PFreq[47][37] = 28; + Big5PFreq[18][155] = 27; + Big5PFreq[20][33] = 26; + Big5PFreq[29][90] = 25; + Big5PFreq[20][103] = 24; + Big5PFreq[37][51] = 23; + Big5PFreq[57][0] = 22; + Big5PFreq[40][31] = 21; + Big5PFreq[45][32] = 20; + Big5PFreq[59][23] = 19; + Big5PFreq[18][47] = 18; + Big5PFreq[45][134] = 17; + Big5PFreq[37][59] = 16; + Big5PFreq[21][128] = 15; + Big5PFreq[36][106] = 14; + Big5PFreq[31][39] = 13; + Big5PFreq[40][182] = 12; + Big5PFreq[52][155] = 11; + Big5PFreq[42][166] = 10; + Big5PFreq[35][27] = 9; + Big5PFreq[38][3] = 8; + Big5PFreq[13][44] = 7; + Big5PFreq[58][157] = 6; + Big5PFreq[47][51] = 5; + Big5PFreq[41][37] = 4; + Big5PFreq[41][172] = 3; + Big5PFreq[51][165] = 2; + Big5PFreq[15][161] = 1; + Big5PFreq[24][181] = 0; + EUC_TWFreq[48][49] = 599; + EUC_TWFreq[35][65] = 598; + EUC_TWFreq[41][27] = 597; + EUC_TWFreq[35][0] = 596; + EUC_TWFreq[39][19] = 595; + EUC_TWFreq[35][42] = 594; + EUC_TWFreq[38][66] = 593; + EUC_TWFreq[35][8] = 592; + EUC_TWFreq[35][6] = 591; + EUC_TWFreq[35][66] = 590; + EUC_TWFreq[43][14] = 589; + EUC_TWFreq[69][80] = 588; + EUC_TWFreq[50][48] = 587; + EUC_TWFreq[36][71] = 586; + EUC_TWFreq[37][10] = 585; + EUC_TWFreq[60][52] = 584; + EUC_TWFreq[51][21] = 583; + EUC_TWFreq[40][2] = 582; + EUC_TWFreq[67][35] = 581; + EUC_TWFreq[38][78] = 580; + EUC_TWFreq[49][18] = 579; + EUC_TWFreq[35][23] = 578; + EUC_TWFreq[42][83] = 577; + EUC_TWFreq[79][47] = 576; + EUC_TWFreq[61][82] = 575; + EUC_TWFreq[38][7] = 574; + EUC_TWFreq[35][29] = 573; + EUC_TWFreq[37][77] = 572; + EUC_TWFreq[54][67] = 571; + EUC_TWFreq[38][80] = 570; + EUC_TWFreq[52][74] = 569; + EUC_TWFreq[36][37] = 568; + EUC_TWFreq[74][8] = 567; + EUC_TWFreq[41][83] = 566; + EUC_TWFreq[36][75] = 565; + EUC_TWFreq[49][63] = 564; + EUC_TWFreq[42][58] = 563; + EUC_TWFreq[56][33] = 562; + EUC_TWFreq[37][76] = 561; + EUC_TWFreq[62][39] = 560; + EUC_TWFreq[35][21] = 559; + EUC_TWFreq[70][19] = 558; + EUC_TWFreq[77][88] = 557; + EUC_TWFreq[51][14] = 556; + EUC_TWFreq[36][17] = 555; + EUC_TWFreq[44][51] = 554; + EUC_TWFreq[38][72] = 553; + EUC_TWFreq[74][90] = 552; + EUC_TWFreq[35][48] = 551; + EUC_TWFreq[35][69] = 550; + EUC_TWFreq[66][86] = 549; + EUC_TWFreq[57][20] = 548; + EUC_TWFreq[35][53] = 547; + EUC_TWFreq[36][87] = 546; + EUC_TWFreq[84][67] = 545; + EUC_TWFreq[70][56] = 544; + EUC_TWFreq[71][54] = 543; + EUC_TWFreq[60][70] = 542; + EUC_TWFreq[80][1] = 541; + EUC_TWFreq[39][59] = 540; + EUC_TWFreq[39][51] = 539; + EUC_TWFreq[35][44] = 538; + EUC_TWFreq[48][4] = 537; + EUC_TWFreq[55][24] = 536; + EUC_TWFreq[52][4] = 535; + EUC_TWFreq[54][26] = 534; + EUC_TWFreq[36][31] = 533; + EUC_TWFreq[37][22] = 532; + EUC_TWFreq[37][9] = 531; + EUC_TWFreq[46][0] = 530; + EUC_TWFreq[56][46] = 529; + EUC_TWFreq[47][93] = 528; + EUC_TWFreq[37][25] = 527; + EUC_TWFreq[39][8] = 526; + EUC_TWFreq[46][73] = 525; + EUC_TWFreq[38][48] = 524; + EUC_TWFreq[39][83] = 523; + EUC_TWFreq[60][92] = 522; + EUC_TWFreq[70][11] = 521; + EUC_TWFreq[63][84] = 520; + EUC_TWFreq[38][65] = 519; + EUC_TWFreq[45][45] = 518; + EUC_TWFreq[63][49] = 517; + EUC_TWFreq[63][50] = 516; + EUC_TWFreq[39][93] = 515; + EUC_TWFreq[68][20] = 514; + EUC_TWFreq[44][84] = 513; + EUC_TWFreq[66][34] = 512; + EUC_TWFreq[37][58] = 511; + EUC_TWFreq[39][0] = 510; + EUC_TWFreq[59][1] = 509; + EUC_TWFreq[47][8] = 508; + EUC_TWFreq[61][17] = 507; + EUC_TWFreq[53][87] = 506; + EUC_TWFreq[67][26] = 505; + EUC_TWFreq[43][46] = 504; + EUC_TWFreq[38][61] = 503; + EUC_TWFreq[45][9] = 502; + EUC_TWFreq[66][83] = 501; + EUC_TWFreq[43][88] = 500; + EUC_TWFreq[85][20] = 499; + EUC_TWFreq[57][36] = 498; + EUC_TWFreq[43][6] = 497; + EUC_TWFreq[86][77] = 496; + EUC_TWFreq[42][70] = 495; + EUC_TWFreq[49][78] = 494; + EUC_TWFreq[36][40] = 493; + EUC_TWFreq[42][71] = 492; + EUC_TWFreq[58][49] = 491; + EUC_TWFreq[35][20] = 490; + EUC_TWFreq[76][20] = 489; + EUC_TWFreq[39][25] = 488; + EUC_TWFreq[40][34] = 487; + EUC_TWFreq[39][76] = 486; + EUC_TWFreq[40][1] = 485; + EUC_TWFreq[59][0] = 484; + EUC_TWFreq[39][70] = 483; + EUC_TWFreq[46][14] = 482; + EUC_TWFreq[68][77] = 481; + EUC_TWFreq[38][55] = 480; + EUC_TWFreq[35][78] = 479; + EUC_TWFreq[84][44] = 478; + EUC_TWFreq[36][41] = 477; + EUC_TWFreq[37][62] = 476; + EUC_TWFreq[65][67] = 475; + EUC_TWFreq[69][66] = 474; + EUC_TWFreq[73][55] = 473; + EUC_TWFreq[71][49] = 472; + EUC_TWFreq[66][87] = 471; + EUC_TWFreq[38][33] = 470; + EUC_TWFreq[64][61] = 469; + EUC_TWFreq[35][7] = 468; + EUC_TWFreq[47][49] = 467; + EUC_TWFreq[56][14] = 466; + EUC_TWFreq[36][49] = 465; + EUC_TWFreq[50][81] = 464; + EUC_TWFreq[55][76] = 463; + EUC_TWFreq[35][19] = 462; + EUC_TWFreq[44][47] = 461; + EUC_TWFreq[35][15] = 460; + EUC_TWFreq[82][59] = 459; + EUC_TWFreq[35][43] = 458; + EUC_TWFreq[73][0] = 457; + EUC_TWFreq[57][83] = 456; + EUC_TWFreq[42][46] = 455; + EUC_TWFreq[36][0] = 454; + EUC_TWFreq[70][88] = 453; + EUC_TWFreq[42][22] = 452; + EUC_TWFreq[46][58] = 451; + EUC_TWFreq[36][34] = 450; + EUC_TWFreq[39][24] = 449; + EUC_TWFreq[35][55] = 448; + EUC_TWFreq[44][91] = 447; + EUC_TWFreq[37][51] = 446; + EUC_TWFreq[36][19] = 445; + EUC_TWFreq[69][90] = 444; + EUC_TWFreq[55][35] = 443; + EUC_TWFreq[35][54] = 442; + EUC_TWFreq[49][61] = 441; + EUC_TWFreq[36][67] = 440; + EUC_TWFreq[88][34] = 439; + EUC_TWFreq[35][17] = 438; + EUC_TWFreq[65][69] = 437; + EUC_TWFreq[74][89] = 436; + EUC_TWFreq[37][31] = 435; + EUC_TWFreq[43][48] = 434; + EUC_TWFreq[89][27] = 433; + EUC_TWFreq[42][79] = 432; + EUC_TWFreq[69][57] = 431; + EUC_TWFreq[36][13] = 430; + EUC_TWFreq[35][62] = 429; + EUC_TWFreq[65][47] = 428; + EUC_TWFreq[56][8] = 427; + EUC_TWFreq[38][79] = 426; + EUC_TWFreq[37][64] = 425; + EUC_TWFreq[64][64] = 424; + EUC_TWFreq[38][53] = 423; + EUC_TWFreq[38][31] = 422; + EUC_TWFreq[56][81] = 421; + EUC_TWFreq[36][22] = 420; + EUC_TWFreq[43][4] = 419; + EUC_TWFreq[36][90] = 418; + EUC_TWFreq[38][62] = 417; + EUC_TWFreq[66][85] = 416; + EUC_TWFreq[39][1] = 415; + EUC_TWFreq[59][40] = 414; + EUC_TWFreq[58][93] = 413; + EUC_TWFreq[44][43] = 412; + EUC_TWFreq[39][49] = 411; + EUC_TWFreq[64][2] = 410; + EUC_TWFreq[41][35] = 409; + EUC_TWFreq[60][22] = 408; + EUC_TWFreq[35][91] = 407; + EUC_TWFreq[78][1] = 406; + EUC_TWFreq[36][14] = 405; + EUC_TWFreq[82][29] = 404; + EUC_TWFreq[52][86] = 403; + EUC_TWFreq[40][16] = 402; + EUC_TWFreq[91][52] = 401; + EUC_TWFreq[50][75] = 400; + EUC_TWFreq[64][30] = 399; + EUC_TWFreq[90][78] = 398; + EUC_TWFreq[36][52] = 397; + EUC_TWFreq[55][87] = 396; + EUC_TWFreq[57][5] = 395; + EUC_TWFreq[57][31] = 394; + EUC_TWFreq[42][35] = 393; + EUC_TWFreq[69][50] = 392; + EUC_TWFreq[45][8] = 391; + EUC_TWFreq[50][87] = 390; + EUC_TWFreq[69][55] = 389; + EUC_TWFreq[92][3] = 388; + EUC_TWFreq[36][43] = 387; + EUC_TWFreq[64][10] = 386; + EUC_TWFreq[56][25] = 385; + EUC_TWFreq[60][68] = 384; + EUC_TWFreq[51][46] = 383; + EUC_TWFreq[50][0] = 382; + EUC_TWFreq[38][30] = 381; + EUC_TWFreq[50][85] = 380; + EUC_TWFreq[60][54] = 379; + EUC_TWFreq[73][6] = 378; + EUC_TWFreq[73][28] = 377; + EUC_TWFreq[56][19] = 376; + EUC_TWFreq[62][69] = 375; + EUC_TWFreq[81][66] = 374; + EUC_TWFreq[40][32] = 373; + EUC_TWFreq[76][31] = 372; + EUC_TWFreq[35][10] = 371; + EUC_TWFreq[41][37] = 370; + EUC_TWFreq[52][82] = 369; + EUC_TWFreq[91][72] = 368; + EUC_TWFreq[37][29] = 367; + EUC_TWFreq[56][30] = 366; + EUC_TWFreq[37][80] = 365; + EUC_TWFreq[81][56] = 364; + EUC_TWFreq[70][3] = 363; + EUC_TWFreq[76][15] = 362; + EUC_TWFreq[46][47] = 361; + EUC_TWFreq[35][88] = 360; + EUC_TWFreq[61][58] = 359; + EUC_TWFreq[37][37] = 358; + EUC_TWFreq[57][22] = 357; + EUC_TWFreq[41][23] = 356; + EUC_TWFreq[90][66] = 355; + EUC_TWFreq[39][60] = 354; + EUC_TWFreq[38][0] = 353; + EUC_TWFreq[37][87] = 352; + EUC_TWFreq[46][2] = 351; + EUC_TWFreq[38][56] = 350; + EUC_TWFreq[58][11] = 349; + EUC_TWFreq[48][10] = 348; + EUC_TWFreq[74][4] = 347; + EUC_TWFreq[40][42] = 346; + EUC_TWFreq[41][52] = 345; + EUC_TWFreq[61][92] = 344; + EUC_TWFreq[39][50] = 343; + EUC_TWFreq[47][88] = 342; + EUC_TWFreq[88][36] = 341; + EUC_TWFreq[45][73] = 340; + EUC_TWFreq[82][3] = 339; + EUC_TWFreq[61][36] = 338; + EUC_TWFreq[60][33] = 337; + EUC_TWFreq[38][27] = 336; + EUC_TWFreq[35][83] = 335; + EUC_TWFreq[65][24] = 334; + EUC_TWFreq[73][10] = 333; + EUC_TWFreq[41][13] = 332; + EUC_TWFreq[50][27] = 331; + EUC_TWFreq[59][50] = 330; + EUC_TWFreq[42][45] = 329; + EUC_TWFreq[55][19] = 328; + EUC_TWFreq[36][77] = 327; + EUC_TWFreq[69][31] = 326; + EUC_TWFreq[60][7] = 325; + EUC_TWFreq[40][88] = 324; + EUC_TWFreq[57][56] = 323; + EUC_TWFreq[50][50] = 322; + EUC_TWFreq[42][37] = 321; + EUC_TWFreq[38][82] = 320; + EUC_TWFreq[52][25] = 319; + EUC_TWFreq[42][67] = 318; + EUC_TWFreq[48][40] = 317; + EUC_TWFreq[45][81] = 316; + EUC_TWFreq[57][14] = 315; + EUC_TWFreq[42][13] = 314; + EUC_TWFreq[78][0] = 313; + EUC_TWFreq[35][51] = 312; + EUC_TWFreq[41][67] = 311; + EUC_TWFreq[64][23] = 310; + EUC_TWFreq[36][65] = 309; + EUC_TWFreq[48][50] = 308; + EUC_TWFreq[46][69] = 307; + EUC_TWFreq[47][89] = 306; + EUC_TWFreq[41][48] = 305; + EUC_TWFreq[60][56] = 304; + EUC_TWFreq[44][82] = 303; + EUC_TWFreq[47][35] = 302; + EUC_TWFreq[49][3] = 301; + EUC_TWFreq[49][69] = 300; + EUC_TWFreq[45][93] = 299; + EUC_TWFreq[60][34] = 298; + EUC_TWFreq[60][82] = 297; + EUC_TWFreq[61][61] = 296; + EUC_TWFreq[86][42] = 295; + EUC_TWFreq[89][60] = 294; + EUC_TWFreq[48][31] = 293; + EUC_TWFreq[35][75] = 292; + EUC_TWFreq[91][39] = 291; + EUC_TWFreq[53][19] = 290; + EUC_TWFreq[39][72] = 289; + EUC_TWFreq[69][59] = 288; + EUC_TWFreq[41][7] = 287; + EUC_TWFreq[54][13] = 286; + EUC_TWFreq[43][28] = 285; + EUC_TWFreq[36][6] = 284; + EUC_TWFreq[45][75] = 283; + EUC_TWFreq[36][61] = 282; + EUC_TWFreq[38][21] = 281; + EUC_TWFreq[45][14] = 280; + EUC_TWFreq[61][43] = 279; + EUC_TWFreq[36][63] = 278; + EUC_TWFreq[43][30] = 277; + EUC_TWFreq[46][51] = 276; + EUC_TWFreq[68][87] = 275; + EUC_TWFreq[39][26] = 274; + EUC_TWFreq[46][76] = 273; + EUC_TWFreq[36][15] = 272; + EUC_TWFreq[35][40] = 271; + EUC_TWFreq[79][60] = 270; + EUC_TWFreq[46][7] = 269; + EUC_TWFreq[65][72] = 268; + EUC_TWFreq[69][88] = 267; + EUC_TWFreq[47][18] = 266; + EUC_TWFreq[37][0] = 265; + EUC_TWFreq[37][49] = 264; + EUC_TWFreq[67][37] = 263; + EUC_TWFreq[36][91] = 262; + EUC_TWFreq[75][48] = 261; + EUC_TWFreq[75][63] = 260; + EUC_TWFreq[83][87] = 259; + EUC_TWFreq[37][44] = 258; + EUC_TWFreq[73][54] = 257; + EUC_TWFreq[51][61] = 256; + EUC_TWFreq[46][57] = 255; + EUC_TWFreq[55][21] = 254; + EUC_TWFreq[39][66] = 253; + EUC_TWFreq[47][11] = 252; + EUC_TWFreq[52][8] = 251; + EUC_TWFreq[82][81] = 250; + EUC_TWFreq[36][57] = 249; + EUC_TWFreq[38][54] = 248; + EUC_TWFreq[43][81] = 247; + EUC_TWFreq[37][42] = 246; + EUC_TWFreq[40][18] = 245; + EUC_TWFreq[80][90] = 244; + EUC_TWFreq[37][84] = 243; + EUC_TWFreq[57][15] = 242; + EUC_TWFreq[38][87] = 241; + EUC_TWFreq[37][32] = 240; + EUC_TWFreq[53][53] = 239; + EUC_TWFreq[89][29] = 238; + EUC_TWFreq[81][53] = 237; + EUC_TWFreq[75][3] = 236; + EUC_TWFreq[83][73] = 235; + EUC_TWFreq[66][13] = 234; + EUC_TWFreq[48][7] = 233; + EUC_TWFreq[46][35] = 232; + EUC_TWFreq[35][86] = 231; + EUC_TWFreq[37][20] = 230; + EUC_TWFreq[46][80] = 229; + EUC_TWFreq[38][24] = 228; + EUC_TWFreq[41][68] = 227; + EUC_TWFreq[42][21] = 226; + EUC_TWFreq[43][32] = 225; + EUC_TWFreq[38][20] = 224; + EUC_TWFreq[37][59] = 223; + EUC_TWFreq[41][77] = 222; + EUC_TWFreq[59][57] = 221; + EUC_TWFreq[68][59] = 220; + EUC_TWFreq[39][43] = 219; + EUC_TWFreq[54][39] = 218; + EUC_TWFreq[48][28] = 217; + EUC_TWFreq[54][28] = 216; + EUC_TWFreq[41][44] = 215; + EUC_TWFreq[51][64] = 214; + EUC_TWFreq[47][72] = 213; + EUC_TWFreq[62][67] = 212; + EUC_TWFreq[42][43] = 211; + EUC_TWFreq[61][38] = 210; + EUC_TWFreq[76][25] = 209; + EUC_TWFreq[48][91] = 208; + EUC_TWFreq[36][36] = 207; + EUC_TWFreq[80][32] = 206; + EUC_TWFreq[81][40] = 205; + EUC_TWFreq[37][5] = 204; + EUC_TWFreq[74][69] = 203; + EUC_TWFreq[36][82] = 202; + EUC_TWFreq[46][59] = 201; + /* + * EUC_TWFreq[38][32] = 200; EUC_TWFreq[74][2] = 199; EUC_TWFreq[53][31] + * = 198; EUC_TWFreq[35][38] = 197; EUC_TWFreq[46][62] = 196; + * EUC_TWFreq[77][31] = 195; EUC_TWFreq[55][74] = 194; EUC_TWFreq[66][6] + * = 193; EUC_TWFreq[56][21] = 192; EUC_TWFreq[54][78] = 191; + * EUC_TWFreq[43][51] = 190; EUC_TWFreq[64][93] = 189; EUC_TWFreq[92][7] + * = 188; EUC_TWFreq[83][89] = 187; EUC_TWFreq[69][9] = 186; + * EUC_TWFreq[45][4] = 185; EUC_TWFreq[53][9] = 184; EUC_TWFreq[43][2] = + * 183; EUC_TWFreq[35][11] = 182; EUC_TWFreq[51][25] = 181; + * EUC_TWFreq[52][71] = 180; EUC_TWFreq[81][67] = 179; + * EUC_TWFreq[37][33] = 178; EUC_TWFreq[38][57] = 177; + * EUC_TWFreq[39][77] = 176; EUC_TWFreq[40][26] = 175; + * EUC_TWFreq[37][21] = 174; EUC_TWFreq[81][70] = 173; + * EUC_TWFreq[56][80] = 172; EUC_TWFreq[65][14] = 171; + * EUC_TWFreq[62][47] = 170; EUC_TWFreq[56][54] = 169; + * EUC_TWFreq[45][17] = 168; EUC_TWFreq[52][52] = 167; + * EUC_TWFreq[74][30] = 166; EUC_TWFreq[60][57] = 165; + * EUC_TWFreq[41][15] = 164; EUC_TWFreq[47][69] = 163; + * EUC_TWFreq[61][11] = 162; EUC_TWFreq[72][25] = 161; + * EUC_TWFreq[82][56] = 160; EUC_TWFreq[76][92] = 159; + * EUC_TWFreq[51][22] = 158; EUC_TWFreq[55][69] = 157; + * EUC_TWFreq[49][43] = 156; EUC_TWFreq[69][49] = 155; + * EUC_TWFreq[88][42] = 154; EUC_TWFreq[84][41] = 153; + * EUC_TWFreq[79][33] = 152; EUC_TWFreq[47][17] = 151; + * EUC_TWFreq[52][88] = 150; EUC_TWFreq[63][74] = 149; + * EUC_TWFreq[50][32] = 148; EUC_TWFreq[65][10] = 147; EUC_TWFreq[57][6] + * = 146; EUC_TWFreq[52][23] = 145; EUC_TWFreq[36][70] = 144; + * EUC_TWFreq[65][55] = 143; EUC_TWFreq[35][27] = 142; + * EUC_TWFreq[57][63] = 141; EUC_TWFreq[39][92] = 140; + * EUC_TWFreq[79][75] = 139; EUC_TWFreq[36][30] = 138; + * EUC_TWFreq[53][60] = 137; EUC_TWFreq[55][43] = 136; + * EUC_TWFreq[71][22] = 135; EUC_TWFreq[43][16] = 134; + * EUC_TWFreq[65][21] = 133; EUC_TWFreq[84][51] = 132; + * EUC_TWFreq[43][64] = 131; EUC_TWFreq[87][91] = 130; + * EUC_TWFreq[47][45] = 129; EUC_TWFreq[65][29] = 128; + * EUC_TWFreq[88][16] = 127; EUC_TWFreq[50][5] = 126; EUC_TWFreq[47][33] + * = 125; EUC_TWFreq[46][27] = 124; EUC_TWFreq[85][2] = 123; + * EUC_TWFreq[43][77] = 122; EUC_TWFreq[70][9] = 121; EUC_TWFreq[41][54] + * = 120; EUC_TWFreq[56][12] = 119; EUC_TWFreq[90][65] = 118; + * EUC_TWFreq[91][50] = 117; EUC_TWFreq[48][41] = 116; + * EUC_TWFreq[35][89] = 115; EUC_TWFreq[90][83] = 114; + * EUC_TWFreq[44][40] = 113; EUC_TWFreq[50][88] = 112; + * EUC_TWFreq[72][39] = 111; EUC_TWFreq[45][3] = 110; EUC_TWFreq[71][33] + * = 109; EUC_TWFreq[39][12] = 108; EUC_TWFreq[59][24] = 107; + * EUC_TWFreq[60][62] = 106; EUC_TWFreq[44][33] = 105; + * EUC_TWFreq[53][70] = 104; EUC_TWFreq[77][90] = 103; + * EUC_TWFreq[50][58] = 102; EUC_TWFreq[54][1] = 101; EUC_TWFreq[73][19] + * = 100; EUC_TWFreq[37][3] = 99; EUC_TWFreq[49][91] = 98; + * EUC_TWFreq[88][43] = 97; EUC_TWFreq[36][78] = 96; EUC_TWFreq[44][20] + * = 95; EUC_TWFreq[64][15] = 94; EUC_TWFreq[72][28] = 93; + * EUC_TWFreq[70][13] = 92; EUC_TWFreq[65][83] = 91; EUC_TWFreq[58][68] + * = 90; EUC_TWFreq[59][32] = 89; EUC_TWFreq[39][13] = 88; + * EUC_TWFreq[55][64] = 87; EUC_TWFreq[56][59] = 86; EUC_TWFreq[39][17] + * = 85; EUC_TWFreq[55][84] = 84; EUC_TWFreq[77][85] = 83; + * EUC_TWFreq[60][19] = 82; EUC_TWFreq[62][82] = 81; EUC_TWFreq[78][16] + * = 80; EUC_TWFreq[66][8] = 79; EUC_TWFreq[39][42] = 78; + * EUC_TWFreq[61][24] = 77; EUC_TWFreq[57][67] = 76; EUC_TWFreq[38][83] + * = 75; EUC_TWFreq[36][53] = 74; EUC_TWFreq[67][76] = 73; + * EUC_TWFreq[37][91] = 72; EUC_TWFreq[44][26] = 71; EUC_TWFreq[72][86] + * = 70; EUC_TWFreq[44][87] = 69; EUC_TWFreq[45][50] = 68; + * EUC_TWFreq[58][4] = 67; EUC_TWFreq[86][65] = 66; EUC_TWFreq[45][56] = + * 65; EUC_TWFreq[79][49] = 64; EUC_TWFreq[35][3] = 63; + * EUC_TWFreq[48][83] = 62; EUC_TWFreq[71][21] = 61; EUC_TWFreq[77][93] + * = 60; EUC_TWFreq[87][92] = 59; EUC_TWFreq[38][35] = 58; + * EUC_TWFreq[66][17] = 57; EUC_TWFreq[37][66] = 56; EUC_TWFreq[51][42] + * = 55; EUC_TWFreq[57][73] = 54; EUC_TWFreq[51][54] = 53; + * EUC_TWFreq[75][64] = 52; EUC_TWFreq[35][5] = 51; EUC_TWFreq[49][40] = + * 50; EUC_TWFreq[58][35] = 49; EUC_TWFreq[67][88] = 48; + * EUC_TWFreq[60][51] = 47; EUC_TWFreq[36][92] = 46; EUC_TWFreq[44][41] + * = 45; EUC_TWFreq[58][29] = 44; EUC_TWFreq[43][62] = 43; + * EUC_TWFreq[56][23] = 42; EUC_TWFreq[67][44] = 41; EUC_TWFreq[52][91] + * = 40; EUC_TWFreq[42][81] = 39; EUC_TWFreq[64][25] = 38; + * EUC_TWFreq[35][36] = 37; EUC_TWFreq[47][73] = 36; EUC_TWFreq[36][1] = + * 35; EUC_TWFreq[65][84] = 34; EUC_TWFreq[73][1] = 33; + * EUC_TWFreq[79][66] = 32; EUC_TWFreq[69][14] = 31; EUC_TWFreq[65][28] + * = 30; EUC_TWFreq[60][93] = 29; EUC_TWFreq[72][79] = 28; + * EUC_TWFreq[48][0] = 27; EUC_TWFreq[73][43] = 26; EUC_TWFreq[66][47] = + * 25; EUC_TWFreq[41][18] = 24; EUC_TWFreq[51][10] = 23; + * EUC_TWFreq[59][7] = 22; EUC_TWFreq[53][27] = 21; EUC_TWFreq[86][67] = + * 20; EUC_TWFreq[49][87] = 19; EUC_TWFreq[52][28] = 18; + * EUC_TWFreq[52][12] = 17; EUC_TWFreq[42][30] = 16; EUC_TWFreq[65][35] + * = 15; EUC_TWFreq[46][64] = 14; EUC_TWFreq[71][7] = 13; + * EUC_TWFreq[56][57] = 12; EUC_TWFreq[56][31] = 11; EUC_TWFreq[41][31] + * = 10; EUC_TWFreq[48][59] = 9; EUC_TWFreq[63][92] = 8; + * EUC_TWFreq[62][57] = 7; EUC_TWFreq[65][87] = 6; EUC_TWFreq[70][10] = + * 5; EUC_TWFreq[52][40] = 4; EUC_TWFreq[40][22] = 3; EUC_TWFreq[65][91] + * = 2; EUC_TWFreq[50][25] = 1; EUC_TWFreq[35][84] = 0; + */ + GBKFreq[52][132] = 600; + GBKFreq[73][135] = 599; + GBKFreq[49][123] = 598; + GBKFreq[77][146] = 597; + GBKFreq[81][123] = 596; + GBKFreq[82][144] = 595; + GBKFreq[51][179] = 594; + GBKFreq[83][154] = 593; + GBKFreq[71][139] = 592; + GBKFreq[64][139] = 591; + GBKFreq[85][144] = 590; + GBKFreq[52][125] = 589; + GBKFreq[88][25] = 588; + GBKFreq[81][106] = 587; + GBKFreq[81][148] = 586; + GBKFreq[62][137] = 585; + GBKFreq[94][0] = 584; + GBKFreq[1][64] = 583; + GBKFreq[67][163] = 582; + GBKFreq[20][190] = 581; + GBKFreq[57][131] = 580; + GBKFreq[29][169] = 579; + GBKFreq[72][143] = 578; + GBKFreq[0][173] = 577; + GBKFreq[11][23] = 576; + GBKFreq[61][141] = 575; + GBKFreq[60][123] = 574; + GBKFreq[81][114] = 573; + GBKFreq[82][131] = 572; + GBKFreq[67][156] = 571; + GBKFreq[71][167] = 570; + GBKFreq[20][50] = 569; + GBKFreq[77][132] = 568; + GBKFreq[84][38] = 567; + GBKFreq[26][29] = 566; + GBKFreq[74][187] = 565; + GBKFreq[62][116] = 564; + GBKFreq[67][135] = 563; + GBKFreq[5][86] = 562; + GBKFreq[72][186] = 561; + GBKFreq[75][161] = 560; + GBKFreq[78][130] = 559; + GBKFreq[94][30] = 558; + GBKFreq[84][72] = 557; + GBKFreq[1][67] = 556; + GBKFreq[75][172] = 555; + GBKFreq[74][185] = 554; + GBKFreq[53][160] = 553; + GBKFreq[123][14] = 552; + GBKFreq[79][97] = 551; + GBKFreq[85][110] = 550; + GBKFreq[78][171] = 549; + GBKFreq[52][131] = 548; + GBKFreq[56][100] = 547; + GBKFreq[50][182] = 546; + GBKFreq[94][64] = 545; + GBKFreq[106][74] = 544; + GBKFreq[11][102] = 543; + GBKFreq[53][124] = 542; + GBKFreq[24][3] = 541; + GBKFreq[86][148] = 540; + GBKFreq[53][184] = 539; + GBKFreq[86][147] = 538; + GBKFreq[96][161] = 537; + GBKFreq[82][77] = 536; + GBKFreq[59][146] = 535; + GBKFreq[84][126] = 534; + GBKFreq[79][132] = 533; + GBKFreq[85][123] = 532; + GBKFreq[71][101] = 531; + GBKFreq[85][106] = 530; + GBKFreq[6][184] = 529; + GBKFreq[57][156] = 528; + GBKFreq[75][104] = 527; + GBKFreq[50][137] = 526; + GBKFreq[79][133] = 525; + GBKFreq[76][108] = 524; + GBKFreq[57][142] = 523; + GBKFreq[84][130] = 522; + GBKFreq[52][128] = 521; + GBKFreq[47][44] = 520; + GBKFreq[52][152] = 519; + GBKFreq[54][104] = 518; + GBKFreq[30][47] = 517; + GBKFreq[71][123] = 516; + GBKFreq[52][107] = 515; + GBKFreq[45][84] = 514; + GBKFreq[107][118] = 513; + GBKFreq[5][161] = 512; + GBKFreq[48][126] = 511; + GBKFreq[67][170] = 510; + GBKFreq[43][6] = 509; + GBKFreq[70][112] = 508; + GBKFreq[86][174] = 507; + GBKFreq[84][166] = 506; + GBKFreq[79][130] = 505; + GBKFreq[57][141] = 504; + GBKFreq[81][178] = 503; + GBKFreq[56][187] = 502; + GBKFreq[81][162] = 501; + GBKFreq[53][104] = 500; + GBKFreq[123][35] = 499; + GBKFreq[70][169] = 498; + GBKFreq[69][164] = 497; + GBKFreq[109][61] = 496; + GBKFreq[73][130] = 495; + GBKFreq[62][134] = 494; + GBKFreq[54][125] = 493; + GBKFreq[79][105] = 492; + GBKFreq[70][165] = 491; + GBKFreq[71][189] = 490; + GBKFreq[23][147] = 489; + GBKFreq[51][139] = 488; + GBKFreq[47][137] = 487; + GBKFreq[77][123] = 486; + GBKFreq[86][183] = 485; + GBKFreq[63][173] = 484; + GBKFreq[79][144] = 483; + GBKFreq[84][159] = 482; + GBKFreq[60][91] = 481; + GBKFreq[66][187] = 480; + GBKFreq[73][114] = 479; + GBKFreq[85][56] = 478; + GBKFreq[71][149] = 477; + GBKFreq[84][189] = 476; + GBKFreq[104][31] = 475; + GBKFreq[83][82] = 474; + GBKFreq[68][35] = 473; + GBKFreq[11][77] = 472; + GBKFreq[15][155] = 471; + GBKFreq[83][153] = 470; + GBKFreq[71][1] = 469; + GBKFreq[53][190] = 468; + GBKFreq[50][135] = 467; + GBKFreq[3][147] = 466; + GBKFreq[48][136] = 465; + GBKFreq[66][166] = 464; + GBKFreq[55][159] = 463; + GBKFreq[82][150] = 462; + GBKFreq[58][178] = 461; + GBKFreq[64][102] = 460; + GBKFreq[16][106] = 459; + GBKFreq[68][110] = 458; + GBKFreq[54][14] = 457; + GBKFreq[60][140] = 456; + GBKFreq[91][71] = 455; + GBKFreq[54][150] = 454; + GBKFreq[78][177] = 453; + GBKFreq[78][117] = 452; + GBKFreq[104][12] = 451; + GBKFreq[73][150] = 450; + GBKFreq[51][142] = 449; + GBKFreq[81][145] = 448; + GBKFreq[66][183] = 447; + GBKFreq[51][178] = 446; + GBKFreq[75][107] = 445; + GBKFreq[65][119] = 444; + GBKFreq[69][176] = 443; + GBKFreq[59][122] = 442; + GBKFreq[78][160] = 441; + GBKFreq[85][183] = 440; + GBKFreq[105][16] = 439; + GBKFreq[73][110] = 438; + GBKFreq[104][39] = 437; + GBKFreq[119][16] = 436; + GBKFreq[76][162] = 435; + GBKFreq[67][152] = 434; + GBKFreq[82][24] = 433; + GBKFreq[73][121] = 432; + GBKFreq[83][83] = 431; + GBKFreq[82][145] = 430; + GBKFreq[49][133] = 429; + GBKFreq[94][13] = 428; + GBKFreq[58][139] = 427; + GBKFreq[74][189] = 426; + GBKFreq[66][177] = 425; + GBKFreq[85][184] = 424; + GBKFreq[55][183] = 423; + GBKFreq[71][107] = 422; + GBKFreq[11][98] = 421; + GBKFreq[72][153] = 420; + GBKFreq[2][137] = 419; + GBKFreq[59][147] = 418; + GBKFreq[58][152] = 417; + GBKFreq[55][144] = 416; + GBKFreq[73][125] = 415; + GBKFreq[52][154] = 414; + GBKFreq[70][178] = 413; + GBKFreq[79][148] = 412; + GBKFreq[63][143] = 411; + GBKFreq[50][140] = 410; + GBKFreq[47][145] = 409; + GBKFreq[48][123] = 408; + GBKFreq[56][107] = 407; + GBKFreq[84][83] = 406; + GBKFreq[59][112] = 405; + GBKFreq[124][72] = 404; + GBKFreq[79][99] = 403; + GBKFreq[3][37] = 402; + GBKFreq[114][55] = 401; + GBKFreq[85][152] = 400; + GBKFreq[60][47] = 399; + GBKFreq[65][96] = 398; + GBKFreq[74][110] = 397; + GBKFreq[86][182] = 396; + GBKFreq[50][99] = 395; + GBKFreq[67][186] = 394; + GBKFreq[81][74] = 393; + GBKFreq[80][37] = 392; + GBKFreq[21][60] = 391; + GBKFreq[110][12] = 390; + GBKFreq[60][162] = 389; + GBKFreq[29][115] = 388; + GBKFreq[83][130] = 387; + GBKFreq[52][136] = 386; + GBKFreq[63][114] = 385; + GBKFreq[49][127] = 384; + GBKFreq[83][109] = 383; + GBKFreq[66][128] = 382; + GBKFreq[78][136] = 381; + GBKFreq[81][180] = 380; + GBKFreq[76][104] = 379; + GBKFreq[56][156] = 378; + GBKFreq[61][23] = 377; + GBKFreq[4][30] = 376; + GBKFreq[69][154] = 375; + GBKFreq[100][37] = 374; + GBKFreq[54][177] = 373; + GBKFreq[23][119] = 372; + GBKFreq[71][171] = 371; + GBKFreq[84][146] = 370; + GBKFreq[20][184] = 369; + GBKFreq[86][76] = 368; + GBKFreq[74][132] = 367; + GBKFreq[47][97] = 366; + GBKFreq[82][137] = 365; + GBKFreq[94][56] = 364; + GBKFreq[92][30] = 363; + GBKFreq[19][117] = 362; + GBKFreq[48][173] = 361; + GBKFreq[2][136] = 360; + GBKFreq[7][182] = 359; + GBKFreq[74][188] = 358; + GBKFreq[14][132] = 357; + GBKFreq[62][172] = 356; + GBKFreq[25][39] = 355; + GBKFreq[85][129] = 354; + GBKFreq[64][98] = 353; + GBKFreq[67][127] = 352; + GBKFreq[72][167] = 351; + GBKFreq[57][143] = 350; + GBKFreq[76][187] = 349; + GBKFreq[83][181] = 348; + GBKFreq[84][10] = 347; + GBKFreq[55][166] = 346; + GBKFreq[55][188] = 345; + GBKFreq[13][151] = 344; + GBKFreq[62][124] = 343; + GBKFreq[53][136] = 342; + GBKFreq[106][57] = 341; + GBKFreq[47][166] = 340; + GBKFreq[109][30] = 339; + GBKFreq[78][114] = 338; + GBKFreq[83][19] = 337; + GBKFreq[56][162] = 336; + GBKFreq[60][177] = 335; + GBKFreq[88][9] = 334; + GBKFreq[74][163] = 333; + GBKFreq[52][156] = 332; + GBKFreq[71][180] = 331; + GBKFreq[60][57] = 330; + GBKFreq[72][173] = 329; + GBKFreq[82][91] = 328; + GBKFreq[51][186] = 327; + GBKFreq[75][86] = 326; + GBKFreq[75][78] = 325; + GBKFreq[76][170] = 324; + GBKFreq[60][147] = 323; + GBKFreq[82][75] = 322; + GBKFreq[80][148] = 321; + GBKFreq[86][150] = 320; + GBKFreq[13][95] = 319; + GBKFreq[0][11] = 318; + GBKFreq[84][190] = 317; + GBKFreq[76][166] = 316; + GBKFreq[14][72] = 315; + GBKFreq[67][144] = 314; + GBKFreq[84][44] = 313; + GBKFreq[72][125] = 312; + GBKFreq[66][127] = 311; + GBKFreq[60][25] = 310; + GBKFreq[70][146] = 309; + GBKFreq[79][135] = 308; + GBKFreq[54][135] = 307; + GBKFreq[60][104] = 306; + GBKFreq[55][132] = 305; + GBKFreq[94][2] = 304; + GBKFreq[54][133] = 303; + GBKFreq[56][190] = 302; + GBKFreq[58][174] = 301; + GBKFreq[80][144] = 300; + GBKFreq[85][113] = 299; + /* + * GBKFreq[83][15] = 298; GBKFreq[105][80] = 297; GBKFreq[7][179] = 296; + * GBKFreq[93][4] = 295; GBKFreq[123][40] = 294; GBKFreq[85][120] = 293; + * GBKFreq[77][165] = 292; GBKFreq[86][67] = 291; GBKFreq[25][162] = + * 290; GBKFreq[77][183] = 289; GBKFreq[83][71] = 288; GBKFreq[78][99] = + * 287; GBKFreq[72][177] = 286; GBKFreq[71][97] = 285; GBKFreq[58][111] + * = 284; GBKFreq[77][175] = 283; GBKFreq[76][181] = 282; + * GBKFreq[71][142] = 281; GBKFreq[64][150] = 280; GBKFreq[5][142] = + * 279; GBKFreq[73][128] = 278; GBKFreq[73][156] = 277; GBKFreq[60][188] + * = 276; GBKFreq[64][56] = 275; GBKFreq[74][128] = 274; + * GBKFreq[48][163] = 273; GBKFreq[54][116] = 272; GBKFreq[73][127] = + * 271; GBKFreq[16][176] = 270; GBKFreq[62][149] = 269; GBKFreq[105][96] + * = 268; GBKFreq[55][186] = 267; GBKFreq[4][51] = 266; GBKFreq[48][113] + * = 265; GBKFreq[48][152] = 264; GBKFreq[23][9] = 263; GBKFreq[56][102] + * = 262; GBKFreq[11][81] = 261; GBKFreq[82][112] = 260; GBKFreq[65][85] + * = 259; GBKFreq[69][125] = 258; GBKFreq[68][31] = 257; GBKFreq[5][20] + * = 256; GBKFreq[60][176] = 255; GBKFreq[82][81] = 254; + * GBKFreq[72][107] = 253; GBKFreq[3][52] = 252; GBKFreq[71][157] = 251; + * GBKFreq[24][46] = 250; GBKFreq[69][108] = 249; GBKFreq[78][178] = + * 248; GBKFreq[9][69] = 247; GBKFreq[73][144] = 246; GBKFreq[63][187] = + * 245; GBKFreq[68][36] = 244; GBKFreq[47][151] = 243; GBKFreq[14][74] = + * 242; GBKFreq[47][114] = 241; GBKFreq[80][171] = 240; GBKFreq[75][152] + * = 239; GBKFreq[86][40] = 238; GBKFreq[93][43] = 237; GBKFreq[2][50] = + * 236; GBKFreq[62][66] = 235; GBKFreq[1][183] = 234; GBKFreq[74][124] = + * 233; GBKFreq[58][104] = 232; GBKFreq[83][106] = 231; GBKFreq[60][144] + * = 230; GBKFreq[48][99] = 229; GBKFreq[54][157] = 228; + * GBKFreq[70][179] = 227; GBKFreq[61][127] = 226; GBKFreq[57][135] = + * 225; GBKFreq[59][190] = 224; GBKFreq[77][116] = 223; GBKFreq[26][17] + * = 222; GBKFreq[60][13] = 221; GBKFreq[71][38] = 220; GBKFreq[85][177] + * = 219; GBKFreq[59][73] = 218; GBKFreq[50][150] = 217; + * GBKFreq[79][102] = 216; GBKFreq[76][118] = 215; GBKFreq[67][132] = + * 214; GBKFreq[73][146] = 213; GBKFreq[83][184] = 212; GBKFreq[86][159] + * = 211; GBKFreq[95][120] = 210; GBKFreq[23][139] = 209; + * GBKFreq[64][183] = 208; GBKFreq[85][103] = 207; GBKFreq[41][90] = + * 206; GBKFreq[87][72] = 205; GBKFreq[62][104] = 204; GBKFreq[79][168] + * = 203; GBKFreq[79][150] = 202; GBKFreq[104][20] = 201; + * GBKFreq[56][114] = 200; GBKFreq[84][26] = 199; GBKFreq[57][99] = 198; + * GBKFreq[62][154] = 197; GBKFreq[47][98] = 196; GBKFreq[61][64] = 195; + * GBKFreq[112][18] = 194; GBKFreq[123][19] = 193; GBKFreq[4][98] = 192; + * GBKFreq[47][163] = 191; GBKFreq[66][188] = 190; GBKFreq[81][85] = + * 189; GBKFreq[82][30] = 188; GBKFreq[65][83] = 187; GBKFreq[67][24] = + * 186; GBKFreq[68][179] = 185; GBKFreq[55][177] = 184; GBKFreq[2][122] + * = 183; GBKFreq[47][139] = 182; GBKFreq[79][158] = 181; + * GBKFreq[64][143] = 180; GBKFreq[100][24] = 179; GBKFreq[73][103] = + * 178; GBKFreq[50][148] = 177; GBKFreq[86][97] = 176; GBKFreq[59][116] + * = 175; GBKFreq[64][173] = 174; GBKFreq[99][91] = 173; GBKFreq[11][99] + * = 172; GBKFreq[78][179] = 171; GBKFreq[18][17] = 170; + * GBKFreq[58][185] = 169; GBKFreq[47][165] = 168; GBKFreq[67][131] = + * 167; GBKFreq[94][40] = 166; GBKFreq[74][153] = 165; GBKFreq[79][142] + * = 164; GBKFreq[57][98] = 163; GBKFreq[1][164] = 162; GBKFreq[55][168] + * = 161; GBKFreq[13][141] = 160; GBKFreq[51][31] = 159; + * GBKFreq[57][178] = 158; GBKFreq[50][189] = 157; GBKFreq[60][167] = + * 156; GBKFreq[80][34] = 155; GBKFreq[109][80] = 154; GBKFreq[85][54] = + * 153; GBKFreq[69][183] = 152; GBKFreq[67][143] = 151; GBKFreq[47][120] + * = 150; GBKFreq[45][75] = 149; GBKFreq[82][98] = 148; GBKFreq[83][22] + * = 147; GBKFreq[13][103] = 146; GBKFreq[49][174] = 145; + * GBKFreq[57][181] = 144; GBKFreq[64][127] = 143; GBKFreq[61][131] = + * 142; GBKFreq[52][180] = 141; GBKFreq[74][134] = 140; GBKFreq[84][187] + * = 139; GBKFreq[81][189] = 138; GBKFreq[47][160] = 137; + * GBKFreq[66][148] = 136; GBKFreq[7][4] = 135; GBKFreq[85][134] = 134; + * GBKFreq[88][13] = 133; GBKFreq[88][80] = 132; GBKFreq[69][166] = 131; + * GBKFreq[86][18] = 130; GBKFreq[79][141] = 129; GBKFreq[50][108] = + * 128; GBKFreq[94][69] = 127; GBKFreq[81][110] = 126; GBKFreq[69][119] + * = 125; GBKFreq[72][161] = 124; GBKFreq[106][45] = 123; + * GBKFreq[73][124] = 122; GBKFreq[94][28] = 121; GBKFreq[63][174] = + * 120; GBKFreq[3][149] = 119; GBKFreq[24][160] = 118; GBKFreq[113][94] + * = 117; GBKFreq[56][138] = 116; GBKFreq[64][185] = 115; + * GBKFreq[86][56] = 114; GBKFreq[56][150] = 113; GBKFreq[110][55] = + * 112; GBKFreq[28][13] = 111; GBKFreq[54][190] = 110; GBKFreq[8][180] = + * 109; GBKFreq[73][149] = 108; GBKFreq[80][155] = 107; GBKFreq[83][172] + * = 106; GBKFreq[67][174] = 105; GBKFreq[64][180] = 104; + * GBKFreq[84][46] = 103; GBKFreq[91][74] = 102; GBKFreq[69][134] = 101; + * GBKFreq[61][107] = 100; GBKFreq[47][171] = 99; GBKFreq[59][51] = 98; + * GBKFreq[109][74] = 97; GBKFreq[64][174] = 96; GBKFreq[52][151] = 95; + * GBKFreq[51][176] = 94; GBKFreq[80][157] = 93; GBKFreq[94][31] = 92; + * GBKFreq[79][155] = 91; GBKFreq[72][174] = 90; GBKFreq[69][113] = 89; + * GBKFreq[83][167] = 88; GBKFreq[83][122] = 87; GBKFreq[8][178] = 86; + * GBKFreq[70][186] = 85; GBKFreq[59][153] = 84; GBKFreq[84][68] = 83; + * GBKFreq[79][39] = 82; GBKFreq[47][180] = 81; GBKFreq[88][53] = 80; + * GBKFreq[57][154] = 79; GBKFreq[47][153] = 78; GBKFreq[3][153] = 77; + * GBKFreq[76][134] = 76; GBKFreq[51][166] = 75; GBKFreq[58][176] = 74; + * GBKFreq[27][138] = 73; GBKFreq[73][126] = 72; GBKFreq[76][185] = 71; + * GBKFreq[52][186] = 70; GBKFreq[81][151] = 69; GBKFreq[26][50] = 68; + * GBKFreq[76][173] = 67; GBKFreq[106][56] = 66; GBKFreq[85][142] = 65; + * GBKFreq[11][103] = 64; GBKFreq[69][159] = 63; GBKFreq[53][142] = 62; + * GBKFreq[7][6] = 61; GBKFreq[84][59] = 60; GBKFreq[86][3] = 59; + * GBKFreq[64][144] = 58; GBKFreq[1][187] = 57; GBKFreq[82][128] = 56; + * GBKFreq[3][66] = 55; GBKFreq[68][133] = 54; GBKFreq[55][167] = 53; + * GBKFreq[52][130] = 52; GBKFreq[61][133] = 51; GBKFreq[72][181] = 50; + * GBKFreq[25][98] = 49; GBKFreq[84][149] = 48; GBKFreq[91][91] = 47; + * GBKFreq[47][188] = 46; GBKFreq[68][130] = 45; GBKFreq[22][44] = 44; + * GBKFreq[81][121] = 43; GBKFreq[72][140] = 42; GBKFreq[55][133] = 41; + * GBKFreq[55][185] = 40; GBKFreq[56][105] = 39; GBKFreq[60][30] = 38; + * GBKFreq[70][103] = 37; GBKFreq[62][141] = 36; GBKFreq[70][144] = 35; + * GBKFreq[59][111] = 34; GBKFreq[54][17] = 33; GBKFreq[18][190] = 32; + * GBKFreq[65][164] = 31; GBKFreq[83][125] = 30; GBKFreq[61][121] = 29; + * GBKFreq[48][13] = 28; GBKFreq[51][189] = 27; GBKFreq[65][68] = 26; + * GBKFreq[7][0] = 25; GBKFreq[76][188] = 24; GBKFreq[85][117] = 23; + * GBKFreq[45][33] = 22; GBKFreq[78][187] = 21; GBKFreq[106][48] = 20; + * GBKFreq[59][52] = 19; GBKFreq[86][185] = 18; GBKFreq[84][121] = 17; + * GBKFreq[82][189] = 16; GBKFreq[68][156] = 15; GBKFreq[55][125] = 14; + * GBKFreq[65][175] = 13; GBKFreq[7][140] = 12; GBKFreq[50][106] = 11; + * GBKFreq[59][124] = 10; GBKFreq[67][115] = 9; GBKFreq[82][114] = 8; + * GBKFreq[74][121] = 7; GBKFreq[106][69] = 6; GBKFreq[94][27] = 5; + * GBKFreq[78][98] = 4; GBKFreq[85][186] = 3; GBKFreq[108][90] = 2; + * GBKFreq[62][160] = 1; GBKFreq[60][169] = 0; + */ + KRFreq[31][43] = 600; + KRFreq[19][56] = 599; + KRFreq[38][46] = 598; + KRFreq[3][3] = 597; + KRFreq[29][77] = 596; + KRFreq[19][33] = 595; + KRFreq[30][0] = 594; + KRFreq[29][89] = 593; + KRFreq[31][26] = 592; + KRFreq[31][38] = 591; + KRFreq[32][85] = 590; + KRFreq[15][0] = 589; + KRFreq[16][54] = 588; + KRFreq[15][76] = 587; + KRFreq[31][25] = 586; + KRFreq[23][13] = 585; + KRFreq[28][34] = 584; + KRFreq[18][9] = 583; + KRFreq[29][37] = 582; + KRFreq[22][45] = 581; + KRFreq[19][46] = 580; + KRFreq[16][65] = 579; + KRFreq[23][5] = 578; + KRFreq[26][70] = 577; + KRFreq[31][53] = 576; + KRFreq[27][12] = 575; + KRFreq[30][67] = 574; + KRFreq[31][57] = 573; + KRFreq[20][20] = 572; + KRFreq[30][31] = 571; + KRFreq[20][72] = 570; + KRFreq[15][51] = 569; + KRFreq[3][8] = 568; + KRFreq[32][53] = 567; + KRFreq[27][85] = 566; + KRFreq[25][23] = 565; + KRFreq[15][44] = 564; + KRFreq[32][3] = 563; + KRFreq[31][68] = 562; + KRFreq[30][24] = 561; + KRFreq[29][49] = 560; + KRFreq[27][49] = 559; + KRFreq[23][23] = 558; + KRFreq[31][91] = 557; + KRFreq[31][46] = 556; + KRFreq[19][74] = 555; + KRFreq[27][27] = 554; + KRFreq[3][17] = 553; + KRFreq[20][38] = 552; + KRFreq[21][82] = 551; + KRFreq[28][25] = 550; + KRFreq[32][5] = 549; + KRFreq[31][23] = 548; + KRFreq[25][45] = 547; + KRFreq[32][87] = 546; + KRFreq[18][26] = 545; + KRFreq[24][10] = 544; + KRFreq[26][82] = 543; + KRFreq[15][89] = 542; + KRFreq[28][36] = 541; + KRFreq[28][31] = 540; + KRFreq[16][23] = 539; + KRFreq[16][77] = 538; + KRFreq[19][84] = 537; + KRFreq[23][72] = 536; + KRFreq[38][48] = 535; + KRFreq[23][2] = 534; + KRFreq[30][20] = 533; + KRFreq[38][47] = 532; + KRFreq[39][12] = 531; + KRFreq[23][21] = 530; + KRFreq[18][17] = 529; + KRFreq[30][87] = 528; + KRFreq[29][62] = 527; + KRFreq[29][87] = 526; + KRFreq[34][53] = 525; + KRFreq[32][29] = 524; + KRFreq[35][0] = 523; + KRFreq[24][43] = 522; + KRFreq[36][44] = 521; + KRFreq[20][30] = 520; + KRFreq[39][86] = 519; + KRFreq[22][14] = 518; + KRFreq[29][39] = 517; + KRFreq[28][38] = 516; + KRFreq[23][79] = 515; + KRFreq[24][56] = 514; + KRFreq[29][63] = 513; + KRFreq[31][45] = 512; + KRFreq[23][26] = 511; + KRFreq[15][87] = 510; + KRFreq[30][74] = 509; + KRFreq[24][69] = 508; + KRFreq[20][4] = 507; + KRFreq[27][50] = 506; + KRFreq[30][75] = 505; + KRFreq[24][13] = 504; + KRFreq[30][8] = 503; + KRFreq[31][6] = 502; + KRFreq[25][80] = 501; + KRFreq[36][8] = 500; + KRFreq[15][18] = 499; + KRFreq[39][23] = 498; + KRFreq[16][24] = 497; + KRFreq[31][89] = 496; + KRFreq[15][71] = 495; + KRFreq[15][57] = 494; + KRFreq[30][11] = 493; + KRFreq[15][36] = 492; + KRFreq[16][60] = 491; + KRFreq[24][45] = 490; + KRFreq[37][35] = 489; + KRFreq[24][87] = 488; + KRFreq[20][45] = 487; + KRFreq[31][90] = 486; + KRFreq[32][21] = 485; + KRFreq[19][70] = 484; + KRFreq[24][15] = 483; + KRFreq[26][92] = 482; + KRFreq[37][13] = 481; + KRFreq[39][2] = 480; + KRFreq[23][70] = 479; + KRFreq[27][25] = 478; + KRFreq[15][69] = 477; + KRFreq[19][61] = 476; + KRFreq[31][58] = 475; + KRFreq[24][57] = 474; + KRFreq[36][74] = 473; + KRFreq[21][6] = 472; + KRFreq[30][44] = 471; + KRFreq[15][91] = 470; + KRFreq[27][16] = 469; + KRFreq[29][42] = 468; + KRFreq[33][86] = 467; + KRFreq[29][41] = 466; + KRFreq[20][68] = 465; + KRFreq[25][47] = 464; + KRFreq[22][0] = 463; + KRFreq[18][14] = 462; + KRFreq[31][28] = 461; + KRFreq[15][2] = 460; + KRFreq[23][76] = 459; + KRFreq[38][32] = 458; + KRFreq[29][82] = 457; + KRFreq[21][86] = 456; + KRFreq[24][62] = 455; + KRFreq[31][64] = 454; + KRFreq[38][26] = 453; + KRFreq[32][86] = 452; + KRFreq[22][32] = 451; + KRFreq[19][59] = 450; + KRFreq[34][18] = 449; + KRFreq[18][54] = 448; + KRFreq[38][63] = 447; + KRFreq[36][23] = 446; + KRFreq[35][35] = 445; + KRFreq[32][62] = 444; + KRFreq[28][35] = 443; + KRFreq[27][13] = 442; + KRFreq[31][59] = 441; + KRFreq[29][29] = 440; + KRFreq[15][64] = 439; + KRFreq[26][84] = 438; + KRFreq[21][90] = 437; + KRFreq[20][24] = 436; + KRFreq[16][18] = 435; + KRFreq[22][23] = 434; + KRFreq[31][14] = 433; + KRFreq[15][1] = 432; + KRFreq[18][63] = 431; + KRFreq[19][10] = 430; + KRFreq[25][49] = 429; + KRFreq[36][57] = 428; + KRFreq[20][22] = 427; + KRFreq[15][15] = 426; + KRFreq[31][51] = 425; + KRFreq[24][60] = 424; + KRFreq[31][70] = 423; + KRFreq[15][7] = 422; + KRFreq[28][40] = 421; + KRFreq[18][41] = 420; + KRFreq[15][38] = 419; + KRFreq[32][0] = 418; + KRFreq[19][51] = 417; + KRFreq[34][62] = 416; + KRFreq[16][27] = 415; + KRFreq[20][70] = 414; + KRFreq[22][33] = 413; + KRFreq[26][73] = 412; + KRFreq[20][79] = 411; + KRFreq[23][6] = 410; + KRFreq[24][85] = 409; + KRFreq[38][51] = 408; + KRFreq[29][88] = 407; + KRFreq[38][55] = 406; + KRFreq[32][32] = 405; + KRFreq[27][18] = 404; + KRFreq[23][87] = 403; + KRFreq[35][6] = 402; + KRFreq[34][27] = 401; + KRFreq[39][35] = 400; + KRFreq[30][88] = 399; + KRFreq[32][92] = 398; + KRFreq[32][49] = 397; + KRFreq[24][61] = 396; + KRFreq[18][74] = 395; + KRFreq[23][77] = 394; + KRFreq[23][50] = 393; + KRFreq[23][32] = 392; + KRFreq[23][36] = 391; + KRFreq[38][38] = 390; + KRFreq[29][86] = 389; + KRFreq[36][15] = 388; + KRFreq[31][50] = 387; + KRFreq[15][86] = 386; + KRFreq[39][13] = 385; + KRFreq[34][26] = 384; + KRFreq[19][34] = 383; + KRFreq[16][3] = 382; + KRFreq[26][93] = 381; + KRFreq[19][67] = 380; + KRFreq[24][72] = 379; + KRFreq[29][17] = 378; + KRFreq[23][24] = 377; + KRFreq[25][19] = 376; + KRFreq[18][65] = 375; + KRFreq[30][78] = 374; + KRFreq[27][52] = 373; + KRFreq[22][18] = 372; + KRFreq[16][38] = 371; + KRFreq[21][26] = 370; + KRFreq[34][20] = 369; + KRFreq[15][42] = 368; + KRFreq[16][71] = 367; + KRFreq[17][17] = 366; + KRFreq[24][71] = 365; + KRFreq[18][84] = 364; + KRFreq[15][40] = 363; + KRFreq[31][62] = 362; + KRFreq[15][8] = 361; + KRFreq[16][69] = 360; + KRFreq[29][79] = 359; + KRFreq[38][91] = 358; + KRFreq[31][92] = 357; + KRFreq[20][77] = 356; + KRFreq[3][16] = 355; + KRFreq[27][87] = 354; + KRFreq[16][25] = 353; + KRFreq[36][33] = 352; + KRFreq[37][76] = 351; + KRFreq[30][12] = 350; + KRFreq[26][75] = 349; + KRFreq[25][14] = 348; + KRFreq[32][26] = 347; + KRFreq[23][22] = 346; + KRFreq[20][90] = 345; + KRFreq[19][8] = 344; + KRFreq[38][41] = 343; + KRFreq[34][2] = 342; + KRFreq[39][4] = 341; + KRFreq[27][89] = 340; + KRFreq[28][41] = 339; + KRFreq[28][44] = 338; + KRFreq[24][92] = 337; + KRFreq[34][65] = 336; + KRFreq[39][14] = 335; + KRFreq[21][38] = 334; + KRFreq[19][31] = 333; + KRFreq[37][39] = 332; + KRFreq[33][41] = 331; + KRFreq[38][4] = 330; + KRFreq[23][80] = 329; + KRFreq[25][24] = 328; + KRFreq[37][17] = 327; + KRFreq[22][16] = 326; + KRFreq[22][46] = 325; + KRFreq[33][91] = 324; + KRFreq[24][89] = 323; + KRFreq[30][52] = 322; + KRFreq[29][38] = 321; + KRFreq[38][85] = 320; + KRFreq[15][12] = 319; + KRFreq[27][58] = 318; + KRFreq[29][52] = 317; + KRFreq[37][38] = 316; + KRFreq[34][41] = 315; + KRFreq[31][65] = 314; + KRFreq[29][53] = 313; + KRFreq[22][47] = 312; + KRFreq[22][19] = 311; + KRFreq[26][0] = 310; + KRFreq[37][86] = 309; + KRFreq[35][4] = 308; + KRFreq[36][54] = 307; + KRFreq[20][76] = 306; + KRFreq[30][9] = 305; + KRFreq[30][33] = 304; + KRFreq[23][17] = 303; + KRFreq[23][33] = 302; + KRFreq[38][52] = 301; + KRFreq[15][19] = 300; + KRFreq[28][45] = 299; + KRFreq[29][78] = 298; + KRFreq[23][15] = 297; + KRFreq[33][5] = 296; + KRFreq[17][40] = 295; + KRFreq[30][83] = 294; + KRFreq[18][1] = 293; + KRFreq[30][81] = 292; + KRFreq[19][40] = 291; + KRFreq[24][47] = 290; + KRFreq[17][56] = 289; + KRFreq[39][80] = 288; + KRFreq[30][46] = 287; + KRFreq[16][61] = 286; + KRFreq[26][78] = 285; + KRFreq[26][57] = 284; + KRFreq[20][46] = 283; + KRFreq[25][15] = 282; + KRFreq[25][91] = 281; + KRFreq[21][83] = 280; + KRFreq[30][77] = 279; + KRFreq[35][30] = 278; + KRFreq[30][34] = 277; + KRFreq[20][69] = 276; + KRFreq[35][10] = 275; + KRFreq[29][70] = 274; + KRFreq[22][50] = 273; + KRFreq[18][0] = 272; + KRFreq[22][64] = 271; + KRFreq[38][65] = 270; + KRFreq[22][70] = 269; + KRFreq[24][58] = 268; + KRFreq[19][66] = 267; + KRFreq[30][59] = 266; + KRFreq[37][14] = 265; + KRFreq[16][56] = 264; + KRFreq[29][85] = 263; + KRFreq[31][15] = 262; + KRFreq[36][84] = 261; + KRFreq[39][15] = 260; + KRFreq[39][90] = 259; + KRFreq[18][12] = 258; + KRFreq[21][93] = 257; + KRFreq[24][66] = 256; + KRFreq[27][90] = 255; + KRFreq[25][90] = 254; + KRFreq[22][24] = 253; + KRFreq[36][67] = 252; + KRFreq[33][90] = 251; + KRFreq[15][60] = 250; + KRFreq[23][85] = 249; + KRFreq[34][1] = 248; + KRFreq[39][37] = 247; + KRFreq[21][18] = 246; + KRFreq[34][4] = 245; + KRFreq[28][33] = 244; + KRFreq[15][13] = 243; + KRFreq[32][22] = 242; + KRFreq[30][76] = 241; + KRFreq[20][21] = 240; + KRFreq[38][66] = 239; + KRFreq[32][55] = 238; + KRFreq[32][89] = 237; + KRFreq[25][26] = 236; + KRFreq[16][80] = 235; + KRFreq[15][43] = 234; + KRFreq[38][54] = 233; + KRFreq[39][68] = 232; + KRFreq[22][88] = 231; + KRFreq[21][84] = 230; + KRFreq[21][17] = 229; + KRFreq[20][28] = 228; + KRFreq[32][1] = 227; + KRFreq[33][87] = 226; + KRFreq[38][71] = 225; + KRFreq[37][47] = 224; + KRFreq[18][77] = 223; + KRFreq[37][58] = 222; + KRFreq[34][74] = 221; + KRFreq[32][54] = 220; + KRFreq[27][33] = 219; + KRFreq[32][93] = 218; + KRFreq[23][51] = 217; + KRFreq[20][57] = 216; + KRFreq[22][37] = 215; + KRFreq[39][10] = 214; + KRFreq[39][17] = 213; + KRFreq[33][4] = 212; + KRFreq[32][84] = 211; + KRFreq[34][3] = 210; + KRFreq[28][27] = 209; + KRFreq[15][79] = 208; + KRFreq[34][21] = 207; + KRFreq[34][69] = 206; + KRFreq[21][62] = 205; + KRFreq[36][24] = 204; + KRFreq[16][89] = 203; + KRFreq[18][48] = 202; + KRFreq[38][15] = 201; + KRFreq[36][58] = 200; + KRFreq[21][56] = 199; + KRFreq[34][48] = 198; + KRFreq[21][15] = 197; + KRFreq[39][3] = 196; + KRFreq[16][44] = 195; + KRFreq[18][79] = 194; + KRFreq[25][13] = 193; + KRFreq[29][47] = 192; + KRFreq[38][88] = 191; + KRFreq[20][71] = 190; + KRFreq[16][58] = 189; + KRFreq[35][57] = 188; + KRFreq[29][30] = 187; + KRFreq[29][23] = 186; + KRFreq[34][93] = 185; + KRFreq[30][85] = 184; + KRFreq[15][80] = 183; + KRFreq[32][78] = 182; + KRFreq[37][82] = 181; + KRFreq[22][40] = 180; + KRFreq[21][69] = 179; + KRFreq[26][85] = 178; + KRFreq[31][31] = 177; + KRFreq[28][64] = 176; + KRFreq[38][13] = 175; + KRFreq[25][2] = 174; + KRFreq[22][34] = 173; + KRFreq[28][28] = 172; + KRFreq[24][91] = 171; + KRFreq[33][74] = 170; + KRFreq[29][40] = 169; + KRFreq[15][77] = 168; + KRFreq[32][80] = 167; + KRFreq[30][41] = 166; + KRFreq[23][30] = 165; + KRFreq[24][63] = 164; + KRFreq[30][53] = 163; + KRFreq[39][70] = 162; + KRFreq[23][61] = 161; + KRFreq[37][27] = 160; + KRFreq[16][55] = 159; + KRFreq[22][74] = 158; + KRFreq[26][50] = 157; + KRFreq[16][10] = 156; + KRFreq[34][63] = 155; + KRFreq[35][14] = 154; + KRFreq[17][7] = 153; + KRFreq[15][59] = 152; + KRFreq[27][23] = 151; + KRFreq[18][70] = 150; + KRFreq[32][56] = 149; + KRFreq[37][87] = 148; + KRFreq[17][61] = 147; + KRFreq[18][83] = 146; + KRFreq[23][86] = 145; + KRFreq[17][31] = 144; + KRFreq[23][83] = 143; + KRFreq[35][2] = 142; + KRFreq[18][64] = 141; + KRFreq[27][43] = 140; + KRFreq[32][42] = 139; + KRFreq[25][76] = 138; + KRFreq[19][85] = 137; + KRFreq[37][81] = 136; + KRFreq[38][83] = 135; + KRFreq[35][7] = 134; + KRFreq[16][51] = 133; + KRFreq[27][22] = 132; + KRFreq[16][76] = 131; + KRFreq[22][4] = 130; + KRFreq[38][84] = 129; + KRFreq[17][83] = 128; + KRFreq[24][46] = 127; + KRFreq[33][15] = 126; + KRFreq[20][48] = 125; + KRFreq[17][30] = 124; + KRFreq[30][93] = 123; + KRFreq[28][11] = 122; + KRFreq[28][30] = 121; + KRFreq[15][62] = 120; + KRFreq[17][87] = 119; + KRFreq[32][81] = 118; + KRFreq[23][37] = 117; + KRFreq[30][22] = 116; + KRFreq[32][66] = 115; + KRFreq[33][78] = 114; + KRFreq[21][4] = 113; + KRFreq[31][17] = 112; + KRFreq[39][61] = 111; + KRFreq[18][76] = 110; + KRFreq[15][85] = 109; + KRFreq[31][47] = 108; + KRFreq[19][57] = 107; + KRFreq[23][55] = 106; + KRFreq[27][29] = 105; + KRFreq[29][46] = 104; + KRFreq[33][0] = 103; + KRFreq[16][83] = 102; + KRFreq[39][78] = 101; + KRFreq[32][77] = 100; + KRFreq[36][25] = 99; + KRFreq[34][19] = 98; + KRFreq[38][49] = 97; + KRFreq[19][25] = 96; + KRFreq[23][53] = 95; + KRFreq[28][43] = 94; + KRFreq[31][44] = 93; + KRFreq[36][34] = 92; + KRFreq[16][34] = 91; + KRFreq[35][1] = 90; + KRFreq[19][87] = 89; + KRFreq[18][53] = 88; + KRFreq[29][54] = 87; + KRFreq[22][41] = 86; + KRFreq[38][18] = 85; + KRFreq[22][2] = 84; + KRFreq[20][3] = 83; + KRFreq[39][69] = 82; + KRFreq[30][29] = 81; + KRFreq[28][19] = 80; + KRFreq[29][90] = 79; + KRFreq[17][86] = 78; + KRFreq[15][9] = 77; + KRFreq[39][73] = 76; + KRFreq[15][37] = 75; + KRFreq[35][40] = 74; + KRFreq[33][77] = 73; + KRFreq[27][86] = 72; + KRFreq[36][79] = 71; + KRFreq[23][18] = 70; + KRFreq[34][87] = 69; + KRFreq[39][24] = 68; + KRFreq[26][8] = 67; + KRFreq[33][48] = 66; + KRFreq[39][30] = 65; + KRFreq[33][28] = 64; + KRFreq[16][67] = 63; + KRFreq[31][78] = 62; + KRFreq[32][23] = 61; + KRFreq[24][55] = 60; + KRFreq[30][68] = 59; + KRFreq[18][60] = 58; + KRFreq[15][17] = 57; + KRFreq[23][34] = 56; + KRFreq[20][49] = 55; + KRFreq[15][78] = 54; + KRFreq[24][14] = 53; + KRFreq[19][41] = 52; + KRFreq[31][55] = 51; + KRFreq[21][39] = 50; + KRFreq[35][9] = 49; + KRFreq[30][15] = 48; + KRFreq[20][52] = 47; + KRFreq[35][71] = 46; + KRFreq[20][7] = 45; + KRFreq[29][72] = 44; + KRFreq[37][77] = 43; + KRFreq[22][35] = 42; + KRFreq[20][61] = 41; + KRFreq[31][60] = 40; + KRFreq[20][93] = 39; + KRFreq[27][92] = 38; + KRFreq[28][16] = 37; + KRFreq[36][26] = 36; + KRFreq[18][89] = 35; + KRFreq[21][63] = 34; + KRFreq[22][52] = 33; + KRFreq[24][65] = 32; + KRFreq[31][8] = 31; + KRFreq[31][49] = 30; + KRFreq[33][30] = 29; + KRFreq[37][15] = 28; + KRFreq[18][18] = 27; + KRFreq[25][50] = 26; + KRFreq[29][20] = 25; + KRFreq[35][48] = 24; + KRFreq[38][75] = 23; + KRFreq[26][83] = 22; + KRFreq[21][87] = 21; + KRFreq[27][71] = 20; + KRFreq[32][91] = 19; + KRFreq[25][73] = 18; + KRFreq[16][84] = 17; + KRFreq[25][31] = 16; + KRFreq[17][90] = 15; + KRFreq[18][40] = 14; + KRFreq[17][77] = 13; + KRFreq[17][35] = 12; + KRFreq[23][52] = 11; + KRFreq[23][35] = 10; + KRFreq[16][5] = 9; + KRFreq[23][58] = 8; + KRFreq[19][60] = 7; + KRFreq[30][32] = 6; + KRFreq[38][34] = 5; + KRFreq[23][4] = 4; + KRFreq[23][1] = 3; + KRFreq[27][57] = 2; + KRFreq[39][38] = 1; + KRFreq[32][33] = 0; + JPFreq[3][74] = 600; + JPFreq[3][45] = 599; + JPFreq[3][3] = 598; + JPFreq[3][24] = 597; + JPFreq[3][30] = 596; + JPFreq[3][42] = 595; + JPFreq[3][46] = 594; + JPFreq[3][39] = 593; + JPFreq[3][11] = 592; + JPFreq[3][37] = 591; + JPFreq[3][38] = 590; + JPFreq[3][31] = 589; + JPFreq[3][41] = 588; + JPFreq[3][5] = 587; + JPFreq[3][10] = 586; + JPFreq[3][75] = 585; + JPFreq[3][65] = 584; + JPFreq[3][72] = 583; + JPFreq[37][91] = 582; + JPFreq[0][27] = 581; + JPFreq[3][18] = 580; + JPFreq[3][22] = 579; + JPFreq[3][61] = 578; + JPFreq[3][14] = 577; + JPFreq[24][80] = 576; + JPFreq[4][82] = 575; + JPFreq[17][80] = 574; + JPFreq[30][44] = 573; + JPFreq[3][73] = 572; + JPFreq[3][64] = 571; + JPFreq[38][14] = 570; + JPFreq[33][70] = 569; + JPFreq[3][1] = 568; + JPFreq[3][16] = 567; + JPFreq[3][35] = 566; + JPFreq[3][40] = 565; + JPFreq[4][74] = 564; + JPFreq[4][24] = 563; + JPFreq[42][59] = 562; + JPFreq[3][7] = 561; + JPFreq[3][71] = 560; + JPFreq[3][12] = 559; + JPFreq[15][75] = 558; + JPFreq[3][20] = 557; + JPFreq[4][39] = 556; + JPFreq[34][69] = 555; + JPFreq[3][28] = 554; + JPFreq[35][24] = 553; + JPFreq[3][82] = 552; + JPFreq[28][47] = 551; + JPFreq[3][67] = 550; + JPFreq[37][16] = 549; + JPFreq[26][93] = 548; + JPFreq[4][1] = 547; + JPFreq[26][85] = 546; + JPFreq[31][14] = 545; + JPFreq[4][3] = 544; + JPFreq[4][72] = 543; + JPFreq[24][51] = 542; + JPFreq[27][51] = 541; + JPFreq[27][49] = 540; + JPFreq[22][77] = 539; + JPFreq[27][10] = 538; + JPFreq[29][68] = 537; + JPFreq[20][35] = 536; + JPFreq[41][11] = 535; + JPFreq[24][70] = 534; + JPFreq[36][61] = 533; + JPFreq[31][23] = 532; + JPFreq[43][16] = 531; + JPFreq[23][68] = 530; + JPFreq[32][15] = 529; + JPFreq[3][32] = 528; + JPFreq[19][53] = 527; + JPFreq[40][83] = 526; + JPFreq[4][14] = 525; + JPFreq[36][9] = 524; + JPFreq[4][73] = 523; + JPFreq[23][10] = 522; + JPFreq[3][63] = 521; + JPFreq[39][14] = 520; + JPFreq[3][78] = 519; + JPFreq[33][47] = 518; + JPFreq[21][39] = 517; + JPFreq[34][46] = 516; + JPFreq[36][75] = 515; + JPFreq[41][92] = 514; + JPFreq[37][93] = 513; + JPFreq[4][34] = 512; + JPFreq[15][86] = 511; + JPFreq[46][1] = 510; + JPFreq[37][65] = 509; + JPFreq[3][62] = 508; + JPFreq[32][73] = 507; + JPFreq[21][65] = 506; + JPFreq[29][75] = 505; + JPFreq[26][51] = 504; + JPFreq[3][34] = 503; + JPFreq[4][10] = 502; + JPFreq[30][22] = 501; + JPFreq[35][73] = 500; + JPFreq[17][82] = 499; + JPFreq[45][8] = 498; + JPFreq[27][73] = 497; + JPFreq[18][55] = 496; + JPFreq[25][2] = 495; + JPFreq[3][26] = 494; + JPFreq[45][46] = 493; + JPFreq[4][22] = 492; + JPFreq[4][40] = 491; + JPFreq[18][10] = 490; + JPFreq[32][9] = 489; + JPFreq[26][49] = 488; + JPFreq[3][47] = 487; + JPFreq[24][65] = 486; + JPFreq[4][76] = 485; + JPFreq[43][67] = 484; + JPFreq[3][9] = 483; + JPFreq[41][37] = 482; + JPFreq[33][68] = 481; + JPFreq[43][31] = 480; + JPFreq[19][55] = 479; + JPFreq[4][30] = 478; + JPFreq[27][33] = 477; + JPFreq[16][62] = 476; + JPFreq[36][35] = 475; + JPFreq[37][15] = 474; + JPFreq[27][70] = 473; + JPFreq[22][71] = 472; + JPFreq[33][45] = 471; + JPFreq[31][78] = 470; + JPFreq[43][59] = 469; + JPFreq[32][19] = 468; + JPFreq[17][28] = 467; + JPFreq[40][28] = 466; + JPFreq[20][93] = 465; + JPFreq[18][15] = 464; + JPFreq[4][23] = 463; + JPFreq[3][23] = 462; + JPFreq[26][64] = 461; + JPFreq[44][92] = 460; + JPFreq[17][27] = 459; + JPFreq[3][56] = 458; + JPFreq[25][38] = 457; + JPFreq[23][31] = 456; + JPFreq[35][43] = 455; + JPFreq[4][54] = 454; + JPFreq[35][19] = 453; + JPFreq[22][47] = 452; + JPFreq[42][0] = 451; + JPFreq[23][28] = 450; + JPFreq[46][33] = 449; + JPFreq[36][85] = 448; + JPFreq[31][12] = 447; + JPFreq[3][76] = 446; + JPFreq[4][75] = 445; + JPFreq[36][56] = 444; + JPFreq[4][64] = 443; + JPFreq[25][77] = 442; + JPFreq[15][52] = 441; + JPFreq[33][73] = 440; + JPFreq[3][55] = 439; + JPFreq[43][82] = 438; + JPFreq[27][82] = 437; + JPFreq[20][3] = 436; + JPFreq[40][51] = 435; + JPFreq[3][17] = 434; + JPFreq[27][71] = 433; + JPFreq[4][52] = 432; + JPFreq[44][48] = 431; + JPFreq[27][2] = 430; + JPFreq[17][39] = 429; + JPFreq[31][8] = 428; + JPFreq[44][54] = 427; + JPFreq[43][18] = 426; + JPFreq[43][77] = 425; + JPFreq[4][61] = 424; + JPFreq[19][91] = 423; + JPFreq[31][13] = 422; + JPFreq[44][71] = 421; + JPFreq[20][0] = 420; + JPFreq[23][87] = 419; + JPFreq[21][14] = 418; + JPFreq[29][13] = 417; + JPFreq[3][58] = 416; + JPFreq[26][18] = 415; + JPFreq[4][47] = 414; + JPFreq[4][18] = 413; + JPFreq[3][53] = 412; + JPFreq[26][92] = 411; + JPFreq[21][7] = 410; + JPFreq[4][37] = 409; + JPFreq[4][63] = 408; + JPFreq[36][51] = 407; + JPFreq[4][32] = 406; + JPFreq[28][73] = 405; + JPFreq[4][50] = 404; + JPFreq[41][60] = 403; + JPFreq[23][1] = 402; + JPFreq[36][92] = 401; + JPFreq[15][41] = 400; + JPFreq[21][71] = 399; + JPFreq[41][30] = 398; + JPFreq[32][76] = 397; + JPFreq[17][34] = 396; + JPFreq[26][15] = 395; + JPFreq[26][25] = 394; + JPFreq[31][77] = 393; + JPFreq[31][3] = 392; + JPFreq[46][34] = 391; + JPFreq[27][84] = 390; + JPFreq[23][8] = 389; + JPFreq[16][0] = 388; + JPFreq[28][80] = 387; + JPFreq[26][54] = 386; + JPFreq[33][18] = 385; + JPFreq[31][20] = 384; + JPFreq[31][62] = 383; + JPFreq[30][41] = 382; + JPFreq[33][30] = 381; + JPFreq[45][45] = 380; + JPFreq[37][82] = 379; + JPFreq[15][33] = 378; + JPFreq[20][12] = 377; + JPFreq[18][5] = 376; + JPFreq[28][86] = 375; + JPFreq[30][19] = 374; + JPFreq[42][43] = 373; + JPFreq[36][31] = 372; + JPFreq[17][93] = 371; + JPFreq[4][15] = 370; + JPFreq[21][20] = 369; + JPFreq[23][21] = 368; + JPFreq[28][72] = 367; + JPFreq[4][20] = 366; + JPFreq[26][55] = 365; + JPFreq[21][5] = 364; + JPFreq[19][16] = 363; + JPFreq[23][64] = 362; + JPFreq[40][59] = 361; + JPFreq[37][26] = 360; + JPFreq[26][56] = 359; + JPFreq[4][12] = 358; + JPFreq[33][71] = 357; + JPFreq[32][39] = 356; + JPFreq[38][40] = 355; + JPFreq[22][74] = 354; + JPFreq[3][25] = 353; + JPFreq[15][48] = 352; + JPFreq[41][82] = 351; + JPFreq[41][9] = 350; + JPFreq[25][48] = 349; + JPFreq[31][71] = 348; + JPFreq[43][29] = 347; + JPFreq[26][80] = 346; + JPFreq[4][5] = 345; + JPFreq[18][71] = 344; + JPFreq[29][0] = 343; + JPFreq[43][43] = 342; + JPFreq[23][81] = 341; + JPFreq[4][42] = 340; + JPFreq[44][28] = 339; + JPFreq[23][93] = 338; + JPFreq[17][81] = 337; + JPFreq[25][25] = 336; + JPFreq[41][23] = 335; + JPFreq[34][35] = 334; + JPFreq[4][53] = 333; + JPFreq[28][36] = 332; + JPFreq[4][41] = 331; + JPFreq[25][60] = 330; + JPFreq[23][20] = 329; + JPFreq[3][43] = 328; + JPFreq[24][79] = 327; + JPFreq[29][41] = 326; + JPFreq[30][83] = 325; + JPFreq[3][50] = 324; + JPFreq[22][18] = 323; + JPFreq[18][3] = 322; + JPFreq[39][30] = 321; + JPFreq[4][28] = 320; + JPFreq[21][64] = 319; + JPFreq[4][68] = 318; + JPFreq[17][71] = 317; + JPFreq[27][0] = 316; + JPFreq[39][28] = 315; + JPFreq[30][13] = 314; + JPFreq[36][70] = 313; + JPFreq[20][82] = 312; + JPFreq[33][38] = 311; + JPFreq[44][87] = 310; + JPFreq[34][45] = 309; + JPFreq[4][26] = 308; + JPFreq[24][44] = 307; + JPFreq[38][67] = 306; + JPFreq[38][6] = 305; + JPFreq[30][68] = 304; + JPFreq[15][89] = 303; + JPFreq[24][93] = 302; + JPFreq[40][41] = 301; + JPFreq[38][3] = 300; + JPFreq[28][23] = 299; + JPFreq[26][17] = 298; + JPFreq[4][38] = 297; + JPFreq[22][78] = 296; + JPFreq[15][37] = 295; + JPFreq[25][85] = 294; + JPFreq[4][9] = 293; + JPFreq[4][7] = 292; + JPFreq[27][53] = 291; + JPFreq[39][29] = 290; + JPFreq[41][43] = 289; + JPFreq[25][62] = 288; + JPFreq[4][48] = 287; + JPFreq[28][28] = 286; + JPFreq[21][40] = 285; + JPFreq[36][73] = 284; + JPFreq[26][39] = 283; + JPFreq[22][54] = 282; + JPFreq[33][5] = 281; + JPFreq[19][21] = 280; + JPFreq[46][31] = 279; + JPFreq[20][64] = 278; + JPFreq[26][63] = 277; + JPFreq[22][23] = 276; + JPFreq[25][81] = 275; + JPFreq[4][62] = 274; + JPFreq[37][31] = 273; + JPFreq[40][52] = 272; + JPFreq[29][79] = 271; + JPFreq[41][48] = 270; + JPFreq[31][57] = 269; + JPFreq[32][92] = 268; + JPFreq[36][36] = 267; + JPFreq[27][7] = 266; + JPFreq[35][29] = 265; + JPFreq[37][34] = 264; + JPFreq[34][42] = 263; + JPFreq[27][15] = 262; + JPFreq[33][27] = 261; + JPFreq[31][38] = 260; + JPFreq[19][79] = 259; + JPFreq[4][31] = 258; + JPFreq[4][66] = 257; + JPFreq[17][32] = 256; + JPFreq[26][67] = 255; + JPFreq[16][30] = 254; + JPFreq[26][46] = 253; + JPFreq[24][26] = 252; + JPFreq[35][10] = 251; + JPFreq[18][37] = 250; + JPFreq[3][19] = 249; + JPFreq[33][69] = 248; + JPFreq[31][9] = 247; + JPFreq[45][29] = 246; + JPFreq[3][15] = 245; + JPFreq[18][54] = 244; + JPFreq[3][44] = 243; + JPFreq[31][29] = 242; + JPFreq[18][45] = 241; + JPFreq[38][28] = 240; + JPFreq[24][12] = 239; + JPFreq[35][82] = 238; + JPFreq[17][43] = 237; + JPFreq[28][9] = 236; + JPFreq[23][25] = 235; + JPFreq[44][37] = 234; + JPFreq[23][75] = 233; + JPFreq[23][92] = 232; + JPFreq[0][24] = 231; + JPFreq[19][74] = 230; + JPFreq[45][32] = 229; + JPFreq[16][72] = 228; + JPFreq[16][93] = 227; + JPFreq[45][13] = 226; + JPFreq[24][8] = 225; + JPFreq[25][47] = 224; + JPFreq[28][26] = 223; + JPFreq[43][81] = 222; + JPFreq[32][71] = 221; + JPFreq[18][41] = 220; + JPFreq[26][62] = 219; + JPFreq[41][24] = 218; + JPFreq[40][11] = 217; + JPFreq[43][57] = 216; + JPFreq[34][53] = 215; + JPFreq[20][32] = 214; + JPFreq[34][43] = 213; + JPFreq[41][91] = 212; + JPFreq[29][57] = 211; + JPFreq[15][43] = 210; + JPFreq[22][89] = 209; + JPFreq[33][83] = 208; + JPFreq[43][20] = 207; + JPFreq[25][58] = 206; + JPFreq[30][30] = 205; + JPFreq[4][56] = 204; + JPFreq[17][64] = 203; + JPFreq[23][0] = 202; + JPFreq[44][12] = 201; + JPFreq[25][37] = 200; + JPFreq[35][13] = 199; + JPFreq[20][30] = 198; + JPFreq[21][84] = 197; + JPFreq[29][14] = 196; + JPFreq[30][5] = 195; + JPFreq[37][2] = 194; + JPFreq[4][78] = 193; + JPFreq[29][78] = 192; + JPFreq[29][84] = 191; + JPFreq[32][86] = 190; + JPFreq[20][68] = 189; + JPFreq[30][39] = 188; + JPFreq[15][69] = 187; + JPFreq[4][60] = 186; + JPFreq[20][61] = 185; + JPFreq[41][67] = 184; + JPFreq[16][35] = 183; + JPFreq[36][57] = 182; + JPFreq[39][80] = 181; + JPFreq[4][59] = 180; + JPFreq[4][44] = 179; + JPFreq[40][54] = 178; + JPFreq[30][8] = 177; + JPFreq[44][30] = 176; + JPFreq[31][93] = 175; + JPFreq[31][47] = 174; + JPFreq[16][70] = 173; + JPFreq[21][0] = 172; + JPFreq[17][35] = 171; + JPFreq[21][67] = 170; + JPFreq[44][18] = 169; + JPFreq[36][29] = 168; + JPFreq[18][67] = 167; + JPFreq[24][28] = 166; + JPFreq[36][24] = 165; + JPFreq[23][5] = 164; + JPFreq[31][65] = 163; + JPFreq[26][59] = 162; + JPFreq[28][2] = 161; + JPFreq[39][69] = 160; + JPFreq[42][40] = 159; + JPFreq[37][80] = 158; + JPFreq[15][66] = 157; + JPFreq[34][38] = 156; + JPFreq[28][48] = 155; + JPFreq[37][77] = 154; + JPFreq[29][34] = 153; + JPFreq[33][12] = 152; + JPFreq[4][65] = 151; + JPFreq[30][31] = 150; + JPFreq[27][92] = 149; + JPFreq[4][2] = 148; + JPFreq[4][51] = 147; + JPFreq[23][77] = 146; + JPFreq[4][35] = 145; + JPFreq[3][13] = 144; + JPFreq[26][26] = 143; + JPFreq[44][4] = 142; + JPFreq[39][53] = 141; + JPFreq[20][11] = 140; + JPFreq[40][33] = 139; + JPFreq[45][7] = 138; + JPFreq[4][70] = 137; + JPFreq[3][49] = 136; + JPFreq[20][59] = 135; + JPFreq[21][12] = 134; + JPFreq[33][53] = 133; + JPFreq[20][14] = 132; + JPFreq[37][18] = 131; + JPFreq[18][17] = 130; + JPFreq[36][23] = 129; + JPFreq[18][57] = 128; + JPFreq[26][74] = 127; + JPFreq[35][2] = 126; + JPFreq[38][58] = 125; + JPFreq[34][68] = 124; + JPFreq[29][81] = 123; + JPFreq[20][69] = 122; + JPFreq[39][86] = 121; + JPFreq[4][16] = 120; + JPFreq[16][49] = 119; + JPFreq[15][72] = 118; + JPFreq[26][35] = 117; + JPFreq[32][14] = 116; + JPFreq[40][90] = 115; + JPFreq[33][79] = 114; + JPFreq[35][4] = 113; + JPFreq[23][33] = 112; + JPFreq[19][19] = 111; + JPFreq[31][41] = 110; + JPFreq[44][1] = 109; + JPFreq[22][56] = 108; + JPFreq[31][27] = 107; + JPFreq[32][18] = 106; + JPFreq[27][32] = 105; + JPFreq[37][39] = 104; + JPFreq[42][11] = 103; + JPFreq[29][71] = 102; + JPFreq[32][58] = 101; + JPFreq[46][10] = 100; + JPFreq[17][30] = 99; + JPFreq[38][15] = 98; + JPFreq[29][60] = 97; + JPFreq[4][11] = 96; + JPFreq[38][31] = 95; + JPFreq[40][79] = 94; + JPFreq[28][49] = 93; + JPFreq[28][84] = 92; + JPFreq[26][77] = 91; + JPFreq[22][32] = 90; + JPFreq[33][17] = 89; + JPFreq[23][18] = 88; + JPFreq[32][64] = 87; + JPFreq[4][6] = 86; + JPFreq[33][51] = 85; + JPFreq[44][77] = 84; + JPFreq[29][5] = 83; + JPFreq[46][25] = 82; + JPFreq[19][58] = 81; + JPFreq[4][46] = 80; + JPFreq[15][71] = 79; + JPFreq[18][58] = 78; + JPFreq[26][45] = 77; + JPFreq[45][66] = 76; + JPFreq[34][10] = 75; + JPFreq[19][37] = 74; + JPFreq[33][65] = 73; + JPFreq[44][52] = 72; + JPFreq[16][38] = 71; + JPFreq[36][46] = 70; + JPFreq[20][26] = 69; + JPFreq[30][37] = 68; + JPFreq[4][58] = 67; + JPFreq[43][2] = 66; + JPFreq[30][18] = 65; + JPFreq[19][35] = 64; + JPFreq[15][68] = 63; + JPFreq[3][36] = 62; + JPFreq[35][40] = 61; + JPFreq[36][32] = 60; + JPFreq[37][14] = 59; + JPFreq[17][11] = 58; + JPFreq[19][78] = 57; + JPFreq[37][11] = 56; + JPFreq[28][63] = 55; + JPFreq[29][61] = 54; + JPFreq[33][3] = 53; + JPFreq[41][52] = 52; + JPFreq[33][63] = 51; + JPFreq[22][41] = 50; + JPFreq[4][19] = 49; + JPFreq[32][41] = 48; + JPFreq[24][4] = 47; + JPFreq[31][28] = 46; + JPFreq[43][30] = 45; + JPFreq[17][3] = 44; + JPFreq[43][70] = 43; + JPFreq[34][19] = 42; + JPFreq[20][77] = 41; + JPFreq[18][83] = 40; + JPFreq[17][15] = 39; + JPFreq[23][61] = 38; + JPFreq[40][27] = 37; + JPFreq[16][48] = 36; + JPFreq[39][78] = 35; + JPFreq[41][53] = 34; + JPFreq[40][91] = 33; + JPFreq[40][72] = 32; + JPFreq[18][52] = 31; + JPFreq[35][66] = 30; + JPFreq[39][93] = 29; + JPFreq[19][48] = 28; + JPFreq[26][36] = 27; + JPFreq[27][25] = 26; + JPFreq[42][71] = 25; + JPFreq[42][85] = 24; + JPFreq[26][48] = 23; + JPFreq[28][15] = 22; + JPFreq[3][66] = 21; + JPFreq[25][24] = 20; + JPFreq[27][43] = 19; + JPFreq[27][78] = 18; + JPFreq[45][43] = 17; + JPFreq[27][72] = 16; + JPFreq[40][29] = 15; + JPFreq[41][0] = 14; + JPFreq[19][57] = 13; + JPFreq[15][59] = 12; + JPFreq[29][29] = 11; + JPFreq[4][25] = 10; + JPFreq[21][42] = 9; + JPFreq[23][35] = 8; + JPFreq[33][1] = 7; + JPFreq[4][57] = 6; + JPFreq[17][60] = 5; + JPFreq[25][19] = 4; + JPFreq[22][65] = 3; + JPFreq[42][29] = 2; + JPFreq[27][66] = 1; + JPFreq[26][89] = 0; + } +} + +class Encoding { + // Supported Encoding Types + + public static int GB2312 = 0; + + public static int GBK = 1; + + public static int GB18030 = 2; + + public static int HZ = 3; + + public static int BIG5 = 4; + + public static int CNS11643 = 5; + + public static int UTF8 = 6; + + public static int UTF8T = 7; + + public static int UTF8S = 8; + + public static int UNICODE = 9; + + public static int UNICODET = 10; + + public static int UNICODES = 11; + + public static int ISO2022CN = 12; + + public static int ISO2022CN_CNS = 13; + + public static int ISO2022CN_GB = 14; + + public static int EUC_KR = 15; + + public static int CP949 = 16; + + public static int ISO2022KR = 17; + + public static int JOHAB = 18; + + public static int SJIS = 19; + + public static int EUC_JP = 20; + + public static int ISO2022JP = 21; + + public static int ASCII = 22; + + public static int OTHER = 23; + + public static int TOTALTYPES = 24; + + public final static int SIMP = 0; + + public final static int TRAD = 1; + + // Names of the encodings as understood by Java + public static String[] javaname; + + // Names of the encodings for human viewing + public static String[] nicename; + + // Names of charsets as used in charset parameter of HTML Meta tag + public static String[] htmlname; + + // Constructor + public Encoding() { + javaname = new String[TOTALTYPES]; + nicename = new String[TOTALTYPES]; + htmlname = new String[TOTALTYPES]; + // Assign encoding names + javaname[GB2312] = "GB2312"; + javaname[GBK] = "GBK"; + javaname[GB18030] = "GB18030"; + javaname[HZ] = "ASCII"; // What to put here? Sun doesn't support HZ + javaname[ISO2022CN_GB] = "ISO2022CN_GB"; + javaname[BIG5] = "BIG5"; + javaname[CNS11643] = "EUC-TW"; + javaname[ISO2022CN_CNS] = "ISO2022CN_CNS"; + javaname[ISO2022CN] = "ISO2022CN"; + javaname[UTF8] = "UTF-8"; + javaname[UTF8T] = "UTF-8"; + javaname[UTF8S] = "UTF-8"; + javaname[UNICODE] = "Unicode"; + javaname[UNICODET] = "Unicode"; + javaname[UNICODES] = "Unicode"; + javaname[EUC_KR] = "EUC_KR"; + javaname[CP949] = "MS949"; + javaname[ISO2022KR] = "ISO2022KR"; + javaname[JOHAB] = "Johab"; + javaname[SJIS] = "SJIS"; + javaname[EUC_JP] = "EUC_JP"; + javaname[ISO2022JP] = "ISO2022JP"; + javaname[ASCII] = "ASCII"; + javaname[OTHER] = "ISO8859_1"; + // Assign encoding names + htmlname[GB2312] = "GB2312"; + htmlname[GBK] = "GBK"; + htmlname[GB18030] = "GB18030"; + htmlname[HZ] = "HZ-GB-2312"; + htmlname[ISO2022CN_GB] = "ISO-2022-CN-EXT"; + htmlname[BIG5] = "BIG5"; + htmlname[CNS11643] = "EUC-TW"; + htmlname[ISO2022CN_CNS] = "ISO-2022-CN-EXT"; + htmlname[ISO2022CN] = "ISO-2022-CN"; + htmlname[UTF8] = "UTF-8"; + htmlname[UTF8T] = "UTF-8"; + htmlname[UTF8S] = "UTF-8"; + htmlname[UNICODE] = "UTF-16"; + htmlname[UNICODET] = "UTF-16"; + htmlname[UNICODES] = "UTF-16"; + htmlname[EUC_KR] = "EUC-KR"; + htmlname[CP949] = "x-windows-949"; + htmlname[ISO2022KR] = "ISO-2022-KR"; + htmlname[JOHAB] = "x-Johab"; + htmlname[SJIS] = "Shift_JIS"; + htmlname[EUC_JP] = "EUC-JP"; + htmlname[ISO2022JP] = "ISO-2022-JP"; + htmlname[ASCII] = "ASCII"; + htmlname[OTHER] = "ISO8859-1"; + // Assign Human readable names + nicename[GB2312] = "GB-2312"; + nicename[GBK] = "GBK"; + nicename[GB18030] = "GB18030"; + nicename[HZ] = "HZ"; + nicename[ISO2022CN_GB] = "ISO2022CN-GB"; + nicename[BIG5] = "Big5"; + nicename[CNS11643] = "CNS11643"; + nicename[ISO2022CN_CNS] = "ISO2022CN-CNS"; + nicename[ISO2022CN] = "ISO2022 CN"; + nicename[UTF8] = "UTF-8"; + nicename[UTF8T] = "UTF-8 (Trad)"; + nicename[UTF8S] = "UTF-8 (Simp)"; + nicename[UNICODE] = "Unicode"; + nicename[UNICODET] = "Unicode (Trad)"; + nicename[UNICODES] = "Unicode (Simp)"; + nicename[EUC_KR] = "EUC-KR"; + nicename[CP949] = "CP949"; + nicename[ISO2022KR] = "ISO 2022 KR"; + nicename[JOHAB] = "Johab"; + nicename[SJIS] = "Shift-JIS"; + nicename[EUC_JP] = "EUC-JP"; + nicename[ISO2022JP] = "ISO 2022 JP"; + nicename[ASCII] = "ASCII"; + nicename[OTHER] = "OTHER"; + } +} diff --git a/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataInputStream.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataInputStream.java new file mode 100644 index 00000000..5f4e8824 --- /dev/null +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataInputStream.java @@ -0,0 +1,136 @@ + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common.io; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.IOException; + + /** + * + * @author yaqiang - come from OpenJump + */ + public class EndianDataInputStream { + private final DataInputStream inputStream; + private final byte[] workSpace = new byte[8]; //chars are 16 bits, so we always quash the 1st 8 bits + + /** Creates new EndianDataInputStream + * @param in */ + public EndianDataInputStream(java.io.InputStream in) { + inputStream = new DataInputStream(new BufferedInputStream(in)); + } + + /** close the strea*/ + public void close() throws IOException { + inputStream.close(); + } + + /** read a byte in BigEndian - the same as LE because its only 1 byt*/ + public byte readByteBE() throws IOException { + return inputStream.readByte(); + } + + /** read a byte in LittleEndian - the same as BE because its only 1 byt*/ + public byte readByteLE() throws IOException { + return inputStream.readByte(); + } + + /** read a byte in LittleEndian - the same as BE because its only 1 byte*/ + public void readByteLEnum(byte[] b) throws IOException { + inputStream.readFully(b); + } + + + /** read a byte in BigEndian - the same as LE because its only 1 byte. returns int as per java.io.DataStream*/ + public int readUnsignedByteBE() throws IOException { + return inputStream.readUnsignedByte(); + } + + /** read a byte in LittleEndian - the same as BE because its only 1 byte. returns int as per java.io.DataStream*/ + public int readUnsignedByteLE() throws IOException { + return inputStream.readUnsignedByte(); + } + + /** read a 16bit short in BE*/ + public short readShortBE() throws IOException { + return inputStream.readShort(); + } + + /** read a 16bit short in LE*/ + public short readShortLE() throws IOException { + inputStream.readFully(workSpace, 0, 2); + + return (short) (((workSpace[1] & 0xff) << 8) | (workSpace[0] & 0xff)); + } + + /** read a 32bit int in BE*/ + public int readIntBE() throws IOException { + return inputStream.readInt(); + } + + /** read a 32bit int in LE*/ + public int readIntLE() throws IOException { + inputStream.readFully(workSpace, 0, 4); + + return ((workSpace[3] & 0xff) << 24) | ((workSpace[2] & 0xff) << 16) | + ((workSpace[1] & 0xff) << 8) | (workSpace[0] & 0xff); + } + + /** read a 64bit long in BE*/ + public long readLongBE() throws IOException { + return inputStream.readLong(); + } + + /** read a 64bit long in LE*/ + public long readLongLE() throws IOException { + inputStream.readFully(workSpace, 0, 8); + + return ((long) (workSpace[7] & 0xff) << 56) | + ((long) (workSpace[6] & 0xff) << 48) | + ((long) (workSpace[5] & 0xff) << 40) | + ((long) (workSpace[4] & 0xff) << 32) | + ((long) (workSpace[3] & 0xff) << 24) | + ((long) (workSpace[2] & 0xff) << 16) | + ((long) (workSpace[1] & 0xff) << 8) | ((long) (workSpace[0] & 0xff)); + } + + /** read a 64bit double in BE*/ + public double readDoubleBE() throws IOException { + return inputStream.readDouble(); + } + + /** read a 64bit double in LE*/ + public double readDoubleLE() throws IOException { + long l; + + inputStream.readFully(workSpace, 0, 8); + l = ((long) (workSpace[7] & 0xff) << 56) | + ((long) (workSpace[6] & 0xff) << 48) | + ((long) (workSpace[5] & 0xff) << 40) | + ((long) (workSpace[4] & 0xff) << 32) | + ((long) (workSpace[3] & 0xff) << 24) | + ((long) (workSpace[2] & 0xff) << 16) | + ((long) (workSpace[1] & 0xff) << 8) | + ((long) (workSpace[0] & 0xff)); + + return Double.longBitsToDouble(l); + } + + /** skip ahead in the stream + * @param num number of bytes to read ahead + */ + public int skipBytes(int num) throws IOException { + return inputStream.skipBytes(num); + } + } diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataOutputStream.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataOutputStream.java similarity index 85% rename from MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataOutputStream.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataOutputStream.java index 72bc122d..16337ab7 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/EndianDataOutputStream.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/EndianDataOutputStream.java @@ -1,211 +1,211 @@ -/* Copyright 2012 Yaqiang Wang, - * yaqiang.wang@gmail.com - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - */ -package org.meteoinfo.io; - -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * - * @author yaqiang - come from OpenJump - */ -public class EndianDataOutputStream { - - private final java.io.DataOutputStream outputStream; - - /** - * Creates new EndianDataOutputStream - * @param out - */ - public EndianDataOutputStream(java.io.OutputStream out) { - outputStream = new DataOutputStream(out); - } - - /** - * close stream* - * @throws java.io.IOException - */ - public void close() throws IOException { - outputStream.close(); - } - - /** - * Write bytes - * @param b bytes - * @throws IOException - */ - public void write(byte[] b) throws IOException{ - outputStream.write(b); - } - - /** - * write bytes - * @param b - * @param off - * @param len - * @throws java.io.IOException - */ - public void write(byte[] b, int off, int len) throws IOException { - outputStream.write(b, off, len); - } - - /** - * flush stream* - * @throws java.io.IOException - */ - public void flush() throws IOException { - outputStream.flush(); - } - - /** - * write a byte in LittleEndian - this is exactly the same as the BigEndian - * version since there's no endian in a single byte - * @param b - * @throws java.io.IOException - */ - public void writeByteLE(int b) throws IOException { - outputStream.writeByte(b); - } - - /** - * write a byte in BigEndian - this is exactly the same as the LittleEndian - * version since there's no endian in a single byte - * @param b - * @throws java.io.IOException - */ - public void writeByteBE(int b) throws IOException { - outputStream.writeByte(b); - } - - /** - * write a set of bytes in LittleEndian - this is exactly the same as the - * BigEndian version since there's no endian in a single byte - * @param s - * @throws java.io.IOException - */ - public void writeBytesLE(String s) throws IOException { - outputStream.writeBytes(s); - } - - /** - * write a set of bytes in BigEndian - this is exactly the same as the - * LittleEndian version since there's no endian in a single byte - * @param s - * @throws java.io.IOException - */ - public void writeBytesBE(String s) throws IOException { - outputStream.writeBytes(s); - } - - /** - * write a 16bit short in BigEndian - * @param s - * @throws java.io.IOException - */ - public void writeShortBE(int s) throws IOException { - outputStream.writeShort(s); - } - - /** - * write a 16bit short in LittleEndian - * @param s - * @throws java.io.IOException - */ - public void writeShortLE(int s) throws IOException { - outputStream.writeByte(s); - outputStream.writeByte(s >> 8); - } - - /** - * write a 32bit int in BigEndian - * @param i - * @throws java.io.IOException - */ - public void writeIntBE(int i) throws IOException { - outputStream.writeInt(i); - } - - /** - * write a 32bit int in LittleEndian - * @param i - * @throws java.io.IOException - */ - public void writeIntLE(int i) throws IOException { - outputStream.writeByte(i); - outputStream.writeByte(i >> 8); - outputStream.writeByte(i >> 16); - outputStream.writeByte(i >> 24); - } - - /** - * write a 64bit long in BigEndian - * @param l - * @throws java.io.IOException - */ - public void writeLongBE(long l) throws IOException { - outputStream.writeLong(l); - } - - /** - * write a 64bit long in LittleEndian - * @param l - * @throws java.io.IOException - */ - public void writeLongLE(long l) throws IOException { - outputStream.writeByte((byte) (l)); - outputStream.writeByte((byte) (l >> 8)); - outputStream.writeByte((byte) (l >> 16)); - outputStream.writeByte((byte) (l >> 24)); - outputStream.writeByte((byte) (l >> 32)); - outputStream.writeByte((byte) (l >> 40)); - outputStream.writeByte((byte) (l >> 48)); - outputStream.writeByte((byte) (l >> 56)); - } - - /** - * Write a float in big endian - * @param f Float value - * @throws IOException - */ - public void writeFloatBE(float f) throws IOException { - outputStream.writeFloat(f); - } - - /** - * Write a float in little endian - * @param f Float value - * @throws IOException - */ - public void writeFloatLE(float f) throws IOException { - this.writeIntLE(Float.floatToIntBits(f)); - } - - /** - * write a 64bit double in BigEndian - * @param d - * @throws java.io.IOException - */ - public void writeDoubleBE(double d) throws IOException { - outputStream.writeDouble(d); - } - - /** - * write a 64bit double in LittleEndian - * @param d - * @throws java.io.IOException - */ - public void writeDoubleLE(double d) throws IOException { - this.writeLongLE(Double.doubleToLongBits(d)); - } -} +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common.io; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * + * @author yaqiang - come from OpenJump + */ +public class EndianDataOutputStream { + + private final DataOutputStream outputStream; + + /** + * Creates new EndianDataOutputStream + * @param out + */ + public EndianDataOutputStream(java.io.OutputStream out) { + outputStream = new DataOutputStream(out); + } + + /** + * close stream* + * @throws IOException + */ + public void close() throws IOException { + outputStream.close(); + } + + /** + * Write bytes + * @param b bytes + * @throws IOException + */ + public void write(byte[] b) throws IOException{ + outputStream.write(b); + } + + /** + * write bytes + * @param b + * @param off + * @param len + * @throws IOException + */ + public void write(byte[] b, int off, int len) throws IOException { + outputStream.write(b, off, len); + } + + /** + * flush stream* + * @throws IOException + */ + public void flush() throws IOException { + outputStream.flush(); + } + + /** + * write a byte in LittleEndian - this is exactly the same as the BigEndian + * version since there's no endian in a single byte + * @param b + * @throws IOException + */ + public void writeByteLE(int b) throws IOException { + outputStream.writeByte(b); + } + + /** + * write a byte in BigEndian - this is exactly the same as the LittleEndian + * version since there's no endian in a single byte + * @param b + * @throws IOException + */ + public void writeByteBE(int b) throws IOException { + outputStream.writeByte(b); + } + + /** + * write a set of bytes in LittleEndian - this is exactly the same as the + * BigEndian version since there's no endian in a single byte + * @param s + * @throws IOException + */ + public void writeBytesLE(String s) throws IOException { + outputStream.writeBytes(s); + } + + /** + * write a set of bytes in BigEndian - this is exactly the same as the + * LittleEndian version since there's no endian in a single byte + * @param s + * @throws IOException + */ + public void writeBytesBE(String s) throws IOException { + outputStream.writeBytes(s); + } + + /** + * write a 16bit short in BigEndian + * @param s + * @throws IOException + */ + public void writeShortBE(int s) throws IOException { + outputStream.writeShort(s); + } + + /** + * write a 16bit short in LittleEndian + * @param s + * @throws IOException + */ + public void writeShortLE(int s) throws IOException { + outputStream.writeByte(s); + outputStream.writeByte(s >> 8); + } + + /** + * write a 32bit int in BigEndian + * @param i + * @throws IOException + */ + public void writeIntBE(int i) throws IOException { + outputStream.writeInt(i); + } + + /** + * write a 32bit int in LittleEndian + * @param i + * @throws IOException + */ + public void writeIntLE(int i) throws IOException { + outputStream.writeByte(i); + outputStream.writeByte(i >> 8); + outputStream.writeByte(i >> 16); + outputStream.writeByte(i >> 24); + } + + /** + * write a 64bit long in BigEndian + * @param l + * @throws IOException + */ + public void writeLongBE(long l) throws IOException { + outputStream.writeLong(l); + } + + /** + * write a 64bit long in LittleEndian + * @param l + * @throws IOException + */ + public void writeLongLE(long l) throws IOException { + outputStream.writeByte((byte) (l)); + outputStream.writeByte((byte) (l >> 8)); + outputStream.writeByte((byte) (l >> 16)); + outputStream.writeByte((byte) (l >> 24)); + outputStream.writeByte((byte) (l >> 32)); + outputStream.writeByte((byte) (l >> 40)); + outputStream.writeByte((byte) (l >> 48)); + outputStream.writeByte((byte) (l >> 56)); + } + + /** + * Write a float in big endian + * @param f Float value + * @throws IOException + */ + public void writeFloatBE(float f) throws IOException { + outputStream.writeFloat(f); + } + + /** + * Write a float in little endian + * @param f Float value + * @throws IOException + */ + public void writeFloatLE(float f) throws IOException { + this.writeIntLE(Float.floatToIntBits(f)); + } + + /** + * write a 64bit double in BigEndian + * @param d + * @throws IOException + */ + public void writeDoubleBE(double d) throws IOException { + outputStream.writeDouble(d); + } + + /** + * write a 64bit double in LittleEndian + * @param d + * @throws IOException + */ + public void writeDoubleLE(double d) throws IOException { + this.writeLongLE(Double.doubleToLongBits(d)); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/FileCharsetDetector.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/FileCharsetDetector.java similarity index 96% rename from MeteoInfoLib/src/main/java/org/meteoinfo/io/FileCharsetDetector.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/io/FileCharsetDetector.java index 9e518bcd..9cac2c64 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/FileCharsetDetector.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/FileCharsetDetector.java @@ -1,144 +1,144 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.io; - -//Use jchardet get file encoding -javacode -//Error with Chinese characters using ANSI encoding -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import org.mozilla.intl.chardet.nsDetector; -import org.mozilla.intl.chardet.nsICharsetDetectionObserver; - -/** - * Using JCharDet get file charset - * - * @author icer PS: JCharDet: - * http://jchardet.sourceforge.net/ - */ -public class FileCharsetDetector { - - private boolean found = false; - - private String encoding = null; - - /** - * Check file encoding - * - * @param file File object - * @return Encoding string - * @throws FileNotFoundException - * @throws IOException - */ - public String guestFileEncoding(File file) throws FileNotFoundException, - IOException { - return guestFileEncoding(file, new nsDetector()); - } - - /** - * Check file encoding - * - * @param file File object - * @param languageHint Language comment code, eg: 1 : Japanese; 2 : Chinese; 3 : Simplified - * Chinese; 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) - * @return File encoding, eg: UTF-8,GBK,GB2312 - * @throws FileNotFoundException - * @throws IOException - */ - public String guestFileEncoding(File file, int languageHint) - throws FileNotFoundException, IOException { - return guestFileEncoding(file, new nsDetector(languageHint)); - } - - /** - * Check file encoding - * - * @param path File path - * @return File encoding - * @throws FileNotFoundException - * @throws IOException - */ - public String guestFileEncoding(String path) throws FileNotFoundException, - IOException { - return guestFileEncoding(new File(path)); - } - - /** - * Get file encoding - * - * @param path File path - * @param languageHint Language comment code, eg: 1 : Japanese; 2 : Chinese; 3 : Simplified - * Chinese; 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) - * @return - * @throws FileNotFoundException - * @throws IOException - */ - public String guestFileEncoding(String path, int languageHint) - throws FileNotFoundException, IOException { - return guestFileEncoding(new File(path), languageHint); - } - - /** - * Get file encoding - * - * @param file File object - * @param det Detector - * @return File encoding - * @throws FileNotFoundException - * @throws IOException - */ - private String guestFileEncoding(File file, nsDetector det) - throws FileNotFoundException, IOException { - // Set an observer... - // The Notify() will be called when a matching charset is found. - det.Init(new nsICharsetDetectionObserver() { - @Override - public void Notify(String charset) { - found = true; - encoding = charset; - } - }); - - BufferedInputStream imp = new BufferedInputStream(new FileInputStream( - file)); - - byte[] buf = new byte[1024]; - int len; - boolean done = false; - boolean isAscii = true; - - while ((len = imp.read(buf, 0, buf.length)) != -1) { - // Check if the stream is only ascii. - if (isAscii) { - isAscii = det.isAscii(buf, len); - } - - // DoIt if non-ascii and not done yet. - if (!isAscii && !done) { - done = det.DoIt(buf, len, false); - } - } - det.DataEnd(); - - if (isAscii) { - encoding = "ASCII"; - found = true; - } - - if (!found) { - String prob[] = det.getProbableCharsets(); - if (prob.length > 0) { - // use file guess encoding when no encoding found - encoding = prob[0]; - } else { - return null; - } - } - return encoding; - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common.io; + +//Use jchardet get file encoding -javacode +//Error with Chinese characters using ANSI encoding +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.mozilla.intl.chardet.nsDetector; +import org.mozilla.intl.chardet.nsICharsetDetectionObserver; + +/** + * Using JCharDet get file charset + * + * @author icer PS: JCharDet: + * http://jchardet.sourceforge.net/ + */ +public class FileCharsetDetector { + + private boolean found = false; + + private String encoding = null; + + /** + * Check file encoding + * + * @param file File object + * @return Encoding string + * @throws FileNotFoundException + * @throws IOException + */ + public String guestFileEncoding(File file) throws FileNotFoundException, + IOException { + return guestFileEncoding(file, new nsDetector()); + } + + /** + * Check file encoding + * + * @param file File object + * @param languageHint Language comment code, eg: 1 : Japanese; 2 : Chinese; 3 : Simplified + * Chinese; 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) + * @return File encoding, eg: UTF-8,GBK,GB2312 + * @throws FileNotFoundException + * @throws IOException + */ + public String guestFileEncoding(File file, int languageHint) + throws FileNotFoundException, IOException { + return guestFileEncoding(file, new nsDetector(languageHint)); + } + + /** + * Check file encoding + * + * @param path File path + * @return File encoding + * @throws FileNotFoundException + * @throws IOException + */ + public String guestFileEncoding(String path) throws FileNotFoundException, + IOException { + return guestFileEncoding(new File(path)); + } + + /** + * Get file encoding + * + * @param path File path + * @param languageHint Language comment code, eg: 1 : Japanese; 2 : Chinese; 3 : Simplified + * Chinese; 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) + * @return + * @throws FileNotFoundException + * @throws IOException + */ + public String guestFileEncoding(String path, int languageHint) + throws FileNotFoundException, IOException { + return guestFileEncoding(new File(path), languageHint); + } + + /** + * Get file encoding + * + * @param file File object + * @param det Detector + * @return File encoding + * @throws FileNotFoundException + * @throws IOException + */ + private String guestFileEncoding(File file, nsDetector det) + throws FileNotFoundException, IOException { + // Set an observer... + // The Notify() will be called when a matching charset is found. + det.Init(new nsICharsetDetectionObserver() { + @Override + public void Notify(String charset) { + found = true; + encoding = charset; + } + }); + + BufferedInputStream imp = new BufferedInputStream(new FileInputStream( + file)); + + byte[] buf = new byte[1024]; + int len; + boolean done = false; + boolean isAscii = true; + + while ((len = imp.read(buf, 0, buf.length)) != -1) { + // Check if the stream is only ascii. + if (isAscii) { + isAscii = det.isAscii(buf, len); + } + + // DoIt if non-ascii and not done yet. + if (!isAscii && !done) { + done = det.DoIt(buf, len, false); + } + } + det.DataEnd(); + + if (isAscii) { + encoding = "ASCII"; + found = true; + } + + if (!found) { + String prob[] = det.getProbableCharsets(); + if (prob.length > 0) { + // use file guess encoding when no encoding found + encoding = prob[0]; + } else { + return null; + } + } + return encoding; + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/IOUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/IOUtil.java similarity index 93% rename from MeteoInfoLib/src/main/java/org/meteoinfo/io/IOUtil.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/io/IOUtil.java index 4bf5d59d..d4240bfa 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/IOUtil.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/IOUtil.java @@ -1,132 +1,134 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.io; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author wyq - */ -public class IOUtil { - - /** - * Get file chart - * - * @param filePath File path - * @return File chart - * @throws IOException - */ - public static String getFileChart(String filePath) throws IOException { - BufferedInputStream bin = new BufferedInputStream(new FileInputStream(filePath)); - int p = (bin.read() << 8) + bin.read(); - bin.close(); - String code = null; - - switch (p) { - case 0xefbb: - code = "UTF-8"; - break; - case 0xfffe: - code = "Unicode"; - break; - case 0xfeff: - code = "UTF-16BE"; - break; - default: - code = "GBK"; - } - - return code; - - } - - /** - * Guess file encoding - * - * @param filePath The file path - * @return Guessed encoding - * @throws IOException - */ - public static String guessFileEncoding(String filePath) throws IOException { - FileCharsetDetector fcd = new FileCharsetDetector(); - String encoding = fcd.guestFileEncoding(filePath); - return encoding; - } - - /** - * Detect file encoding - * @param filePath The file path - * @return Encoding - */ - public static String encodingDetect(String filePath) { - return encodingDetect(new File(filePath)); - } - - /** - * Detect file encoding - * @param file The file - * @return Encoding - */ - public static String encodingDetect(File file) { - EncodingDetect detect = new EncodingDetect(); - int encodingNumber = detect.detectEncoding(file); - // may return GBK > GB-2312 > GB18030 - String name = EncodingDetect.javaname[encodingNumber]; - return name; - } - - /** - * Encoding detect to a shape file - * @param shpfilepath The shape file path - * @return Encoding - */ - public static String encodingDetectShp(String shpfilepath){ - String cpgfilepath = shpfilepath.replaceFirst(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".cpg"); - File cpgFile = new File(cpgfilepath); - if (cpgFile.exists()){ - BufferedReader sr = null; - try { - sr = new BufferedReader(new FileReader(cpgFile)); - String ec = sr.readLine().trim(); - sr.close(); - return ec; - } catch (FileNotFoundException ex) { - Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); - } finally { - try { - if (sr != null) - sr.close(); - } catch (IOException ex) { - Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); - File dbfFile = new File(dbffilepath); - if (!dbfFile.exists()) { - dbffilepath = dbffilepath.replace(".dbf", ".DBF"); - dbfFile = new File(dbffilepath); - } - if (!dbfFile.exists()) { - System.out.println(".dbf file not exists!"); - return null; - } else { - return encodingDetect(dbfFile); - } - } - -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common.io; + +import org.meteoinfo.common.io.FileCharsetDetector; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author wyq + */ +public class IOUtil { + + /** + * Get file chart + * + * @param filePath File path + * @return File chart + * @throws IOException + */ + public static String getFileChart(String filePath) throws IOException { + BufferedInputStream bin = new BufferedInputStream(new FileInputStream(filePath)); + int p = (bin.read() << 8) + bin.read(); + bin.close(); + String code = null; + + switch (p) { + case 0xefbb: + code = "UTF-8"; + break; + case 0xfffe: + code = "Unicode"; + break; + case 0xfeff: + code = "UTF-16BE"; + break; + default: + code = "GBK"; + } + + return code; + + } + + /** + * Guess file encoding + * + * @param filePath The file path + * @return Guessed encoding + * @throws IOException + */ + public static String guessFileEncoding(String filePath) throws IOException { + FileCharsetDetector fcd = new FileCharsetDetector(); + String encoding = fcd.guestFileEncoding(filePath); + return encoding; + } + + /** + * Detect file encoding + * @param filePath The file path + * @return Encoding + */ + public static String encodingDetect(String filePath) { + return encodingDetect(new File(filePath)); + } + + /** + * Detect file encoding + * @param file The file + * @return Encoding + */ + public static String encodingDetect(File file) { + org.meteoinfo.io.EncodingDetect detect = new org.meteoinfo.io.EncodingDetect(); + int encodingNumber = detect.detectEncoding(file); + // may return GBK > GB-2312 > GB18030 + String name = org.meteoinfo.io.EncodingDetect.javaname[encodingNumber]; + return name; + } + + /** + * Encoding detect to a shape file + * @param shpfilepath The shape file path + * @return Encoding + */ + public static String encodingDetectShp(String shpfilepath){ + String cpgfilepath = shpfilepath.replaceFirst(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".cpg"); + File cpgFile = new File(cpgfilepath); + if (cpgFile.exists()){ + BufferedReader sr = null; + try { + sr = new BufferedReader(new FileReader(cpgFile)); + String ec = sr.readLine().trim(); + sr.close(); + return ec; + } catch (FileNotFoundException ex) { + Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + if (sr != null) + sr.close(); + } catch (IOException ex) { + Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + String dbffilepath = shpfilepath.replace(shpfilepath.substring(shpfilepath.lastIndexOf(".")), ".dbf"); + File dbfFile = new File(dbffilepath); + if (!dbfFile.exists()) { + dbffilepath = dbffilepath.replace(".dbf", ".DBF"); + dbfFile = new File(dbffilepath); + } + if (!dbfFile.exists()) { + System.out.println(".dbf file not exists!"); + return null; + } else { + return encodingDetect(dbfFile); + } + } + +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/io/UnclosableOutputStream.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/UnclosableOutputStream.java similarity index 92% rename from MeteoInfoLib/src/main/java/org/meteoinfo/io/UnclosableOutputStream.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/io/UnclosableOutputStream.java index 2b99023e..1323343e 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/io/UnclosableOutputStream.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/io/UnclosableOutputStream.java @@ -1,32 +1,32 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.io; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author yaqia - */ -public class UnclosableOutputStream extends PrintStream { - - public UnclosableOutputStream(OutputStream out) { - super(out); - } - - @Override - public void close() { - try { - out.flush(); - } catch (IOException ex) { - Logger.getLogger(UnclosableOutputStream.class.getName()).log(Level.SEVERE, null, ex); - } - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author yaqia + */ +public class UnclosableOutputStream extends PrintStream { + + public UnclosableOutputStream(OutputStream out) { + super(out); + } + + @Override + public void close() { + try { + out.flush(); + } catch (IOException ex) { + Logger.getLogger(UnclosableOutputStream.class.getName()).log(Level.SEVERE, null, ex); + } + } +} diff --git a/meteoinfo-common/src/main/java/org/meteoinfo/common/util/BigDecimalUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/BigDecimalUtil.java new file mode 100644 index 00000000..e186ef49 --- /dev/null +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/BigDecimalUtil.java @@ -0,0 +1,142 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common.util; + +import java.math.BigDecimal; +import java.math.MathContext; + +/** + * + * @author wyq + */ +public class BigDecimalUtil { + /** + * Float to double + * @param v Float value + * @return Double value + */ + public static double toDouble(float v){ + return Double.parseDouble(Float.toString(v)); + } + + /** + * Double to float + * @param v Double value + * @return Float value + */ + public static float toFloat(double v) { + BigDecimal b = new BigDecimal(v); + return b.floatValue(); + } + + /** + * Add + * @param d1 Value1 + * @param d2 Value2 + * @return Add result + */ + public static double add(double d1,double d2){ + BigDecimal b1=new BigDecimal(Double.toString(d1)); + BigDecimal b2=new BigDecimal(Double.toString(d2)); + return b1.add(b2).doubleValue(); + } + + /** + * Add + * @param d1 Value1 + * @param d2 Value2 + * @return Add result + */ + public static double add(float d1,float d2){ + BigDecimal b1=new BigDecimal(Float.toString(d1)); + BigDecimal b2=new BigDecimal(Float.toString(d2)); + return b1.add(b2).doubleValue(); + } + + /** + * Substract + * @param d1 Value1 + * @param d2 Value2 + * @return Substract result + */ + public static double sub(double d1,double d2){ + BigDecimal b1=new BigDecimal(Double.toString(d1)); + BigDecimal b2=new BigDecimal(Double.toString(d2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * Multiply + * @param d1 Value1 + * @param d2 Value2 + * @return Multiply result + */ + public static double mul(double d1,double d2){ + BigDecimal b1=new BigDecimal(Double.toString(d1)); + BigDecimal b2=new BigDecimal(Double.toString(d2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * Multiply + * @param d1 Value1 + * @param d2 Value2 + * @return Multiply result + */ + public static double mul(float d1,float d2){ + BigDecimal b1=new BigDecimal(Float.toString(d1)); + BigDecimal b2=new BigDecimal(Float.toString(d2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * Divide + * @param d1 Value1 + * @param d2 Value2 + * @return Divide result + */ + public static double div(double d1,double d2){ + return div(d1,d2,20); + } + + /** + * Divide + * @param d1 Value1 + * @param d2 Value2 + * @param scale Scale + * @return Divide result + */ + public static double div(double d1,double d2,int scale){ + if(scale<0){ + throw new IllegalArgumentException("The scale must be a positive integer or zero"); + } + BigDecimal b1=new BigDecimal(Double.toString(d1)); + BigDecimal b2=new BigDecimal(Double.toString(d2)); + return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); + } + + /** + * Power + * @param d1 Value1 + * @param d2 Value2 + * @return Power value + */ + public static double pow(double d1,int d2){ + BigDecimal b1=new BigDecimal(Double.toString(d1)); + return b1.pow(d2, new MathContext(10)).doubleValue(); + } + + /** + * Mod + * @param d1 Value 1 + * @param d2 Value 2 + * @return Mod value + */ + public static double mod(double d1, double d2) { + BigDecimal b1=new BigDecimal(Double.toString(d1)); + BigDecimal b2=new BigDecimal(Double.toString(d2)); + return b1.divideAndRemainder(b2)[1].doubleValue(); + } +} diff --git a/meteoinfo-common/src/main/java/org/meteoinfo/common/util/FontUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/FontUtil.java new file mode 100644 index 00000000..cbe40969 --- /dev/null +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/FontUtil.java @@ -0,0 +1,128 @@ + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common.util; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +//import org.meteoinfo.drawing.Draw; +//import org.meteoinfo.legend.MapFrame; + + /** + * + * @author yaqiang + */ + public class FontUtil { + + /** + * Get all available fonts (system fonts, weather font and custom fonts) + * + * @return Font list + */ + public static List getAllFonts() { + List fontList = new ArrayList<>(); + + //Weather font + Font weatherFont = getWeatherFont(); + if (weatherFont != null) { + fontList.add(weatherFont); + } + + //System fonts + GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Font[] fonts = gEnv.getAllFonts(); + for (Font font : fonts) { + fontList.add(font); + } + + //Custom fonts + String fn = GlobalUtil.getAppPath(FontUtil.class); + fn = fn.substring(0, fn.lastIndexOf("/")); + String path = fn + File.separator + "font"; + File pathDir = new File(path); + if (pathDir.isDirectory()) { + + } + + return fontList; + } + + /** + * Register a font + * @param font The font + */ + public static void registerFont(Font font){ + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + } + + /** + * Register a font + * @param fileName Font file name + */ + public static void registerFont(String fileName){ + Font font = getFont(fileName); + if (font != null){ + registerFont(font); + } + } + + /** + * Register weather font + */ + public static void registerWeatherFont(){ + Font weatherFont = getWeatherFont(); + if (weatherFont != null) { + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(weatherFont); + } + } + + /** + * Get font from font file - .ttf + * @param fileName Font file name + * @return The font + */ + public static Font getFont(String fileName){ + Font font = null; + try { + font = Font.createFont(Font.TRUETYPE_FONT, new File(fileName)); + } catch (FontFormatException | IOException ex) { + Logger.getLogger(FontUtil.class.getName()).log(Level.SEVERE, null, ex); + } + return font; + } + + /** + * Get weather symbol font + * + * @return Weather symbol font + */ + public static Font getWeatherFont() { + Font font = null; + InputStream is = FontUtil.class.getResourceAsStream("/fonts/WeatherSymbol.ttf"); + try { + font = Font.createFont(Font.TRUETYPE_FONT, is); + } catch (FontFormatException | IOException ex) { + Logger.getLogger(FontUtil.class.getName()).log(Level.SEVERE, null, ex); + } + + return font; + } + } diff --git a/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java new file mode 100644 index 00000000..c2167c49 --- /dev/null +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java @@ -0,0 +1,682 @@ + /* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.common.util; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageFilter; +import java.awt.image.ImageProducer; +import java.awt.image.RGBImageFilter; +import java.awt.image.WritableRaster; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + + /** + * Template + * + * @author Yaqiang Wang + */ + public class GlobalUtil { + // + // + // + // + // + // + // + + /** + * Get software version + * @return Software version + */ + public static String getVersion(){ + String version = GlobalUtil.class.getPackage().getImplementationVersion(); + return version; + } + + /** + * Get file extension + * + * @param filePath The file path + * @return File extension + */ + public static String getFileExtension(String filePath) { + String extension = ""; + String fn = new File(filePath).getName(); + if (fn.contains(".")) { + String ext = filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase().trim(); + try { + extension = ext; + } catch (IllegalArgumentException e) { + } + } + + return extension; + } + + /** + * Get the list of specific file types in a directory + * + * @param directory The directory + * @param ext the file extension + * @return File name list + */ + public static List getFiles(String directory, String ext) { + List fileNames = new ArrayList<>(); + try { + File f = new File(directory); + boolean flag = f.isDirectory(); + if (flag) { + File fs[] = f.listFiles(); + for (int i = 0; i < fs.length; i++) { + if (!fs[i].isDirectory()) { + String filename = fs[i].getAbsolutePath(); + if (filename.endsWith(ext.trim())) { + fileNames.add(filename); + } + } else { + fileNames.addAll(getFiles(fs[i].getAbsolutePath(), ext)); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + return fileNames; + } + + /** + * Get sub directories + * + * @param directory The directory + * @return Sub directories + */ + public static List getSubDirectories(String directory) { + List subDirs = new ArrayList<>(); + File f = new File(directory); + File fs[] = f.listFiles(); + for (File f1 : fs) { + if (f1.isDirectory()) { + subDirs.add(f1.getPath()); + } + } + + return subDirs; + } + + /** + * Get class names in a jar file + * + * @param jarFileName The jar file name + * @return The class names in the jar file + * @throws FileNotFoundException + * @throws IOException + */ + public static List getClassNames(String jarFileName) throws FileNotFoundException, IOException { + List classNames = new ArrayList<>(); + ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFileName)); + for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) { + if (entry.getName().endsWith(".class") && !entry.isDirectory()) { + // This ZipEntry represents a class. Now, what class does it represent? + StringBuilder className = new StringBuilder(); + for (String part : entry.getName().split("/")) { + if (className.length() != 0) { + className.append("."); + } + className.append(part); + if (part.endsWith(".class")) { + className.setLength(className.length() - ".class".length()); + } + } + classNames.add(className.toString()); + } + } + + return classNames; + } + + /** + * Get the class name which implements IPlugin interface + * + * @param jarFileName The jar file name + * @return The class name which implements IPlugin interface + */ + public static String getPluginClassName(String jarFileName) { + String pluginClassName = null; + try { + List classNames = getClassNames(jarFileName); + URL url = new URL("file:" + jarFileName); + URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}); + for (String name : classNames) { + Class clazz = urlClassLoader.loadClass(name); + if (isInterface(clazz, "org.meteoinfo.plugin.IPlugin")) { + pluginClassName = name; + break; + } + } + } catch (FileNotFoundException ex) { + Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); + } catch (ClassNotFoundException ex) { + Logger.getLogger(GlobalUtil.class.getName()).log(Level.SEVERE, null, ex); + } + + return pluginClassName; + } + + /** + * Given a package name, attempts to reflect to find all classes within the + * package on the local file system. + * + * @param packageName + * @return Class list + */ + public static List getClassesInPackage(String packageName) { + List classes = new ArrayList<>(); + String packageNameSlashed = "/" + packageName.replace(".", "/"); + // Get a File object for the package + URL directoryURL = Thread.currentThread().getContextClassLoader().getResource(packageNameSlashed); + if (directoryURL == null) { + System.out.println("Could not retrieve URL resource: " + packageNameSlashed); + return classes; + } + + String directoryString = directoryURL.getFile(); + if (directoryString == null) { + System.out.println("Could not find directory for URL resource: " + packageNameSlashed); + return classes; + } + + File directory = new File(directoryString); + if (directory.exists()) { + // Get the list of the files contained in the package + String[] files = directory.list(); + for (String fileName : files) { + // We are only interested in .class files + if (fileName.endsWith(".class")) { + // Remove the .class extension + fileName = fileName.substring(0, fileName.length() - 6); + try { + classes.add(Class.forName(packageName + "." + fileName)); + } catch (ClassNotFoundException e) { + System.out.println(packageName + "." + fileName + " does not appear to be a valid class."); + } + } + } + } else { + System.out.println(packageName + " does not appear to exist as a valid package on the file system."); + } + return classes; + } + + /** + * Given a package name, attempts to reflect to find all file names within the + * package on the local file system. + * + * @param packageName + * @return File names + */ + public static List getFilesInPackage(String packageName) { + List fns = new ArrayList<>(); + //String packageNameSlashed = "/" + packageName.replace(".", "/"); + String packageNameSlashed = packageName.replace(".", "/"); + // Get a File object for the package + URL directoryURL = Thread.currentThread().getContextClassLoader().getResource(packageNameSlashed); + if (directoryURL == null) { + System.out.println("Could not retrieve URL resource: " + packageNameSlashed); + return fns; + } + + String directoryString = directoryURL.getFile(); + if (directoryString == null) { + System.out.println("Could not find directory for URL resource: " + packageNameSlashed); + return fns; + } + + File directory = new File(directoryString); + if (directory.exists()) { + // Get the list of the files contained in the package + String[] files = directory.list(); + for (String fileName : files) { + fns.add(fileName); + } + } else { + System.out.println(packageName + " does not appear to exist as a valid package on the file system."); + } + return fns; + } + + /** + * Determine if a class implements a interface + * + * @param c The class + * @param szInterface The interface name + * @return Boolean + */ + public static boolean isInterface(Class c, String szInterface) { + Class[] face = c.getInterfaces(); + for (int i = 0, j = face.length; i < j; i++) { + if (face[i].getName().equals(szInterface)) { + return true; + } else { + Class[] face1 = face[i].getInterfaces(); + for (int x = 0; x < face1.length; x++) { + if (face1[x].getName().equals(szInterface)) { + return true; + } else if (isInterface(face1[x], szInterface)) { + return true; + } + } + } + } + if (null != c.getSuperclass()) { + return isInterface(c.getSuperclass(), szInterface); + } + return false; + } + + /** + * Get root path + * + * @param aFile The file + * @return Root path + */ + public static String getPathRoot(File aFile) { + File path = aFile.getParentFile(); + String pathRoot = path.toString(); + while (path != null) { + path = path.getParentFile(); + if (path != null) { + pathRoot = path.toString(); + } + } + + return pathRoot; + } + + /** + * Get relative path of the file using project file path + * + * @param fileName File path + * @param projFile Project file path + * @return Relative path + * @throws IOException + */ + public static String getRelativePath(String fileName, String projFile) throws IOException { + String RelativePath = ""; + File aFile = new File(fileName); + File pFile = new File(projFile); + fileName = aFile.getCanonicalPath(); + + String layerPathRoot = getPathRoot(aFile); + String projPathRoot = getPathRoot(pFile); + if (!layerPathRoot.equalsIgnoreCase(projPathRoot)) { + RelativePath = fileName; + } else { + List aList = new ArrayList<>(); + aList.add(fileName); + do { + aList.add(""); + File tempFile = new File(aList.get(aList.size() - 2)); + if (tempFile.exists() && tempFile.getParent() != null) { + aList.set(aList.size() - 1, tempFile.getParent()); + } else { + break; + } + } while (!"".equals(aList.get(aList.size() - 1))); + + List bList = new ArrayList<>(); + bList.add(pFile.getCanonicalPath()); + do { + bList.add(""); + File tempFile = new File(bList.get(bList.size() - 2)); + if (tempFile.getParent() != null) { + bList.set(bList.size() - 1, tempFile.getParent()); + } else { + break; + } + } while (!"".equals(bList.get(bList.size() - 1))); + + boolean ifExist = false; + int offSet; + for (int i = 0; i < aList.size(); i++) { + for (int j = 0; j < bList.size(); j++) { + if (aList.get(i).equals(bList.get(j))) { + for (int k = 1; k < j; k++) { + RelativePath = RelativePath + ".." + File.separator; + } + if (aList.get(i).endsWith(File.separator)) { + offSet = 0; + } else { + offSet = 1; + } + RelativePath = RelativePath + fileName.substring(aList.get(i).length() + offSet); + ifExist = true; + break; + } + } + if (ifExist) { + break; + } + } + } + + if ("".equals(RelativePath)) { + RelativePath = fileName; + } + return RelativePath; + } + + /** + * Convert Image to BufferedImage + * + * @param image The Image + * @return The BufferedImage + */ + public static BufferedImage imageToBufferedImage(Image image) { + + BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = bufferedImage.createGraphics(); + g2.drawImage(image, 0, 0, null); + g2.dispose(); + + return bufferedImage; + + } + + /** + * Make a color of a image transparent + * + * @param im The image + * @param color The color + * @return Result image + */ + public static Image makeColorTransparent(BufferedImage im, final Color color) { + ImageFilter filter = new RGBImageFilter() { + // the color we are looking for... Alpha bits are set to opaque + public int markerRGB = color.getRGB() | 0xFF000000; + + @Override + public final int filterRGB(int x, int y, int rgb) { + if ((rgb | 0xFF000000) == markerRGB) { + // Mark the alpha bits as zero - transparent + return 0x00FFFFFF & rgb; + } else { + // nothing to do + return rgb; + } + } + }; + + ImageProducer ip = new FilteredImageSource(im.getSource(), filter); + return Toolkit.getDefaultToolkit().createImage(ip); + } + + /** + * Get application path by a class + * + * @param cls Class + * @return Application path + */ + public static String getAppPath(Class cls) { + if (cls == null) { + throw new IllegalArgumentException("The parameter can not be null!"); + } + + ClassLoader loader = cls.getClassLoader(); + //Get class name + String clsName = cls.getName() + ".class"; + //Get package + Package pack = cls.getPackage(); + String path = ""; + if (pack != null) { + String packName = pack.getName(); + //Judge if is Java base class to avoid this condition + if (packName.startsWith("java.") || packName.startsWith("javax.")) { + throw new IllegalArgumentException("Dont use Java system class!"); + } + //Remove package name from the class name + clsName = clsName.substring(packName.length() + 1); + //Convert package name to path if the package has simple name + if (!packName.contains(".")) { + path = packName + "/"; + } else { //Convert package name to path + int start = 0; + int end = packName.indexOf("."); + while (end != -1) { + path = path + packName.substring(start, end) + "/"; + start = end + 1; + end = packName.indexOf(".", start); + } + path = path + packName.substring(start) + "/"; + } + } + + //Get resource + URL url = loader.getResource(path + clsName); + //Get path + String realPath = url.getPath(); + //Remove "file:" + int pos = realPath.indexOf("file:"); + if (pos > -1) { + realPath = realPath.substring(pos + 5); + } + //Remove class info + pos = realPath.indexOf(path + clsName); + realPath = realPath.substring(0, pos - 1); + //Remove JAR package name + if (realPath.endsWith("!")) { + realPath = realPath.substring(0, realPath.lastIndexOf("/")); + } + + //Get Chinese path by decode + try { + realPath = java.net.URLDecoder.decode(realPath, "utf-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return realPath; + } + + /** + * String pad left + * + * @param str The string + * @param length Pad length + * @param ch Pad char + * @return Padded string + */ + public static String padLeft(String str, int length, char ch) { + for (int i = str.length(); i < length; i++) { + str = ch + str; + } + + return str; + } + + /** + * String pad right + * + * @param str The string + * @param length Pad length + * @param ch Pad char + * @return Padded string + */ + public static String padRight(String str, int length, char ch) { + for (int i = str.length(); i < length; i++) { + str = str + ch; + } + + return str; + } + + /** + * Deep clone object + * + * @param oldObj Old object + * @return Cloned object + * @throws Exception + */ + public static Object deepCopy(Object oldObj) throws Exception { + ObjectOutputStream oos = null; + ObjectInputStream ois = null; + try { + ByteArrayOutputStream bos + = new ByteArrayOutputStream(); // A + oos = new ObjectOutputStream(bos); // B + // serialize and pass the object + oos.writeObject(oldObj); // C + oos.flush(); // D + ByteArrayInputStream bin + = new ByteArrayInputStream(bos.toByteArray()); // E + ois = new ObjectInputStream(bin); // F + // return the new object + return ois.readObject(); // G + } catch (Exception e) { + System.out.println("Exception in ObjectCloner = " + e); + throw (e); + } finally { + oos.close(); + ois.close(); + } + } + + /** + * Deep clone a BufferedIamge + * + * @param bi Original image + * @return Cloned image + */ + public static BufferedImage deepCopy(BufferedImage bi) { + ColorModel cm = bi.getColorModel(); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + WritableRaster raster = bi.copyData(null); + return new BufferedImage(cm, raster, isAlphaPremultiplied, null); + } + + /** + * Get default font name + * + * @return Default font name + */ + public static String getDefaultFontName() { + String[] fontnames = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + List fns = Arrays.asList(fontnames); + String fn = "宋体"; + if (!fns.contains(fn)) { + fn = "Arial"; + } + + if (!fns.contains(fn)) { + fn = fontnames[0]; + } + + return fn; + } + + /** + * Get separator + * + * @param line The string line + * @return Delimiter string + */ + public static String getDelimiter(String line) { + String separator = null; + if (line.contains(",")) { + separator = ","; + } else if (line.contains(";")) { + separator = ";"; + } + + return separator; + } + + /** + * Get delimiter + * @param file File + * @return Delimiter + * @throws FileNotFoundException + * @throws IOException + */ + public static String getDelimiter(File file) throws FileNotFoundException, IOException{ + BufferedReader sr = new BufferedReader(new FileReader(file)); + String line = sr.readLine(); + sr.close(); + return getDelimiter(line); + } + + /** + * Split a string line by separator + * + * @param line The string line + * @param separator The separator + * @return Split string array + */ + public static String[] split(String line, String separator) { + if (separator == null || separator.equals(" ")) { + return line.split("\\s+"); + } else { + String[] strs = line.split(separator); + List r = new ArrayList<>(); + for (String s : strs){ + r.add(s.trim()); + } + strs = r.toArray(new String[1]); + return strs; + } + } + + /** + * Capitalize the first character of a string + * @param str The string + * @return Capitalized string + */ + public static String capitalize(String str){ + if(str == null || str.length() == 0) + return ""; + + if(str.length() == 1) + return str.toUpperCase(); + + char[] charArray = str.toCharArray(); + charArray[0] = Character.toUpperCase(charArray[0]); + return new String(charArray); + } + // + } diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GraphicsUtilities.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GraphicsUtilities.java similarity index 97% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GraphicsUtilities.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/util/GraphicsUtilities.java index 054319e6..b51e3c02 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/GraphicsUtilities.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GraphicsUtilities.java @@ -1,399 +1,399 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.global.util; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; -import java.awt.Image; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import javax.imageio.ImageIO; -import javax.swing.JComponent; - -/** - * - * @author wyq - */ -public class GraphicsUtilities { - - private static GraphicsConfiguration getGraphicsConfiguration() { - return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - } - - private static boolean isHeadless() { - return GraphicsEnvironment.isHeadless(); - } - - public static BufferedImage convertToBufferedImage(Image img) { - BufferedImage buff = createCompatibleTranslucentImage(img.getWidth(null), img.getHeight(null)); - - Graphics2D g2 = buff.createGraphics(); - try { - g2.drawImage(img, 0, 0, null); - } finally { - g2.dispose(); - } - - return buff; - } - - public static BufferedImage createColorModelCompatibleImage(BufferedImage image) { - ColorModel cm = image.getColorModel(); - return new BufferedImage(cm, cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), cm.isAlphaPremultiplied(), null); - } - - public static BufferedImage createCompatibleImage(BufferedImage image) { - return createCompatibleImage(image, image.getWidth(), image.getHeight()); - } - - public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) { - return isHeadless() ? new BufferedImage(width, height, image.getType()) : getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency()); - } - - public static BufferedImage createCompatibleImage(int width, int height) { - return isHeadless() ? new BufferedImage(width, height, 1) : getGraphicsConfiguration().createCompatibleImage(width, height); - } - - public static BufferedImage createCompatibleTranslucentImage(int width, int height) { - return isHeadless() ? new BufferedImage(width, height, 2) : getGraphicsConfiguration().createCompatibleImage(width, height, 3); - } - - public static BufferedImage loadCompatibleImage(InputStream in) - throws IOException { - BufferedImage image = ImageIO.read(in); - if (image == null) { - return null; - } - return toCompatibleImage(image); - } - - public static BufferedImage loadCompatibleImage(URL resource) - throws IOException { - BufferedImage image = ImageIO.read(resource); - return toCompatibleImage(image); - } - - public static BufferedImage toCompatibleImage(BufferedImage image) { - if (isHeadless()) { - return image; - } - - if (image.getColorModel().equals(getGraphicsConfiguration().getColorModel())) { - return image; - } - - BufferedImage compatibleImage = getGraphicsConfiguration().createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency()); - - Graphics g = compatibleImage.getGraphics(); - try { - g.drawImage(image, 0, 0, null); - } finally { - g.dispose(); - } - - return compatibleImage; - } - - public static BufferedImage createThumbnailFast(BufferedImage image, int newSize) { - int width = image.getWidth(); - int height = image.getHeight(); - - if (width > height) { - if (newSize >= width) { - throw new IllegalArgumentException("newSize must be lower than the image width"); - } - if (newSize <= 0) { - throw new IllegalArgumentException("newSize must be greater than 0"); - } - - float ratio = width / height; - width = newSize; - height = (int) (newSize / ratio); - } else { - if (newSize >= height) { - throw new IllegalArgumentException("newSize must be lower than the image height"); - } - if (newSize <= 0) { - throw new IllegalArgumentException("newSize must be greater than 0"); - } - - float ratio = height / width; - height = newSize; - width = (int) (newSize / ratio); - } - - BufferedImage temp = createCompatibleImage(image, width, height); - Graphics2D g2 = temp.createGraphics(); - try { - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); - } finally { - g2.dispose(); - } - - return temp; - } - - public static BufferedImage createThumbnailFast(BufferedImage image, int newWidth, int newHeight) { - if ((newWidth >= image.getWidth()) || (newHeight >= image.getHeight())) { - throw new IllegalArgumentException("newWidth and newHeight cannot be greater than the image dimensions"); - } - - if ((newWidth <= 0) || (newHeight <= 0)) { - throw new IllegalArgumentException("newWidth and newHeight must be greater than 0"); - } - - BufferedImage temp = createCompatibleImage(image, newWidth, newHeight); - Graphics2D g2 = temp.createGraphics(); - try { - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); - } finally { - g2.dispose(); - } - - return temp; - } - - public static BufferedImage createThumbnail(BufferedImage image, int newSize) { - int width = image.getWidth(); - int height = image.getHeight(); - - boolean isTranslucent = image.getTransparency() != 1; - boolean isWidthGreater = width > height; - - if (isWidthGreater) { - if (newSize >= width) { - throw new IllegalArgumentException("newSize must be lower than the image width"); - } - } else if (newSize >= height) { - throw new IllegalArgumentException("newSize must be lower than the image height"); - } - - if (newSize <= 0) { - throw new IllegalArgumentException("newSize must be greater than 0"); - } - - float ratioWH = width / height; - float ratioHW = height / width; - - BufferedImage thumb = image; - BufferedImage temp = null; - - Graphics2D g2 = null; - try { - int previousWidth = width; - int previousHeight = height; - do { - if (isWidthGreater) { - width /= 2; - if (width < newSize) { - width = newSize; - } - height = (int) (width / ratioWH); - } else { - height /= 2; - if (height < newSize) { - height = newSize; - } - width = (int) (height / ratioHW); - } - - if ((temp == null) || (isTranslucent)) { - if (g2 != null) { - g2.dispose(); - } - temp = createCompatibleImage(image, width, height); - g2 = temp.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - g2.drawImage(thumb, 0, 0, width, height, 0, 0, previousWidth, previousHeight, null); - - previousWidth = width; - previousHeight = height; - - thumb = temp; - } while (newSize != (isWidthGreater ? width : height)); - } finally { - if (g2 != null) { - g2.dispose(); - } - } - - if ((width != thumb.getWidth()) || (height != thumb.getHeight())) { - temp = createCompatibleImage(image, width, height); - g2 = temp.createGraphics(); - try { - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - g2.drawImage(thumb, 0, 0, width, height, 0, 0, width, height, null); - } finally { - g2.dispose(); - } - - thumb = temp; - } - - return thumb; - } - - public static BufferedImage createThumbnail(BufferedImage image, int newWidth, int newHeight) { - int width = image.getWidth(); - int height = image.getHeight(); - - boolean isTranslucent = image.getTransparency() != 1; - - if ((newWidth >= width) || (newHeight >= height)) { - throw new IllegalArgumentException("newWidth and newHeight cannot be greater than the image dimensions"); - } - - if ((newWidth <= 0) || (newHeight <= 0)) { - throw new IllegalArgumentException("newWidth and newHeight must be greater than 0"); - } - - BufferedImage thumb = image; - BufferedImage temp = null; - - Graphics2D g2 = null; - try { - int previousWidth = width; - int previousHeight = height; - do { - if (width > newWidth) { - width /= 2; - if (width < newWidth) { - width = newWidth; - } - } - - if (height > newHeight) { - height /= 2; - if (height < newHeight) { - height = newHeight; - } - } - - if ((temp == null) || (isTranslucent)) { - if (g2 != null) { - g2.dispose(); - } - temp = createCompatibleImage(image, width, height); - g2 = temp.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - g2.drawImage(thumb, 0, 0, width, height, 0, 0, previousWidth, previousHeight, null); - - previousWidth = width; - previousHeight = height; - - thumb = temp; - } while ((width != newWidth) || (height != newHeight)); - } finally { - if (g2 != null) { - g2.dispose(); - } - } - - if ((width != thumb.getWidth()) || (height != thumb.getHeight())) { - temp = createCompatibleImage(image, width, height); - g2 = temp.createGraphics(); - try { - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - g2.drawImage(thumb, 0, 0, width, height, 0, 0, width, height, null); - } finally { - g2.dispose(); - } - - thumb = temp; - } - - return thumb; - } - - public static int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { - if ((w == 0) || (h == 0)) { - return new int[0]; - } - - if (pixels == null) { - pixels = new int[w * h]; - } else if (pixels.length < w * h) { - throw new IllegalArgumentException("pixels array must have a length >= w*h"); - } - - int imageType = img.getType(); - if ((imageType == 2) || (imageType == 1)) { - Raster raster = img.getRaster(); - return (int[]) raster.getDataElements(x, y, w, h, pixels); - } - - return img.getRGB(x, y, w, h, pixels, 0, w); - } - - public static void setPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { - if ((pixels == null) || (w == 0) || (h == 0)) { - return; - } - if (pixels.length < w * h) { - throw new IllegalArgumentException("pixels array must have a length >= w*h"); - } - - int imageType = img.getType(); - if ((imageType == 2) || (imageType == 1)) { - WritableRaster raster = img.getRaster(); - raster.setDataElements(x, y, w, h, pixels); - } else { - img.setRGB(x, y, w, h, pixels, 0, w); - } - } - - public static void clear(Image img) { - Graphics g = img.getGraphics(); - try { - if ((g instanceof Graphics2D)) { - ((Graphics2D) g).setComposite(AlphaComposite.Clear); - } else { - g.setColor(new Color(0, 0, 0, 0)); - } - - g.fillRect(0, 0, img.getWidth(null), img.getHeight(null)); - } finally { - g.dispose(); - } - } - - public static void tileStretchPaint(Graphics g, JComponent comp, BufferedImage img, Insets ins) { - int left = ins.left; - int right = ins.right; - int top = ins.top; - int bottom = ins.bottom; - - g.drawImage(img, 0, 0, left, top, 0, 0, left, top, null); - g.drawImage(img, left, 0, comp.getWidth() - right, top, left, 0, img.getWidth() - right, top, null); - g.drawImage(img, comp.getWidth() - right, 0, comp.getWidth(), top, img.getWidth() - right, 0, img.getWidth(), top, null); - g.drawImage(img, 0, top, left, comp.getHeight() - bottom, 0, top, left, img.getHeight() - bottom, null); - g.drawImage(img, left, top, comp.getWidth() - right, comp.getHeight() - bottom, left, top, img.getWidth() - right, img.getHeight() - bottom, null); - g.drawImage(img, comp.getWidth() - right, top, comp.getWidth(), comp.getHeight() - bottom, img.getWidth() - right, top, img.getWidth(), img.getHeight() - bottom, null); - g.drawImage(img, 0, comp.getHeight() - bottom, left, comp.getHeight(), 0, img.getHeight() - bottom, left, img.getHeight(), null); - g.drawImage(img, left, comp.getHeight() - bottom, comp.getWidth() - right, comp.getHeight(), left, img.getHeight() - bottom, img.getWidth() - right, img.getHeight(), null); - g.drawImage(img, comp.getWidth() - right, comp.getHeight() - bottom, comp.getWidth(), comp.getHeight(), img.getWidth() - right, img.getHeight() - bottom, img.getWidth(), img.getHeight(), null); - } -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.common.util; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.swing.JComponent; + +/** + * + * @author wyq + */ +public class GraphicsUtilities { + + private static GraphicsConfiguration getGraphicsConfiguration() { + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); + } + + private static boolean isHeadless() { + return GraphicsEnvironment.isHeadless(); + } + + public static BufferedImage convertToBufferedImage(Image img) { + BufferedImage buff = createCompatibleTranslucentImage(img.getWidth(null), img.getHeight(null)); + + Graphics2D g2 = buff.createGraphics(); + try { + g2.drawImage(img, 0, 0, null); + } finally { + g2.dispose(); + } + + return buff; + } + + public static BufferedImage createColorModelCompatibleImage(BufferedImage image) { + ColorModel cm = image.getColorModel(); + return new BufferedImage(cm, cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), cm.isAlphaPremultiplied(), null); + } + + public static BufferedImage createCompatibleImage(BufferedImage image) { + return createCompatibleImage(image, image.getWidth(), image.getHeight()); + } + + public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) { + return isHeadless() ? new BufferedImage(width, height, image.getType()) : getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency()); + } + + public static BufferedImage createCompatibleImage(int width, int height) { + return isHeadless() ? new BufferedImage(width, height, 1) : getGraphicsConfiguration().createCompatibleImage(width, height); + } + + public static BufferedImage createCompatibleTranslucentImage(int width, int height) { + return isHeadless() ? new BufferedImage(width, height, 2) : getGraphicsConfiguration().createCompatibleImage(width, height, 3); + } + + public static BufferedImage loadCompatibleImage(InputStream in) + throws IOException { + BufferedImage image = ImageIO.read(in); + if (image == null) { + return null; + } + return toCompatibleImage(image); + } + + public static BufferedImage loadCompatibleImage(URL resource) + throws IOException { + BufferedImage image = ImageIO.read(resource); + return toCompatibleImage(image); + } + + public static BufferedImage toCompatibleImage(BufferedImage image) { + if (isHeadless()) { + return image; + } + + if (image.getColorModel().equals(getGraphicsConfiguration().getColorModel())) { + return image; + } + + BufferedImage compatibleImage = getGraphicsConfiguration().createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency()); + + Graphics g = compatibleImage.getGraphics(); + try { + g.drawImage(image, 0, 0, null); + } finally { + g.dispose(); + } + + return compatibleImage; + } + + public static BufferedImage createThumbnailFast(BufferedImage image, int newSize) { + int width = image.getWidth(); + int height = image.getHeight(); + + if (width > height) { + if (newSize >= width) { + throw new IllegalArgumentException("newSize must be lower than the image width"); + } + if (newSize <= 0) { + throw new IllegalArgumentException("newSize must be greater than 0"); + } + + float ratio = width / height; + width = newSize; + height = (int) (newSize / ratio); + } else { + if (newSize >= height) { + throw new IllegalArgumentException("newSize must be lower than the image height"); + } + if (newSize <= 0) { + throw new IllegalArgumentException("newSize must be greater than 0"); + } + + float ratio = height / width; + height = newSize; + width = (int) (newSize / ratio); + } + + BufferedImage temp = createCompatibleImage(image, width, height); + Graphics2D g2 = temp.createGraphics(); + try { + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); + } finally { + g2.dispose(); + } + + return temp; + } + + public static BufferedImage createThumbnailFast(BufferedImage image, int newWidth, int newHeight) { + if ((newWidth >= image.getWidth()) || (newHeight >= image.getHeight())) { + throw new IllegalArgumentException("newWidth and newHeight cannot be greater than the image dimensions"); + } + + if ((newWidth <= 0) || (newHeight <= 0)) { + throw new IllegalArgumentException("newWidth and newHeight must be greater than 0"); + } + + BufferedImage temp = createCompatibleImage(image, newWidth, newHeight); + Graphics2D g2 = temp.createGraphics(); + try { + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + g2.drawImage(image, 0, 0, temp.getWidth(), temp.getHeight(), null); + } finally { + g2.dispose(); + } + + return temp; + } + + public static BufferedImage createThumbnail(BufferedImage image, int newSize) { + int width = image.getWidth(); + int height = image.getHeight(); + + boolean isTranslucent = image.getTransparency() != 1; + boolean isWidthGreater = width > height; + + if (isWidthGreater) { + if (newSize >= width) { + throw new IllegalArgumentException("newSize must be lower than the image width"); + } + } else if (newSize >= height) { + throw new IllegalArgumentException("newSize must be lower than the image height"); + } + + if (newSize <= 0) { + throw new IllegalArgumentException("newSize must be greater than 0"); + } + + float ratioWH = width / height; + float ratioHW = height / width; + + BufferedImage thumb = image; + BufferedImage temp = null; + + Graphics2D g2 = null; + try { + int previousWidth = width; + int previousHeight = height; + do { + if (isWidthGreater) { + width /= 2; + if (width < newSize) { + width = newSize; + } + height = (int) (width / ratioWH); + } else { + height /= 2; + if (height < newSize) { + height = newSize; + } + width = (int) (height / ratioHW); + } + + if ((temp == null) || (isTranslucent)) { + if (g2 != null) { + g2.dispose(); + } + temp = createCompatibleImage(image, width, height); + g2 = temp.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + } + + g2.drawImage(thumb, 0, 0, width, height, 0, 0, previousWidth, previousHeight, null); + + previousWidth = width; + previousHeight = height; + + thumb = temp; + } while (newSize != (isWidthGreater ? width : height)); + } finally { + if (g2 != null) { + g2.dispose(); + } + } + + if ((width != thumb.getWidth()) || (height != thumb.getHeight())) { + temp = createCompatibleImage(image, width, height); + g2 = temp.createGraphics(); + try { + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + g2.drawImage(thumb, 0, 0, width, height, 0, 0, width, height, null); + } finally { + g2.dispose(); + } + + thumb = temp; + } + + return thumb; + } + + public static BufferedImage createThumbnail(BufferedImage image, int newWidth, int newHeight) { + int width = image.getWidth(); + int height = image.getHeight(); + + boolean isTranslucent = image.getTransparency() != 1; + + if ((newWidth >= width) || (newHeight >= height)) { + throw new IllegalArgumentException("newWidth and newHeight cannot be greater than the image dimensions"); + } + + if ((newWidth <= 0) || (newHeight <= 0)) { + throw new IllegalArgumentException("newWidth and newHeight must be greater than 0"); + } + + BufferedImage thumb = image; + BufferedImage temp = null; + + Graphics2D g2 = null; + try { + int previousWidth = width; + int previousHeight = height; + do { + if (width > newWidth) { + width /= 2; + if (width < newWidth) { + width = newWidth; + } + } + + if (height > newHeight) { + height /= 2; + if (height < newHeight) { + height = newHeight; + } + } + + if ((temp == null) || (isTranslucent)) { + if (g2 != null) { + g2.dispose(); + } + temp = createCompatibleImage(image, width, height); + g2 = temp.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + } + + g2.drawImage(thumb, 0, 0, width, height, 0, 0, previousWidth, previousHeight, null); + + previousWidth = width; + previousHeight = height; + + thumb = temp; + } while ((width != newWidth) || (height != newHeight)); + } finally { + if (g2 != null) { + g2.dispose(); + } + } + + if ((width != thumb.getWidth()) || (height != thumb.getHeight())) { + temp = createCompatibleImage(image, width, height); + g2 = temp.createGraphics(); + try { + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + g2.drawImage(thumb, 0, 0, width, height, 0, 0, width, height, null); + } finally { + g2.dispose(); + } + + thumb = temp; + } + + return thumb; + } + + public static int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { + if ((w == 0) || (h == 0)) { + return new int[0]; + } + + if (pixels == null) { + pixels = new int[w * h]; + } else if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + + int imageType = img.getType(); + if ((imageType == 2) || (imageType == 1)) { + Raster raster = img.getRaster(); + return (int[]) raster.getDataElements(x, y, w, h, pixels); + } + + return img.getRGB(x, y, w, h, pixels, 0, w); + } + + public static void setPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { + if ((pixels == null) || (w == 0) || (h == 0)) { + return; + } + if (pixels.length < w * h) { + throw new IllegalArgumentException("pixels array must have a length >= w*h"); + } + + int imageType = img.getType(); + if ((imageType == 2) || (imageType == 1)) { + WritableRaster raster = img.getRaster(); + raster.setDataElements(x, y, w, h, pixels); + } else { + img.setRGB(x, y, w, h, pixels, 0, w); + } + } + + public static void clear(Image img) { + Graphics g = img.getGraphics(); + try { + if ((g instanceof Graphics2D)) { + ((Graphics2D) g).setComposite(AlphaComposite.Clear); + } else { + g.setColor(new Color(0, 0, 0, 0)); + } + + g.fillRect(0, 0, img.getWidth(null), img.getHeight(null)); + } finally { + g.dispose(); + } + } + + public static void tileStretchPaint(Graphics g, JComponent comp, BufferedImage img, Insets ins) { + int left = ins.left; + int right = ins.right; + int top = ins.top; + int bottom = ins.bottom; + + g.drawImage(img, 0, 0, left, top, 0, 0, left, top, null); + g.drawImage(img, left, 0, comp.getWidth() - right, top, left, 0, img.getWidth() - right, top, null); + g.drawImage(img, comp.getWidth() - right, 0, comp.getWidth(), top, img.getWidth() - right, 0, img.getWidth(), top, null); + g.drawImage(img, 0, top, left, comp.getHeight() - bottom, 0, top, left, img.getHeight() - bottom, null); + g.drawImage(img, left, top, comp.getWidth() - right, comp.getHeight() - bottom, left, top, img.getWidth() - right, img.getHeight() - bottom, null); + g.drawImage(img, comp.getWidth() - right, top, comp.getWidth(), comp.getHeight() - bottom, img.getWidth() - right, top, img.getWidth(), img.getHeight() - bottom, null); + g.drawImage(img, 0, comp.getHeight() - bottom, left, comp.getHeight(), 0, img.getHeight() - bottom, left, img.getHeight(), null); + g.drawImage(img, left, comp.getHeight() - bottom, comp.getWidth() - right, comp.getHeight(), left, img.getHeight() - bottom, img.getWidth() - right, img.getHeight(), null); + g.drawImage(img, comp.getWidth() - right, comp.getHeight() - bottom, comp.getWidth(), comp.getHeight(), img.getWidth() - right, img.getHeight() - bottom, img.getWidth(), img.getHeight(), null); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/JDateUtil.java similarity index 99% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/util/JDateUtil.java index 417a091f..dd53d802 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/JDateUtil.java @@ -1,6 +1,6 @@ -package org.meteoinfo.global.util; +package org.meteoinfo.common.util; -import org.meteoinfo.ndarray.util.BigDecimalUtil; +import org.meteoinfo.common.util.BigDecimalUtil; import java.time.*; import java.time.chrono.ChronoPeriod; diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/MercatorUtils.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/MercatorUtils.java similarity index 95% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/util/MercatorUtils.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/util/MercatorUtils.java index acaa1e32..4359bb6c 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/MercatorUtils.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/MercatorUtils.java @@ -1,55 +1,55 @@ -/* - * MercatorUtils.java - * - * Created on October 7, 2006, 6:02 PM - * - * To change this template, choose Tools | Template Manager - * and open the template in the editor. - */ - -package org.meteoinfo.global.util; - -/** - * A utility class of methods that help when dealing - * with standard Mercator projections. - * @author joshua.marinacci@sun.com - */ -public final class MercatorUtils { - - /** Creates a new instance of MercatorUtils */ - private MercatorUtils() { - } - - - public static int longToX(double longitudeDegrees, double radius) { - double longitude = Math.toRadians(longitudeDegrees); - return (int)(radius * longitude); - } - - public static int latToY(double latitudeDegrees, double radius) { - double latitude = Math.toRadians(latitudeDegrees); - double y = radius/2.0 * - Math.log((1.0+Math.sin(latitude))/ - (1.0-Math.sin(latitude)) ); - return (int)y; - } - - public static double xToLong(int x, double radius) { - double longRadians = x/radius; - double longDegrees = Math.toDegrees(longRadians); - /* The user could have panned around the world a lot of times. - Lat long goes from -180 to 180. So every time a user gets - to 181 we want to subtract 360 degrees. Every time a user - gets to -181 we want to add 360 degrees. */ - int rotations = (int)Math.floor((longDegrees+180)/360); - double longitude = longDegrees - (rotations * 360); - return longitude; - } - - public static double yToLat(int y, double radius) { - double latitude = (Math.PI/2) - - (2 * Math.atan( - Math.exp(-1.0 * y / radius))); - return Math.toDegrees(latitude); - } -} +/* + * MercatorUtils.java + * + * Created on October 7, 2006, 6:02 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package org.meteoinfo.common.util; + +/** + * A utility class of methods that help when dealing + * with standard Mercator projections. + * @author joshua.marinacci@sun.com + */ +public final class MercatorUtils { + + /** Creates a new instance of MercatorUtils */ + private MercatorUtils() { + } + + + public static int longToX(double longitudeDegrees, double radius) { + double longitude = Math.toRadians(longitudeDegrees); + return (int)(radius * longitude); + } + + public static int latToY(double latitudeDegrees, double radius) { + double latitude = Math.toRadians(latitudeDegrees); + double y = radius/2.0 * + Math.log((1.0+Math.sin(latitude))/ + (1.0-Math.sin(latitude)) ); + return (int)y; + } + + public static double xToLong(int x, double radius) { + double longRadians = x/radius; + double longDegrees = Math.toDegrees(longRadians); + /* The user could have panned around the world a lot of times. + Lat long goes from -180 to 180. So every time a user gets + to 181 we want to subtract 360 degrees. Every time a user + gets to -181 we want to add 360 degrees. */ + int rotations = (int)Math.floor((longDegrees+180)/360); + double longitude = longDegrees - (rotations * 360); + return longitude; + } + + public static double yToLat(int y, double radius) { + double latitude = (Math.PI/2) - + (2 * Math.atan( + Math.exp(-1.0 * y / radius))); + return Math.toDegrees(latitude); + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtils.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/TypeUtils.java similarity index 99% rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtils.java rename to meteoinfo-common/src/main/java/org/meteoinfo/common/util/TypeUtils.java index 889f48e8..2ead55d0 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/TypeUtils.java +++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/TypeUtils.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package org.meteoinfo.global.util; +package org.meteoinfo.common.util; import com.google.common.collect.ImmutableList; diff --git a/meteoinfo-math/meteoinfo-math.iml b/meteoinfo-math/meteoinfo-math.iml new file mode 100644 index 00000000..2d8248c5 --- /dev/null +++ b/meteoinfo-math/meteoinfo-math.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/meteoinfo-math/pom.xml b/meteoinfo-math/pom.xml new file mode 100644 index 00000000..aa03c55d --- /dev/null +++ b/meteoinfo-math/pom.xml @@ -0,0 +1,32 @@ + + + + MeteoInfo + org.meteothink + 3.0.0 + + 4.0.0 + + meteoinfo-math + + + 1.8 + 1.8 + + + + + ${project.groupId} + meteoinfo-ndarray + ${project.version} + + + ${project.groupId} + meteoinfo-common + ${project.version} + + + + \ No newline at end of file diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayMath.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayMath.java similarity index 99% rename from MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayMath.java rename to meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayMath.java index 364c2124..5d4cb56f 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayMath.java +++ b/meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayMath.java @@ -5,19 +5,13 @@ */ package org.meteoinfo.math; +import org.meteoinfo.ndarray.*; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.meteoinfo.ndarray.Complex; -import org.meteoinfo.ndarray.Array; -import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.ndarray.Index; -import org.meteoinfo.ndarray.IndexIterator; -import org.meteoinfo.ndarray.InvalidRangeException; -import org.meteoinfo.ndarray.MAMath; -import org.meteoinfo.ndarray.Range; /** * diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayUtil.java similarity index 95% rename from MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java rename to meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayUtil.java index ae975748..0350a515 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java +++ b/meteoinfo-math/src/main/java/org/meteoinfo/math/ArrayUtil.java @@ -5,46 +5,30 @@ */ package org.meteoinfo.math; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; +//import org.meteoinfo.geoprocess.GeoComputation; +import org.meteoinfo.ndarray.*; +import org.meteoinfo.ndarray.util.DataConvert; +import org.meteoinfo.common.MIMath; +import org.meteoinfo.common.PointD; +import org.meteoinfo.common.util.GlobalUtil; +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.common.io.EndianDataOutputStream; +import org.meteoinfo.math.spatial.KDTree; +import org.meteoinfo.math.spatial.KDTree.SearchResult; +import org.meteoinfo.ndarray.util.BigDecimalUtil; +//import org.meteoinfo.shape.PolygonShape; + +import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.Scanner; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; -import org.meteoinfo.geoprocess.GeoComputation; -import org.meteoinfo.global.DataConvert; -import org.meteoinfo.global.MIMath; -import org.meteoinfo.global.PointD; -import org.meteoinfo.global.util.GlobalUtil; -import org.meteoinfo.global.util.JDateUtil; -import org.meteoinfo.io.EndianDataOutputStream; -import org.meteoinfo.math.spatial.KDTree; -import org.meteoinfo.math.spatial.KDTree.SearchResult; -import org.meteoinfo.ndarray.*; -import org.meteoinfo.ndarray.util.BigDecimalUtil; -import org.meteoinfo.shape.PolygonShape; - /** * * @author yaqiang @@ -67,7 +51,7 @@ public class ArrayUtil { * @throws IOException */ public static Array readASCIIFile(String fileName, String delimiter, int headerLines, String dataType, - List shape, boolean readFirstCol) throws UnsupportedEncodingException, FileNotFoundException, IOException { + List shape, boolean readFirstCol) throws UnsupportedEncodingException, FileNotFoundException, IOException { BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); if (headerLines > 0) { for (int i = 0; i < headerLines; i++) { @@ -344,7 +328,7 @@ public class ArrayUtil { * @param colNum Column number of each line * @param format String format * @param delimiter Delimiter - * @throws java.io.IOException + * @throws IOException */ public static void saveASCIIFile(String fn, Array a, int colNum, String format, String delimiter) throws IOException { @@ -2967,172 +2951,172 @@ public class ArrayUtil { return rdata; } - /** - * Interpolate with surface method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @param unDefData undefine value - * @return grid data - */ - public static Array interpolation_Surface_1(Array x_s, Array y_s, Array a, Array X, Array Y, - double unDefData) { - x_s = x_s.copyIfView(); - y_s = y_s.copyIfView(); - a = a.copyIfView(); - X = X.copyIfView(); - Y = Y.copyIfView(); +// /** +// * Interpolate with surface method +// * +// * @param x_s scatter X array +// * @param y_s scatter Y array +// * @param a scatter value array +// * @param X x coordinate +// * @param Y y coordinate +// * @param unDefData undefine value +// * @return grid data +// */ +// public static Array interpolation_Surface_1(Array x_s, Array y_s, Array a, Array X, Array Y, +// double unDefData) { +// x_s = x_s.copyIfView(); +// y_s = y_s.copyIfView(); +// a = a.copyIfView(); +// X = X.copyIfView(); +// Y = Y.copyIfView(); +// +// int rowNum, colNum, xn, yn; +// int[] shape = x_s.getShape(); +// colNum = shape[1]; +// rowNum = shape[0]; +// xn = (int) X.getSize(); +// yn = (int) Y.getSize(); +// Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); +// double x, y; +// +// PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1]; +// PolygonShape ps; +// for (int i = 0; i < rowNum - 1; i++) { +// for (int j = 0; j < colNum - 1; j++) { +// ps = new PolygonShape(); +// List points = new ArrayList<>(); +// points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j))); +// points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j))); +// points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1))); +// points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1))); +// points.add((PointD) points.get(0).clone()); +// ps.setPoints(points); +// polygons[i][j] = ps; +// } +// } +// +// for (int i = 0; i < yn; i++) { +// for (int j = 0; j < xn; j++) { +// r.setDouble(i * xn + j, unDefData); +// } +// } +// +// double v; +// for (int i = 0; i < rowNum - 1; i++) { +// for (int j = 0; j < colNum - 1; j++) { +// ps = polygons[i][j]; +// v = a.getDouble(i * colNum + j); +// for (int ii = 0; ii < yn; ii++) { +// y = Y.getDouble(ii); +// for (int jj = 0; jj < xn; jj++) { +// x = X.getDouble(jj); +// if (Double.isNaN(r.getDouble(ii * xn + jj)) || r.getDouble(ii * xn + jj) == unDefData) { +// if (GeoComputation.pointInPolygon(ps, x, y)) { +// r.setDouble(ii * xn + jj, v); +// } +// } +// } +// } +// } +// } +// +// return r; +// } - int rowNum, colNum, xn, yn; - int[] shape = x_s.getShape(); - colNum = shape[1]; - rowNum = shape[0]; - xn = (int) X.getSize(); - yn = (int) Y.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - double x, y; - - PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1]; - PolygonShape ps; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j))); - points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1))); - points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1))); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - polygons[i][j] = ps; - } - } - - for (int i = 0; i < yn; i++) { - for (int j = 0; j < xn; j++) { - r.setDouble(i * xn + j, unDefData); - } - } - - double v; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - ps = polygons[i][j]; - v = a.getDouble(i * colNum + j); - for (int ii = 0; ii < yn; ii++) { - y = Y.getDouble(ii); - for (int jj = 0; jj < xn; jj++) { - x = X.getDouble(jj); - if (Double.isNaN(r.getDouble(ii * xn + jj)) || r.getDouble(ii * xn + jj) == unDefData) { - if (GeoComputation.pointInPolygon(ps, x, y)) { - r.setDouble(ii * xn + jj, v); - } - } - } - } - } - } - - return r; - } - - /** - * Interpolate with surface method - * - * @param x_s scatter X array - * @param y_s scatter Y array - * @param a scatter value array - * @param X x coordinate - * @param Y y coordinate - * @return grid data - */ - public static Array interpolation_Surface(Array x_s, Array y_s, Array a, Array X, Array Y) { - x_s = x_s.copyIfView(); - y_s = y_s.copyIfView(); - a = a.copyIfView(); - X = X.copyIfView(); - Y = Y.copyIfView(); - - int rowNum, colNum, xn, yn; - int[] shape = x_s.getShape(); - colNum = shape[1]; - rowNum = shape[0]; - xn = (int) X.getSize(); - yn = (int) Y.getSize(); - Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); - for (int i = 0; i < r.getSize(); i++) { - r.setDouble(i, Double.NaN); - } - - double x, y; - double v, xll, xtl, xtr, xlr, yll, ytl, ytr, ylr; - double dX = X.getDouble(1) - X.getDouble(0); - double dY = Y.getDouble(1) - Y.getDouble(0); - int minxi, maxxi, minyi, maxyi; - for (int i = 0; i < rowNum - 1; i++) { - for (int j = 0; j < colNum - 1; j++) { - v = a.getDouble(i * colNum + j); - if (Double.isNaN(v)) { - continue; - } - xll = x_s.getDouble(i * colNum + j); - xtl = x_s.getDouble((i + 1) * colNum + j); - xtr = x_s.getDouble((i + 1) * colNum + j + 1); - xlr = x_s.getDouble(i * colNum + j + 1); - yll = y_s.getDouble(i * colNum + j); - ytl = y_s.getDouble((i + 1) * colNum + j); - ytr = y_s.getDouble((i + 1) * colNum + j + 1); - ylr = y_s.getDouble(i * colNum + j + 1); - if (Double.isNaN(xll) || Double.isNaN(xtl) || Double.isNaN(xtr) || Double.isNaN(xlr) - || Double.isNaN(yll) || Double.isNaN(ytl) || Double.isNaN(ytr) || Double.isNaN(ylr)) { - continue; - } - PolygonShape ps = new PolygonShape(); - List points = new ArrayList<>(); - points.add(new PointD(xll, yll)); - points.add(new PointD(xtl, ytl)); - points.add(new PointD(xtr, ytr)); - points.add(new PointD(xlr, ylr)); - points.add((PointD) points.get(0).clone()); - ps.setPoints(points); - minxi = (int) ((ps.getExtent().minX - X.getDouble(0)) / dX); - maxxi = (int) ((ps.getExtent().maxX - X.getDouble(0)) / dX); - minyi = (int) ((ps.getExtent().minY - Y.getDouble(0)) / dY); - maxyi = (int) ((ps.getExtent().maxY - Y.getDouble(0)) / dY); - maxxi += 1; - maxyi += 1; - if (maxxi < 0 || minxi >= xn) { - continue; - } - if (maxyi < 0 || minyi >= yn) { - continue; - } - if (minxi < 0) { - minxi = 0; - } - if (maxxi >= xn) { - maxxi = xn - 1; - } - if (maxyi >= yn) { - maxyi = yn - 1; - } - for (int m = minyi; m <= maxyi; m++) { - y = Y.getDouble(m); - for (int n = minxi; n <= maxxi; n++) { - x = X.getDouble(n); - if (GeoComputation.pointInPolygon(ps, x, y)) { - r.setDouble(m * xn + n, v); - } - } - } - } - } - - return r; - } +// /** +// * Interpolate with surface method +// * +// * @param x_s scatter X array +// * @param y_s scatter Y array +// * @param a scatter value array +// * @param X x coordinate +// * @param Y y coordinate +// * @return grid data +// */ +// public static Array interpolation_Surface(Array x_s, Array y_s, Array a, Array X, Array Y) { +// x_s = x_s.copyIfView(); +// y_s = y_s.copyIfView(); +// a = a.copyIfView(); +// X = X.copyIfView(); +// Y = Y.copyIfView(); +// +// int rowNum, colNum, xn, yn; +// int[] shape = x_s.getShape(); +// colNum = shape[1]; +// rowNum = shape[0]; +// xn = (int) X.getSize(); +// yn = (int) Y.getSize(); +// Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn}); +// for (int i = 0; i < r.getSize(); i++) { +// r.setDouble(i, Double.NaN); +// } +// +// double x, y; +// double v, xll, xtl, xtr, xlr, yll, ytl, ytr, ylr; +// double dX = X.getDouble(1) - X.getDouble(0); +// double dY = Y.getDouble(1) - Y.getDouble(0); +// int minxi, maxxi, minyi, maxyi; +// for (int i = 0; i < rowNum - 1; i++) { +// for (int j = 0; j < colNum - 1; j++) { +// v = a.getDouble(i * colNum + j); +// if (Double.isNaN(v)) { +// continue; +// } +// xll = x_s.getDouble(i * colNum + j); +// xtl = x_s.getDouble((i + 1) * colNum + j); +// xtr = x_s.getDouble((i + 1) * colNum + j + 1); +// xlr = x_s.getDouble(i * colNum + j + 1); +// yll = y_s.getDouble(i * colNum + j); +// ytl = y_s.getDouble((i + 1) * colNum + j); +// ytr = y_s.getDouble((i + 1) * colNum + j + 1); +// ylr = y_s.getDouble(i * colNum + j + 1); +// if (Double.isNaN(xll) || Double.isNaN(xtl) || Double.isNaN(xtr) || Double.isNaN(xlr) +// || Double.isNaN(yll) || Double.isNaN(ytl) || Double.isNaN(ytr) || Double.isNaN(ylr)) { +// continue; +// } +// PolygonShape ps = new PolygonShape(); +// List points = new ArrayList<>(); +// points.add(new PointD(xll, yll)); +// points.add(new PointD(xtl, ytl)); +// points.add(new PointD(xtr, ytr)); +// points.add(new PointD(xlr, ylr)); +// points.add((PointD) points.get(0).clone()); +// ps.setPoints(points); +// minxi = (int) ((ps.getExtent().minX - X.getDouble(0)) / dX); +// maxxi = (int) ((ps.getExtent().maxX - X.getDouble(0)) / dX); +// minyi = (int) ((ps.getExtent().minY - Y.getDouble(0)) / dY); +// maxyi = (int) ((ps.getExtent().maxY - Y.getDouble(0)) / dY); +// maxxi += 1; +// maxyi += 1; +// if (maxxi < 0 || minxi >= xn) { +// continue; +// } +// if (maxyi < 0 || minyi >= yn) { +// continue; +// } +// if (minxi < 0) { +// minxi = 0; +// } +// if (maxxi >= xn) { +// maxxi = xn - 1; +// } +// if (maxyi >= yn) { +// maxyi = yn - 1; +// } +// for (int m = minyi; m <= maxyi; m++) { +// y = Y.getDouble(m); +// for (int n = minxi; n <= maxxi; n++) { +// x = X.getDouble(n); +// if (GeoComputation.pointInPolygon(ps, x, y)) { +// r.setDouble(m * xn + n, v); +// } +// } +// } +// } +// } +// +// return r; +// } /** * Extend the grid to half cell, so the grid points are the centers of the @@ -4739,7 +4723,7 @@ public class ArrayUtil { double b = data.getDouble(index.set(i1, j2)); double c = data.getDouble(index.set(i2, j1)); double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); + List dList = new ArrayList<>(); if (!Double.isNaN(a) && !MIMath.doubleEquals(a, missingValue)) { dList.add(a); } @@ -4828,7 +4812,7 @@ public class ArrayUtil { double b = data.getDouble(index.set(i1, j2)); double c = data.getDouble(index.set(i2, j1)); double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); + List dList = new ArrayList<>(); if (!Double.isNaN(a)) { dList.add(a); } @@ -5028,7 +5012,7 @@ public class ArrayUtil { index.setDim(n - 2, i2); index.setDim(n - 1, j2); double d = data.getDouble(index); - List dList = new ArrayList<>(); + List dList = new ArrayList<>(); if (!Double.isNaN(a)) { dList.add(a); } @@ -5120,7 +5104,7 @@ public class ArrayUtil { double b = data.getDouble(index.set(i1, j2)); double c = data.getDouble(index.set(i2, j1)); double d = data.getDouble(index.set(i2, j2)); - List dList = new ArrayList<>(); + List dList = new ArrayList<>(); if (!Double.isNaN(a)) { dList.add(a); } diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ListIndexComparator.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/ListIndexComparator.java similarity index 96% rename from MeteoInfoLib/src/main/java/org/meteoinfo/math/ListIndexComparator.java rename to meteoinfo-math/src/main/java/org/meteoinfo/math/ListIndexComparator.java index d36c97f6..dee933ec 100644 --- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ListIndexComparator.java +++ b/meteoinfo-math/src/main/java/org/meteoinfo/math/ListIndexComparator.java @@ -1,52 +1,52 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.math; - -import java.util.Comparator; -import java.util.List; - -/** - * - * @author Yaqiang Wang - */ -public class ListIndexComparator implements Comparator { - private final List list; - - public ListIndexComparator(List list) - { - this.list = list; - } - - public Integer[] createIndexArray() - { - Integer[] indexes = new Integer[list.size()]; - for (int i = 0; i < list.size(); i++) - { - indexes[i] = i; // Autoboxing - } - return indexes; - } - - @Override - public int compare(Integer index1, Integer index2) - { - // Autounbox from Integer to int to use as array indexes - if (this.list.get(0) instanceof String){ - return ((String)list.get(index1)).compareTo((String)list.get(index2)); - } else if (this.list.get(0) instanceof Integer) { - return ((Integer)list.get(index1)). - compareTo((Integer)list.get(index2)); - } else if (this.list.get(0) instanceof Float) { - return ((Float)list.get(index1)). - compareTo((Float)list.get(index2)); - } else if (this.list.get(0) instanceof Double) { - return ((Double)list.get(index1)). - compareTo((Double)list.get(index2)); - } else { - return -1; - } - } -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.meteoinfo.math; + +import java.util.Comparator; +import java.util.List; + +/** + * + * @author Yaqiang Wang + */ +public class ListIndexComparator implements Comparator { + private final List list; + + public ListIndexComparator(List list) + { + this.list = list; + } + + public Integer[] createIndexArray() + { + Integer[] indexes = new Integer[list.size()]; + for (int i = 0; i < list.size(); i++) + { + indexes[i] = i; // Autoboxing + } + return indexes; + } + + @Override + public int compare(Integer index1, Integer index2) + { + // Autounbox from Integer to int to use as array indexes + if (this.list.get(0) instanceof String){ + return ((String)list.get(index1)).compareTo((String)list.get(index2)); + } else if (this.list.get(0) instanceof Integer) { + return ((Integer)list.get(index1)). + compareTo((Integer)list.get(index2)); + } else if (this.list.get(0) instanceof Float) { + return ((Float)list.get(index1)). + compareTo((Float)list.get(index2)); + } else if (this.list.get(0) instanceof Double) { + return ((Double)list.get(index1)). + compareTo((Double)list.get(index2)); + } else { + return -1; + } + } +} diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/spatial/KDTree.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/spatial/KDTree.java similarity index 100% rename from MeteoInfoLib/src/main/java/org/meteoinfo/math/spatial/KDTree.java rename to meteoinfo-math/src/main/java/org/meteoinfo/math/spatial/KDTree.java diff --git a/meteoinfo-ndarray/meteoinfo-ndarray.iml b/meteoinfo-ndarray/meteoinfo-ndarray.iml index fdf32413..bc8904f0 100644 --- a/meteoinfo-ndarray/meteoinfo-ndarray.iml +++ b/meteoinfo-ndarray/meteoinfo-ndarray.iml @@ -11,6 +11,15 @@ + + + + + + + + + diff --git a/meteoinfo-ndarray/pom.xml b/meteoinfo-ndarray/pom.xml index 8e603762..8a65540f 100644 --- a/meteoinfo-ndarray/pom.xml +++ b/meteoinfo-ndarray/pom.xml @@ -19,6 +19,11 @@ + + ${project.groupId} + meteoinfo-common + ${project.version} + org.apache.commons commons-math3 diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java index 53db7cbc..e15e0cd8 100644 --- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java +++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java @@ -33,7 +33,7 @@ package org.meteoinfo.ndarray; -import org.meteoinfo.ndarray.util.Converter; +import org.meteoinfo.ndarray.util.DataConvert; import java.io.IOException; import java.nio.ByteBuffer; @@ -217,7 +217,7 @@ public class StructureDataDeep extends StructureDataA { break; case CHAR: char[] cdata = sdata.getJavaArrayChar(m); - bb.put(Converter.convertCharToByte(cdata)); + bb.put(DataConvert.convertCharToByte(cdata)); break; case LONG: long[] ldata = sdata.getJavaArrayLong(m); diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java deleted file mode 100644 index c325e518..00000000 --- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.meteoinfo.ndarray.util; - -import org.meteoinfo.ndarray.DataType; -import org.meteoinfo.ndarray.constants.CDM; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; - -/** - * - * @author wyq - */ -public class Converter { - // convert byte array to char array, assuming UTF-8 encoding - - static public char[] convertByteToCharUTF(byte[] byteArray) { - Charset c = CDM.utf8Charset; - CharBuffer output = c.decode(ByteBuffer.wrap(byteArray)); - return output.array(); - } - - // convert char array to byte array, assuming UTF-8 encoding - static public byte[] convertCharToByteUTF(char[] from) { - Charset c = CDM.utf8Charset; - ByteBuffer output = c.encode(CharBuffer.wrap(from)); - return output.array(); - } - - // convert byte array to char array - static public char[] convertByteToChar(byte[] byteArray) { - int size = byteArray.length; - char[] cbuff = new char[size]; - for (int i = 0; i < size; i++) { - cbuff[i] = (char) DataType.unsignedByteToShort(byteArray[i]); // NOTE: not Unicode ! - } - return cbuff; - } - - // convert char array to byte array - static public byte[] convertCharToByte(char[] from) { - int size = from.length; - byte[] to = new byte[size]; - for (int i = 0; i < size; i++) { - to[i] = (byte) from[i]; // LOOK wrong, convert back to unsigned byte ??? - } - return to; - } -} diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/DataConvert.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/DataConvert.java new file mode 100644 index 00000000..17e9d792 --- /dev/null +++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/DataConvert.java @@ -0,0 +1,811 @@ +/* Copyright 2012 Yaqiang Wang, + * yaqiang.wang@gmail.com + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + */ +package org.meteoinfo.ndarray.util; + +import org.meteoinfo.common.util.JDateUtil; +import org.meteoinfo.common.util.TypeUtils; +import org.meteoinfo.ndarray.DataType; +import org.meteoinfo.ndarray.constants.CDM; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * + * @author Yaqiang Wang + */ +public class DataConvert { + // convert byte array to char array, assuming UTF-8 encoding + static public char[] convertByteToCharUTF(byte[] byteArray) { + Charset c = CDM.utf8Charset; + CharBuffer output = c.decode(ByteBuffer.wrap(byteArray)); + return output.array(); + } + + // convert char array to byte array, assuming UTF-8 encoding + static public byte[] convertCharToByteUTF(char[] from) { + Charset c = CDM.utf8Charset; + ByteBuffer output = c.encode(CharBuffer.wrap(from)); + return output.array(); + } + + // convert byte array to char array + static public char[] convertByteToChar(byte[] byteArray) { + int size = byteArray.length; + char[] cbuff = new char[size]; + for (int i = 0; i < size; i++) { + cbuff[i] = (char) DataType.unsignedByteToShort(byteArray[i]); // NOTE: not Unicode ! + } + return cbuff; + } + + // convert char array to byte array + static public byte[] convertCharToByte(char[] from) { + int size = from.length; + byte[] to = new byte[size]; + for (int i = 0; i < size; i++) { + to[i] = (byte) from[i]; // LOOK wrong, convert back to unsigned byte ??? + } + return to; + } + + /** + * Byte array convert to float + * + * @param b Byte array + * @param byteOrder Byte order + * @return Float value + */ + public static float bytes2Float(byte[] b, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.wrap(b); + buf.order(byteOrder); + return buf.getFloat(); + } + + /** + * Byte array convert to double + * + * @param b Byte array + * @param byteOrder Byte order + * @return Double value + */ + public static double bytes2Double(byte[] b, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.wrap(b); + buf.order(byteOrder); + return buf.getDouble(); + } + + /** + * Byte array convert to integer + * + * @param bytes Byte array + * @param byteOrder Byte order + * @return Integer value + */ + public static int bytes2Int(byte[] bytes, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(byteOrder); + if (bytes.length == 4) { + return buf.getInt(); + } else { + return buf.getShort(); + } + } + + /** + * Byte array convert to short integer + * + * @param bytes Byte array + * @param byteOrder Byte order + * @return Short integer value + */ + public static short bytes2Short(byte[] bytes, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(byteOrder); + return buf.getShort(); + } + + /** + * Byte array convert to long integer + * + * @param bytes Byte array + * @param byteOrder Byte order + * @return Long integer value + */ + public static Long bytes2Long(byte[] bytes, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(byteOrder); + return buf.getLong(); + } + + /** + * Byte array convert to integer + * + * @param bytes byte array + * @return Integer value + */ + public static int bytes2Int(byte[] bytes) { + int result = 0; + for (int i = 0; i < 4; i++) { + result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i]; + } + return result; + } + + /** + * Byte array (3 bytes) convert to integer + * + * @param bytes Byte array + * @return Integer value + */ + public static int bytes2Int3(byte[] bytes) { + int val = 0; + for (int bb = 0; bb < 3; bb++) { + val <<= 8; + val |= (int) bytes[bb] & 0xFF; + } + return val; + } + + /** + * Convert byte to int - byte in Java is signed + * + * @param b Input byte + * @return Output integer + */ + public static int byte2Int(byte b) { + return b >= 0 ? (int) b : (int) (b + 256); + } + + /** + * Convert LittleEndian to BigEndian + * + * @param bytes Input LittleEndian byte array + * @return Output BigEndian byte array + */ + public static byte[] littleToBig(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException(); + } + byte[] temp = new byte[bytes.length]; + for (int i = bytes.length - 1; i >= 0; i--) { + temp[i] = bytes[bytes.length - 1 - i]; + } + return temp; + } + + /** + * Convert BigEndian to LittleEndian + * + * @param bytes Input BigEndian byte array + * @return Output LittleEndian byte array + */ + public static byte[] bigToLittle(byte[] bytes) { + return littleToBig(bytes); + } + + /** + * Convert int to byte array. + * + * @param i Int value + * @return Byte array + */ + public static byte[] toBytes(int i) { + byte[] bytes = new byte[4]; + bytes[0] = (byte) (i >> 24 & 0xff); + bytes[1] = (byte) (i >> 16 & 0xff); + bytes[2] = (byte) (i >> 8 & 0xff); + bytes[3] = (byte) (i & 0xff); + return bytes; + } + + /** + * Convert int to 3 byte array. + * + * @param i Int value + * @return Byte array + */ + public static byte[] toUint3Int(int i) { + byte[] ints = new byte[3]; + ints[0] = (byte) (i >> 16 & 0xff); + ints[1] = (byte) (i >> 8 & 0xff); + ints[2] = (byte) (i & 0xff); + return ints; + } + + /** + * Convert int to 2 byte array. + * + * @param i Int value + * @return Byte array + */ + public static byte[] toUint2Int(int i) { + byte[] ints = new byte[2]; + ints[0] = (byte) (i >> 8 & 0xff); + ints[1] = (byte) (i & 0xff); + return ints; + } + + /** + * Convert int to N byte array. + * + * @param i Int value + * @param n bit number + * @return Byte array + */ + public static byte[] toUintNInt(int i, int n) { + byte[] ints = new byte[2]; + ints[0] = (byte) (i >> 8 & 0xff); + ints[1] = (byte) (i & 0xff); + return ints; + } + + /** + * Convert int to byte array - LittleEndian + * + * @param i Int value + * @return Byte array + */ + public static byte[] toLittleBytes(int i) { + byte[] bytes = new byte[4]; + bytes[3] = (byte) (i >> 24 & 0xff); + bytes[2] = (byte) (i >> 16 & 0xff); + bytes[1] = (byte) (i >> 8 & 0xff); + bytes[0] = (byte) (i & 0xff); + return bytes; + } + + /** + * Convert float to byte array + * + * @param f Float value + * @return Byte array + */ + public static byte[] toBytes(float f) { + return toBytes(Float.floatToIntBits(f)); + } + + /** + * Convert float to byte array + * + * @param f Float value + * @param byteOrder ByteOrder + * @return Byte array + */ + public static byte[] float2Bytes(float f, ByteOrder byteOrder) { + ByteBuffer buf = ByteBuffer.allocate(4); + buf.order(byteOrder); + buf.putFloat(f); + return buf.array(); + } + + /** + * Convert float to byte array + * + * @param f Float array + * @return Byte array + */ + public static byte[] toLittleBytes(float f) { + return toLittleBytes(Float.floatToIntBits(f)); + } + + /** + * Resize array + * + * @param oldArray Old array + * @param newSize New size + * @return Resized array + */ + public static Object resizeArray(Object oldArray, int newSize) { + int oldSize = java.lang.reflect.Array.getLength(oldArray); + Class elementType = oldArray.getClass().getComponentType(); + Object newArray = java.lang.reflect.Array.newInstance( + elementType, newSize); + int preserveLength = Math.min(oldSize, newSize); + if (preserveLength > 0) { + System.arraycopy(oldArray, 0, newArray, 0, preserveLength); + } + return newArray; + } + + /** + * Resize double 2d array + * + * @param oldArray Old array + * @param newSize New size + * @return Resized array + */ + public static double[][] resizeArray2D(double[][] oldArray, int newSize) { + int ynum = oldArray.length; + int xnum = oldArray[0].length; + double[][] newArray = new double[newSize][xnum]; + for (int j = 0; j < ynum; j++) { + for (int i = 0; i < xnum; i++) { + newArray[j][i] = oldArray[j][i]; + } + } + return newArray; + } + + /** + * Double to string + * + * @param v The double value + * @return Result string + */ + public static String doubleToString(double v) { + BigDecimal a = new BigDecimal(Double.toString(v)); + a = a.setScale(12, BigDecimal.ROUND_HALF_UP); + return a.stripTrailingZeros().toPlainString(); + } + + /** + * Remove tail zero + * + * @param s The string + * @return Result string + */ + public static String removeTailingZeros(String s) { + if (s.equals("0.0")) { + s = "0"; + } + if (s.length() <= 1) { + return s; + } + if (s.substring(s.length() - 2).equals(".0")) { + return new BigDecimal(s).stripTrailingZeros().toPlainString(); + } else { + return s; + } + } + + /** + * Remove last zero chars + * @param str String + * @return Result string + */ + public static String removeTail0(String str){ + // Return string if the last char is not 0 + if(!str.substring(str.length() -1).equals("0")){ + return str; + }else{ + // Or remove last char and recursion + return removeTail0(str.substring(0, str.length() -1 )); + } + } + + // Returns a byte array of at least length 1. +// The most significant bit in the result is guaranteed not to be a 1 +// (since BitSet does not support sign extension). +// The byte-ordering of the result is big-endian which means the most significant bit is in element 0. +// The bit at index 0 of the bit set is assumed to be the least significant bit. + public static byte[] toByte_bak1(BitSet bits) { + byte[] bytes = new byte[bits.length() / 8 + 1]; + for (int i = 0; i < bits.length(); i++) { + if (bits.get(i)) { + bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8); + } + } + return bytes; + } + + public static byte[] toByteArray(BitSet bits) { + byte[] bytes = new byte[bits.length() / 8 + 1]; + for (int i = 0; i < bits.length(); i++) { + if (bits.get(i)) { + bytes[i / 8] |= 1 << (i % 8); + } + } + return bytes; + } + + public static byte[] toByteArray_bak(BitSet bitSet) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(bitSet.size()); + try { + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(bitSet); + } catch (IOException ex) { + ex.printStackTrace(); + } + return baos.toByteArray(); + } + + /** + * Convert input data to current data type + * + * @param value Data value + * @param dataType Data type + * @param dateFormat Date format + * @return Converted data + */ + public static Object convertTo(Object value, DataType dataType, String dateFormat) { + if (value == null) { + switch (dataType) { + case INT: + return Integer.MIN_VALUE; + case FLOAT: + return Float.NaN; + case DOUBLE: + return Double.NaN; + case BOOLEAN: + return false; + case STRING: + return ""; + default: + return value; + } + } else { + switch (dataType) { + case INT: + if (!(value instanceof Integer)) { + String vStr = value.toString(); + if (vStr.isEmpty()) { + return Integer.MIN_VALUE; + } + return Integer.valueOf(vStr); + } + break; + case DOUBLE: + if (!(value instanceof Double)) { + String vStr = value.toString(); + if (vStr.isEmpty() || vStr.equalsIgnoreCase("nan")) { + return Double.NaN; + } else { + return Double.valueOf(vStr); + } + } + break; + case FLOAT: + if (!(value instanceof Float)) { + String vStr = value.toString(); + if (vStr.isEmpty() || vStr.equalsIgnoreCase("nan")) { + return Float.NaN; + } else { + try { + float v = Float.valueOf(vStr); + return v; + } catch (NumberFormatException e) { + return Float.NaN; + } + } + } + break; + case BOOLEAN: + if (!(value instanceof Boolean)) { + String vStr = value.toString(); + if (vStr.isEmpty()) { + return false; + } + return Boolean.valueOf(vStr); + } + break; + case OBJECT: + if (!(value instanceof Date)) { + String vStr = value.toString(); + if (vStr.isEmpty()) { + return null; + } + DateTimeFormatter dformat = DateTimeFormatter.ofPattern(dateFormat); + return LocalDateTime.parse(vStr, dformat); + } + break; + } + } + + return value; + } + + /** + * Convert input string data to current data type + * + * @param vStr String value + * @param dataType Data type + * @param dateFormat Date format + * @return Converted data + */ + public static Object convertStringTo(String vStr, DataType dataType, String dateFormat) { + if (vStr == null) { + switch (dataType) { + case INT: + return Integer.MIN_VALUE; + case FLOAT: + return Float.NaN; + case DOUBLE: + return Double.NaN; + case BOOLEAN: + return false; + case STRING: + return ""; + default: + return vStr; + } + } else { + switch (dataType) { + case INT: + if (vStr.isEmpty()) { + return Integer.MIN_VALUE; + } else { + try { + int v = Integer.valueOf(vStr); + return v; + } catch (NumberFormatException e) { + return Integer.MIN_VALUE; + } + } + case DOUBLE: + if (vStr.isEmpty() || vStr.equalsIgnoreCase("nan")) { + return Double.NaN; + } else { + try { + double v = Double.valueOf(vStr); + return v; + } catch (NumberFormatException e) { + return Double.NaN; + } + } + case FLOAT: + if (vStr.isEmpty() || vStr.equalsIgnoreCase("nan")) { + return Float.NaN; + } else { + try { + float v = Float.valueOf(vStr); + return v; + } catch (NumberFormatException e) { + return Float.NaN; + } + } + case BOOLEAN: + if (vStr.isEmpty()) { + return false; + } + return Boolean.valueOf(vStr); + case DATE: + if (vStr.isEmpty()) { + return null; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat); + return JDateUtil.parseDateTime(vStr, formatter); + } + } + + return vStr; + } + + /** + * Get data type + * + * @param format Format string + * @return Data type + */ + public static DataType getDataType(String format) { + DataType dt = DataType.STRING; + switch (format) { + case "C": + case "s": + dt = DataType.STRING; + break; + case "i": + dt = DataType.INT; + break; + case "f": + dt = DataType.FLOAT; + break; + case "d": + dt = DataType.DOUBLE; + break; + case "B": + dt = DataType.BOOLEAN; + break; + default: + if (format.substring(0, 1).equals("{")) { //Date + int eidx = format.indexOf("}"); + String formatStr = format.substring(1, eidx); + dt = DataType.DATE; + } + break; + } + + return dt; + } + + /** + * Get date format string + * @param format Format string + * @return Date format string + */ + public static String getDateFormat(String format) { + int eidx = format.indexOf("}"); + String formatStr = format.substring(1, eidx); + return formatStr; + } + + /** + * Check a string is double or not + * + * @param s The string + * @return Boolean + */ + public static boolean isDouble(String s) { + try { + Double.parseDouble(s); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + /** + * Check a string is float or not + * + * @param s The string + * @return Boolean + */ + public static boolean isFloat(String s) { + try { + Float.parseFloat(s); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + /** + * Check a string is integer or not + * + * @param s The string + * @return Boolean + */ + public static boolean isInteger(String s) { + try { + Integer.parseInt(s); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + /** + * Check a string is boolean or not + * + * @param s The string + * @return Boolean + */ + public static boolean isBoolean(String s) { + return TypeUtils.TRUE_STRINGS_FOR_DETECTION.contains(s) || TypeUtils.FALSE_STRINGS_FOR_DETECTION.contains(s); + } + + /** + * Check a string is local date or not + * + * @param s The string + * @param dateTimeFormatter DateTimeFormatter + * @return + */ + public static boolean isLocalDate(String s, DateTimeFormatter dateTimeFormatter) { + try { + if (dateTimeFormatter == null) { + LocalDate.parse(s, TypeUtils.DATE_FORMATTER); + return true; + } else { + LocalDate.parse(s, dateTimeFormatter); + return true; + } + } catch (Exception e) { + // it's all part of the plan + return false; + } + } + + /** + * Check a string is local time or not + * + * @param s The string + * @param formatter DateTimeFormatter + * @return + */ + public static boolean isLocalTime(String s, DateTimeFormatter formatter) { + try { + if (formatter == null) { + LocalTime.parse(s, TypeUtils.TIME_DETECTION_FORMATTER); + return true; + } else { + LocalDate.parse(s, formatter); + return true; + } + } catch (Exception e) { + // it's all part of the plan + return false; + } + } + + /** + * Check a string is local date time or not + * + * @param s The string + * @param formatter DateTimeFormatter + * @return + */ + public static boolean isLocalDateTime(String s, DateTimeFormatter formatter) { + try { + if (formatter == null) { + LocalDateTime.parse(s, TypeUtils.DATE_TIME_FORMATTER); + return true; + } else { + LocalDate.parse(s, formatter); + return true; + } + } catch (Exception e) { + // it's all part of the plan + return false; + } + } + + /** + * Detect data type + * @param valuesList Values list + * @param dtFormatter DateIimeFormatter + * @return Data type + */ + public static DataType detectDataType(List valuesList, DateTimeFormatter dtFormatter) { + List dts = new LinkedList<>(Arrays.asList(DataType.DATE, DataType.BOOLEAN, DataType.INT, DataType.FLOAT, + DataType.DOUBLE, DataType.STRING)); + if (dtFormatter == null) + dts.remove(DataType.DATE); + for (String s : valuesList) { + if (dts.contains(DataType.DATE) ) { + if (dtFormatter != null && !isLocalDateTime(s, dtFormatter)) + dts.remove(DataType.DATE); + } + if (dts.contains(DataType.BOOLEAN) && !isBoolean(s)) { + dts.remove(DataType.BOOLEAN); + } + if (dts.contains(DataType.INT) && !isInteger(s)) { + dts.remove(DataType.INT); + } + if (dts.contains(DataType.FLOAT) && !isFloat(s)) { + dts.remove(DataType.FLOAT); + } + if (dts.contains(DataType.DOUBLE) && !isDouble(s)) { + dts.remove(DataType.DOUBLE); + } + } + + return dts.get(0); + } + + /** + * Detect data type + * @param valuesList Values list + * @param n Value number used for detect + * @param dtFormatter DateIimeFormatter + * @return Data type + */ + public static DataType detectDataType(List valuesList, int n, DateTimeFormatter dtFormatter) { + if (n > valuesList.size()) + n = valuesList.size(); + List vl = valuesList.subList(0, n); + return detectDataType(vl, dtFormatter); + } +} diff --git a/pom.xml b/pom.xml index 02465bfa..3e388fd5 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,8 @@ MeteoInfoLab meteoinfo-console meteoinfo-ndarray + meteoinfo-math + meteoinfo-common