/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 1999-2003, by :
* Corporate:
* Astrium SAS
* EADS CRC
* Individual:
* Claude Cazenave
* Nicolas Brodu
*
*
* $Id: AxisShape.java,v 1.19 2008/10/16 15:00:02 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/
package simtools.shapes;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.text.Format;
import java.util.ArrayList;
public class AxisShape extends AbstractShape implements java.io.Serializable,
Cloneable,
simtools.diagram.Resizable{
static final long serialVersionUID = 2776298686196507458L;
private static Font _defaultFont=new Font("TimesRoman",Font.PLAIN,10);
/**
* the type of the line in the grid
* false : simple lines for the grid
* true : dashed lines for the grid
*/
public static boolean preferredDashedGrid = false;
/**
* Indicate the presence of grids for the
* initialization
*/
public static boolean preferredShowGrid = false;
protected static Color gridColor = Color.gray;
protected static int _defaultTickLength=5;
protected static int _defaultTickSpace=1;
protected boolean _isVertical;
protected boolean _valuesFirst;
protected boolean _withGridlines;
protected boolean _withValues;
protected boolean _withAxis= true;
protected Font _font;
protected Format _format;
protected Color _color;
protected LabelShape _label;
protected boolean _withDashedGrid;
protected transient Stroke _gridStroke;
/** axis minimum value */
protected double _min;
/** axis maximum value */
protected double _max;
/** axis grid step value */
protected double _step;
/** The labelShape Array, that contains the tick.*/
protected LabelShape[] _gridValues;
/** The double values, that contains the value of the ticks.*/
protected double[] _gridDoubleValues;
protected int[] _gridPos;
protected int _gridZeroIndex;
protected double _gridOffset;
protected int _lineWidth;
protected int _lineHeight;
protected int _nbrLabelLines;
protected int _labelLineHeight;
/**A boolean to indicate that the axis is under logarithmic format*/
private boolean log = false;
/**
* @param ox the anchor x position
* @param oy the anchor y position
* @param length the axis length excluding the space
* to display label and gridlines values
*/
public AxisShape(boolean isVertical, boolean valuesFirst, int ox, int oy, int width, int height){
super(ox,oy);
_isVertical=isVertical;
_valuesFirst=valuesFirst;
_withValues=true;
_font=_defaultFont;
_format=null;
_color=Color.black;
_label=null;
_lineWidth=width;
_lineHeight=height;
_gridValues=null;
_gridPos=null;
_gridZeroIndex=-1;
_nbrLabelLines=1;
_labelLineHeight=0;
set(0.,0.,0.);
_withGridlines= preferredShowGrid;
_withDashedGrid= preferredDashedGrid;
createGridStroke();
}
public AbstractShape cloneShape(){
AxisShape o=null;
try{
o=(AxisShape)super.clone();
}
catch(CloneNotSupportedException cnse){
return null;
}
// deep copies
if(o._label!=null){
o._label=(LabelShape)o._label.cloneShape();
}
o._gridValues=null;
o.set(o._min,o._max,o._step);
return o;
}
public void setWithAxis(boolean withAxis){
_withAxis = withAxis;
}
public boolean isWithAxis() {
return _withAxis;
}
public void setWithGridlines(boolean t){
_withGridlines=t;
}
public boolean isWithGridlines() {
return _withGridlines;
}
public void setWithDashedGrid(boolean t){
_withDashedGrid=t;
createGridStroke();
}
public boolean isWithDashedGrid() {
return _withDashedGrid;
}
public void setWithValues(boolean t){
if(t!=_withValues){
_withValues=t;
computeBounds();
}
}
public boolean isWithValues() {
return _withValues;
}
public void setLabel(String s){
if ((s==null) || s.trim().equals("")) {
if(_label!=null){
_label=null;
computeBounds();
}
}
else{
if(_label==null){
_label=new LabelShape(s,
0,0,
_valuesFirst ?
LabelShape.CENTERUP:LabelShape.CENTERDOWN,
_isVertical);
}
else{
_label.setString(s);
}
computeBounds();
}
}
public void setFont(Font f){
if(f!=_font){
_font=f;
computeBounds();
}
}
public void setFormat(Format f){
if(f!=_format){
_format=f;
computeBounds();
}
}
public void setColor(Color c){
_color=c;
}
/**
* Resizes the shape
*/
public void resize(int dx, int dy){
_lineWidth+=dx;
_lineHeight+=dy;
if(_lineWidth<1){
_lineWidth=1;
}
if(_lineHeight<1){
_lineHeight=1;
}
computeBounds();
}
/**
* Resizes the shape
*/
public void setSize(int lineWidth, int lineHeight){
if(lineWidth<1){
lineWidth=1;
}
if(lineHeight<1){
lineHeight=1;
}
this._lineWidth = lineWidth;
this._lineHeight = lineHeight;
computeBounds();
}
/**
* Sets shape anchor
* @param p the origin
*/
public void setAnchor(int ox, int oy) {
int dx=ox-_ox;
int dy=oy-_oy;
translate(dx,dy);
}
/**
* Translates the shape
*/
public void translate(int dx, int dy){
super.translate(dx,dy);
for(int i=0;i<_gridValues.length;i++){
_gridValues[i].translate(dx,dy);
_gridPos[i]+= (_isVertical ? dy : dx);
}
if(_label!=null){
_label.translate(dx,dy);
}
}
/**
* Sets axis values. Default step is computed automatically
* @param min the axis minimum value
* @param max the axis maximum value
*/
public void set(double min, double max){
set(min, max, computeStep(min, max));
}
/**
* Sets axis values
* @param min the axis minimum value
* @param max the axis maximum value
* @param step the step for gridlines
* @param stepOffset the offset between min value and fisrt step
*/
public void set(double min, double max, double step){
//Must take care of logarithmic mode.
if(log){
//beware of negatve values.
if(min < CurveShape.LOG_MIN){
min = CurveShape.LOG_MIN;
}
//If in log mode, given min and max value must be switched in log.
_min = log10(min);
_max = log10(max);
//Step in log mode must be an int between 1 and 9.
//1 will draw a tick every unity 1, 2 3 .. 9 10 20 30 .. 90 100 and so on.
//2 will draw a tick with a 2 step, including power of 10: 1, 3, 5, 7, 10, 30, 50 ...
//9 and over will only draw the powers of 10: 10 100 1000
if(step > 9){
step = 9;
}else if(step < 1){
step =1;
}
//Round given step value to have round ticks.
_step = Math.rint(step);
} else {
//In case of non log axe, simply set min and max numeric values.
_min = Math.min(min, max);
_max = Math.max(min, max);
_step = Math.abs(step);
}
// compute the gridLines
if(!log){
createAndComputeLinearLabels(step);
}else{
createAndComputeLogLabels();
}
computeBounds();
}
/**
* Method <b>createAndComputeLogLabels</b>
* <br><b>Summary:</b><br>
* This method creates and compute the label position and value, for a logarithmic axis.
*/
private void createAndComputeLogLabels() {
//The result that will contains tha values
ArrayList result = new ArrayList();
_gridZeroIndex =-1;
//get lower bound value:
//if small log values and lower bound value too small
// then set to a small value (don't allow <= 0):
//get log10 version of lower bound and round to integer:
int iBegCount = (int) Math.rint(_min);
//get log10 version of upper bound and round to integer:
int iEndCount = (int) Math.rint(_max);
if (iBegCount == iEndCount && iBegCount > 0
&& Math.pow(10, iBegCount) > _min) {
//only 1 power of 10 value, it's > 0 and its resulting
// tick value will be larger than lower bound of data
--iBegCount; //decrement to generate more ticks
}
double tickVal;
boolean zeroTickFlag = false;
for (int i = iBegCount; i <= iEndCount; i++) {
//for each tick with a label to be displayed
int jEndCount = 9;
if (i == iEndCount) {
jEndCount = 1;
}
//use the _step to iterate ticks.
for (int j = 0; j < jEndCount; j=j+(int) _step) {
//for each tick to be displayed
if (zeroTickFlag) { //if did zero tick last iter then
--j;
} //decrement to do 1.0 tick now
tickVal = (i >= 0) ? Math.pow(10, i) + (Math.pow(10, i) * j) : -(Math.pow(10, -i) - (Math.pow(10,
-i - 1) * j));
if (tickVal > 0 && tickVal <= Math.pow(10,Math.rint(_max)) && tickVal >= Math.pow(10,Math.rint(_min))) {
//Add tick val if in range.
result.add(new Double(tickVal));
}
}
}
//we have the values to set in an arraylist.
//set them in the arrays.
int numberOfTick = result.size();
createLabels(numberOfTick);
//Compute the values of the Ticks.
for (int i=0; i<numberOfTick; i++){
Double value = (Double) result.get(i);
if (_format!=null){
_gridValues[i].setString(_format.format(new Double(value.doubleValue())));
}
else{
_gridValues[i].setString(AxisLabelFormatter.labelFormat(value.doubleValue()));
}
//set tick double value in the array.
_gridDoubleValues[i] = value.doubleValue();
}
}
/**
* Method <b>createAndComputeLinearLabels</b>
* <br><b>Summary:</b><br>
* This method creates and compute the label position and value, for a linear axis.
* Parameters:
* @param step The step that will be used to compute labels.
*
*/
private void createAndComputeLinearLabels(double step) {
int n=1;
if (step!=0){
double minStep = Math.ceil(_min/step) * step;
// if zero is inside, label it
if ((minStep < 0.0) && (_max > 0.0)) {
int n1 = (int)Math.floor(_max / _step);
int n2 = (int)Math.floor(Math.abs(minStep) / _step);
n = n1 + n2 + 1; // do not count the 0 twice
_gridOffset = -n2 * _step;
_gridZeroIndex = n2;
// otherwise, compute in the range directly
} else {
n = (int)Math.floor((_max - minStep) / _step) + 1;
_gridOffset = minStep;
_gridZeroIndex=-1;
}
}
if((_gridValues==null)||(_gridValues.length != n)|| (_gridDoubleValues == null) || (_gridDoubleValues.length != n)){
createLabels(n);
}
//Compute the values of the Ticks.
for (int i=0; i<n; i++){
double d = _gridOffset+(double)i*_step;
if (_format!=null){
_gridValues[i].setString(_format.format(new Double(d)));
}else{
_gridValues[i].setString(AxisLabelFormatter.labelFormat(d));
}
//set tick double value in the array.
_gridDoubleValues[i] = d;
}
}
/**
* Gets the axis parameters
* @return minimum value
*/
public double getMin(){
return _min;
}
/**
* Gets the axis parameters
* @return maximum value
*/
public double getMax(){
return _max;
}
/**
* Gets the axis parameters
* @return step value
*/
public double getStep(){
return _step;
}
public boolean isVertical() {
return _isVertical;
}
public void setVertical(boolean vertical) {
_isVertical = vertical;
// Create a new label shape
if (_label != null){
String labelValue = _label.getText();
_label = null;
setLabel(labelValue);
}
// Create new grid values
_gridValues = null;
if(!log){
createAndComputeLinearLabels(_step);
}else{
createAndComputeLogLabels();
}
computeBounds();
}
/**
* Gets the axis scale factor
* @return scale value
*/
public double getScale(){
if(_max==_min){
return 0.;
}
if(_isVertical){
return (_lineHeight) / (_max -_min);
}
else{
return (_lineWidth) / (_max -_min);
}
}
/**
* Draws it
* @param g2 the current graphics
*/
public void draw(Graphics2D g2) {
int k;
int l;
int o1;
g2.setColor(_color);
if (_isVertical) {
k = _withGridlines ? _lineWidth : 0;
if (_valuesFirst) {
o1 = _ox;
} else {
o1 = _ox + _lineWidth;
}
if (_withAxis){
g2.drawLine(o1, _oy, o1, _oy - _lineHeight);
}
for (int i = 0; i < _gridValues.length; i++) {
l = (i == _gridZeroIndex) ? _lineWidth : k;
if (_valuesFirst) {
g2.drawLine(o1 - _defaultTickLength, _gridPos[i], o1,
_gridPos[i]);
if (l > 0) {
Stroke s = g2.getStroke();
Color c = g2.getColor();
if (i != _gridZeroIndex)
g2.setStroke(_gridStroke);
g2.setColor(gridColor);
g2.drawLine(o1, _gridPos[i], o1 + l, _gridPos[i]);
g2.setColor(c);
g2.setStroke(s);
}
} else {
g2.drawLine(o1 + _defaultTickLength, _gridPos[i], o1,
_gridPos[i]);
if (l > 0) {
Stroke s = g2.getStroke();
Color c = g2.getColor();
if (i != _gridZeroIndex)
g2.setStroke(_gridStroke);
g2.setColor(gridColor);
g2.drawLine(o1, _gridPos[i], o1 - l, _gridPos[i]);
g2.setColor(c);
g2.setStroke(s);
}
}
}
} else {
k = _withGridlines ? _lineHeight : 0;
if (_valuesFirst) {
o1 = _oy;
} else {
o1 = _oy - _lineHeight;
}
if (_withAxis){
g2.drawLine(_ox, o1, _ox + _lineWidth, o1);
}
for (int i = 0; i < _gridValues.length; i++) {
l = (i == _gridZeroIndex) ? _lineHeight : k;
int labelShift=0;
if(_nbrLabelLines>0){
labelShift= (i%_nbrLabelLines)*_labelLineHeight;
}
if (_valuesFirst) {
g2.drawLine(_gridPos[i], o1 + _defaultTickLength + labelShift,
_gridPos[i], o1);
if (l > 0) {
Stroke s = g2.getStroke();
Color c = g2.getColor();
if (i != _gridZeroIndex)
g2.setStroke(_gridStroke);
g2.setColor(gridColor);
g2.drawLine(_gridPos[i], o1, _gridPos[i], o1 - l);
g2.setColor(c);
g2.setStroke(s);
}
} else {
g2.drawLine(_gridPos[i], o1 - _defaultTickLength - labelShift,
_gridPos[i], o1);
if (l > 0) {
Stroke s = g2.getStroke();
Color c = g2.getColor();
if (i != _gridZeroIndex)
g2.setStroke(_gridStroke);
g2.setColor(gridColor);
g2.drawLine(_gridPos[i], o1, _gridPos[i], o1 + l);
g2.setColor(c);
g2.setStroke(s);
}
}
}
}
if (_withValues) {
for (int i = 0; i < _gridValues.length; i++) {
_gridValues[i].draw(g2);
}
}
if (_label != null) {
_label.draw(g2);
}
}
/**
*
* Method <b>createLabels</b>
* <br><b>Summary:</b><br>
* This method initialise the arrays containing the tick.
* Parameters:
* @param n The number of tick, used to set array's size.
*
*/
private void createLabels(int n){
LabelShape[] tmpGridValues=new LabelShape[n];
int[] tmpGridPos=new int[n];
double[] tmpGridDoubleValues = new double[n];
int as;
if(_valuesFirst){
if(_isVertical){
as=LabelShape.LEFT;
}
else{
as=LabelShape.CENTERDOWN;
}
}
else{
if(_isVertical){
as=LabelShape.RIGHT;
}
else{
as=LabelShape.CENTERUP;
}
}
for(int i=0;i<n;i++){
tmpGridValues[i]=new LabelShape("",
0,0,as,false);
tmpGridPos[i]=0;
tmpGridDoubleValues[i]=0;
}
_gridPos = tmpGridPos;
_gridValues = tmpGridValues;
_gridDoubleValues = tmpGridDoubleValues;
}
protected void computeBounds(){
// reset labels position and
// compute labels bounds
Point p=new Point(0,0);
Point pmin=new Point(0,0);
Point pmax=new Point(0,0);
Rectangle r=null;
if(_withValues){
for(int i=0;i<_gridValues.length;i++){
LabelShape l=_gridValues[i];
l.setAnchor(p);
l.setBounds(_font);
l.getMax(pmax);
l.getMin(pmin);
}
}
if(_label!=null){
_label.setAnchor(p);
_label.setBounds(_font);
r=_label.getBounds();
}
// compute number of lines to display the labels horizontaly
// for horizontal axis without overlapping
if(!_isVertical && _withValues){
_nbrLabelLines=(int)Math.ceil(
(double)((pmax.x-pmin.x)*(_gridValues.length+1))
/ (double)_lineWidth);
if(_nbrLabelLines==0){
_nbrLabelLines=1;
}
_labelLineHeight=pmax.y-pmin.y;
}
// compute the width and the height
if (_isVertical) {
_w = _lineWidth
+ (pmax.x - pmin.x + _defaultTickLength + _defaultTickSpace);
if (r != null) {
_w += r.width;
}
if (_valuesFirst) {
_x = _lineWidth - _w;
} else {
_x = 0;
}
_h = _lineHeight + (pmax.y - pmin.y);
_y = (_h - _lineHeight) / 2;
if (_label != null) {
if (_valuesFirst) {
_label.translate(_ox + _x, _oy + _y - _h / 2);
} else {
_label.translate(_ox + _x + _w, _oy + _y - _h / 2);
}
}
} else {
_h = _lineHeight
+ ((pmax.y - pmin.y)*_nbrLabelLines + _defaultTickLength + _defaultTickSpace);
if (r != null) {
_h += r.height;
}
if (_valuesFirst) {
_y = _h - _lineHeight;
} else {
_y = 0;
}
_w = _lineWidth + (pmax.x - pmin.x);
_x = -(_w - _lineWidth) / 2;
if (_label != null) {
if (_valuesFirst) {
_label.translate(_ox + _x + _w / 2, _oy + _y);
} else {
_label.translate(_ox + _x + _w / 2, _oy + _y - _h);
}
}
}
// compute lines length and location and
// layout the labels accordingly
double sc=getScale();
long k;
for(int i=0;i<_gridValues.length;i++){
//If non log axis, return linear value.
if(!log){
//k=(long)Math.floor((_gridOffset+_step*i)*sc);
k= (long)Math.floor( (_gridDoubleValues[i] - _min)*sc);
}else{
//else, compute log value.
//get current tick value.
double currentValue = _gridOffset+ (_gridDoubleValues[i] - _min);
//beware of negative values.
if(currentValue >0){
k=(long)Math.floor((log10(currentValue)*sc));
}else{
k=0;
}
}
if(_isVertical){
_gridPos[i]=_oy - (int)k; //TODO test
if(_valuesFirst){
_gridValues[i].translate(_ox
-_defaultTickLength
-_defaultTickSpace,
_gridPos[i]);
}
else{
_gridValues[i].translate(_ox
+_lineWidth
+_defaultTickLength
+_defaultTickSpace,
_gridPos[i]);
}
}
else{
_gridPos[i] = _ox + (int)k;
int labelShift= (i%_nbrLabelLines)*_labelLineHeight;
if(_valuesFirst){
_gridValues[i].translate(_gridPos[i],
_oy
+_defaultTickLength
+_defaultTickSpace
+labelShift);
}
else{
_gridValues[i].translate(_gridPos[i],
_oy
-_lineHeight
-_defaultTickLength
-_defaultTickSpace
-labelShift);
}
}
}
}
/**
* Computes the "best" step to go from min to max
* Average number of graduations is set to 10
* Algo from simgo/util/geom/WaveAxis.java
*/
protected double computeStep(double min, double max) {
// To understand the following, note that :
// Let x = ampli/(_averageNbGrad-1) .
// Let y = x/10^E(log10(x/0.75)) .
// Then: 0.75 <= y < 7.5
// Depending on the value of y, the graduations will be
// every 1, every 2 or every 5 ( times 10^n ).
double ampli = Math.abs(max - min);
double x = ampli/9;
double ln10 = Math.log(10);
double n = Math.floor(Math.log(x / 0.75)/ln10);
double zeros = Math.exp(n*ln10); // = 10^n
double y = x/zeros;
int roundVal = 2;
if(y<1.5) roundVal = 1;
else if(y>=3.5) roundVal = 5;
double ret=roundVal * zeros;
if(ret<1e-6){
return ret;
}
else{
return Math.rint(ret*1e6)/1e6;
}
}
private void createGridStroke(){
if(_withDashedGrid==true){
final float dash[] = {5.0f,5.0f};
_gridStroke=new BasicStroke(0.1f, 0, 0, 1.0f,dash, 0.0f);
}
else{
_gridStroke=new BasicStroke(0.1f);
}
}
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
in.defaultReadObject();
if(_gridDoubleValues == null && _gridValues != null){
_gridDoubleValues = new double[_gridValues.length];
for (int i = 0; i < _gridValues.length; i++) {
try{
_gridDoubleValues[i] = Double.parseDouble(_gridValues[i].getText());
}
catch(NumberFormatException nfe){
_gridDoubleValues[i]=0;
}
}
}
createGridStroke();
}
public int getLineHeight() {
//return the _lineHeight
return _lineHeight;
}
public int getLineWidth() {
//return the _lineWidth
return _lineWidth;
}
/**
* Method <b>setLog</b>
* <br><b>Summary:</b><br>
* This method set the axis logarithmic mode indicator.
* Parameters:
* @param logpx True to put axis in logarithmic mode, or false otherwise.
*
*/
public void setLog(boolean _log) {
log = _log;
}
/**
* @return true is axis logarithmic mode indicator is logarithmic mode
*/
public boolean isLog() {
return log;
}
/**
* Method <b>log10</b>
* <br><b>Summary:</b><br>
* Compute and return the log base 10 of a given double value.
* Parameters:
* @param value The value to compute the log base 10.
* @return The computed log base 10 of the given value.
*
*/
private double log10(double value){
return Math.log(value) / CurveShape.LOG10_VALUE;
}
/**
* Returns the largest (closest to positive infinity) double value that is
* not greater than the argument, is equal to a mathematical integer and
* satisfying the condition that log base 10 of the value is an integer
* (i.e., the value returned will be a power of 10: 1, 10, 100, 1000, etc.).
*
* @param lower a double value below which a floor will be calcualted.
*
* @return 10<sup>N</sup> with N .. { 1 ... }
*/
protected double computeLogFloor(double lower) {
double logFloor;
//negative values not allowed
if (lower > 0.0) { //parameter value is > 0
logFloor = log10(lower);
logFloor = Math.floor(logFloor);
logFloor = Math.pow(10, logFloor);
} else {
//parameter value is <= 0
logFloor = Math.floor(lower); //use as-is
}
return logFloor;
}
/**
* Returns the smallest (closest to negative infinity) double value that is
* not less than the argument, is equal to a mathematical integer and
* satisfying the condition that log base 10 of the value is an integer
* (i.e., the value returned will be a power of 10: 1, 10, 100, 1000, etc.).
*
* @param upper a double value above which a ceiling will be calcualted.
*
* @return 10<sup>N</sup> with N .. { 1 ... }
*/
protected double computeLogCeil(double upper) {
double logCeil;
//negative values not allowed
if (upper > 0.0) {
//parameter value is > 0
logCeil = log10(upper);
logCeil = Math.ceil(logCeil);
logCeil = Math.pow(10, logCeil);
} else {
//parameter value is <= 0
logCeil = Math.ceil(upper); //use as-is
}
return logCeil;
}
/**
* Properties managment
*
*/
public static String getPrefix(String id){
return "PLOT_AXE_"+id;
}
public static class AxePropertiesNames extends AbstractShapePropertiesNames{
public AxePropertiesNames(String id){
super();
propertyNames.add(getPrefix(id)+"_OK");
propertyNames.add(getPrefix(id)+"_GRID");
propertyNames.add(getPrefix(id)+"_DASHEDGRID");
propertyNames.add(getPrefix(id)+"_AUTO");
propertyNames.add(getPrefix(id)+"_MIN");
propertyNames.add(getPrefix(id)+"_MAX");
propertyNames.add(getPrefix(id)+"_STEP");
propertyNames.add(getPrefix(id)+"_LABEL");
propertyNames.add(getPrefix(id)+"_LOG");
propertyNames.add(getPrefix(id)+"_FLOATING");
propertyNames.add(getPrefix(id)+"_FLOATING_RANGE");
}
}
}