/******************************************************************************* * Copyright 2012 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.worldwind.common.layers.model.gocad; import gov.nasa.worldwind.geom.Position; import java.awt.Color; import java.net.URL; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.media.opengl.GL2; import au.gov.ga.earthsci.worldwind.common.render.fastshape.FastShape; /** * A {@link GocadReader} that reads a VSet object into a {@link FastShape} * * @author James Navin (james.navin@ga.gov.au) */ public class GocadVSetReader implements GocadReader<FastShape> { public final static String HEADER_REGEX = "(?i).*vset.*"; private final static Pattern atomSizePattern = Pattern.compile("\\*atoms\\*size:(.+)"); private final static Pattern atomColorPattern = Pattern.compile("\\*atoms\\*color:.+"); private GocadReaderParameters parameters; private List<Position> positions; private boolean zPositive; private String name; private Float size; private Color color; private List<Float> values; private float min, max; private String paintedVariableName; private int paintedVariableId = 0; private float noDataValue = -Float.MAX_VALUE; private Map<Integer, Integer> vertexIdMap; @Override public void begin(GocadReaderParameters parameters) { this.parameters = parameters; positions = new ArrayList<Position>(); values = new ArrayList<Float>(); min = Float.MAX_VALUE; max = -Float.MAX_VALUE; vertexIdMap = new HashMap<Integer, Integer>(); paintedVariableName = parameters.getPaintedVariable(); } @Override public void addLine(String line) { Matcher matcher; // Vertex / PVertex matcher = vertexPattern.matcher(line); if (matcher.matches()) { processVertexLine(matcher); return; } // ZPOSITIVE directive matcher = zpositivePattern.matcher(line); if (matcher.matches()) { zPositive = !matcher.group(1).equalsIgnoreCase("depth"); return; } // Atom size matcher = atomSizePattern.matcher(line); if (matcher.matches()) { size = Float.parseFloat(matcher.group(1)); return; } // Atom color matcher = atomColorPattern.matcher(line); if (matcher.matches()) { color = GocadColor.gocadLineToColor(line); return; } // NODATA value matcher = nodataValuesPattern.matcher(line); if (matcher.matches()) { processNodataValue(matcher); return; } // Properties matcher = propertiesPattern.matcher(line); if (matcher.matches()) { processPropertiesLine(matcher); return; } // Painted variable matcher = paintedVariablePattern.matcher(line); if (matcher.matches()) { if (parameters.getPaintedVariable() == null) { paintedVariableName = matcher.group(1); } return; } // Name matcher = namePattern.matcher(line); if (matcher.matches()) { name = matcher.group(1); return; } } @Override public FastShape end(URL context) { if (name == null) { name = "VSet"; } FastShape shape = new FastShape(positions, GL2.GL_POINTS); shape.setName(name); if (parameters.getPointSize() != null) { shape.setPointSize(parameters.getPointSize()); } else { shape.setPointSize((double) size); } shape.setPointMaxSize(parameters.getPointMaxSize()); shape.setPointMinSize(parameters.getPointMinSize()); shape.setPointConstantAttenuation(parameters.getPointConstantAttenuation()); shape.setPointLinearAttenuation(parameters.getPointLinearAttenuation()); shape.setPointQuadraticAttenuation(parameters.getPointQuadraticAttenuation()); if (parameters.getColorMap() != null) { float[] colorBuffer = createColorBuffer(); shape.setColorBufferElementSize(4); shape.setColorBuffer(colorBuffer); } else if (parameters.getColor() != null) { shape.setColor(parameters.getColor()); } else if (color != null) { shape.setColor(color); } return shape; } private float[] createColorBuffer() { FloatBuffer colorBuffer = FloatBuffer.allocate(positions.size() * 4); for (float value : values) { if (Float.isNaN(value) || value == noDataValue) { colorBuffer.put(0).put(0).put(0).put(0); } else { Color color = parameters.getColorMap().calculateColorNotingIsValuesPercentages(value, min, max); colorBuffer.put(color.getRed() / 255f).put(color.getGreen() / 255f).put(color.getBlue() / 255f) .put(color.getAlpha() / 255f); } } return colorBuffer.array(); } private void processVertexLine(Matcher matcher) { int id = Integer.parseInt(matcher.group(1)); Position position = createPositionFromVertex(Double.parseDouble(matcher.group(2)), Double.parseDouble(matcher.group(3)), Double.parseDouble(matcher.group(4))); positions.add(position); vertexIdMap.put(id, positions.size() - 1); float value = Float.NaN; if (paintedVariableId <= 0) { value = (float) position.elevation; } else { double[] values = GocadTSurfReader.splitStringToDoubles(matcher.group(5)); if (paintedVariableId <= values.length) { value = (float) values[paintedVariableId - 1]; } } if (!Float.isNaN(value) && value != noDataValue) { min = Math.min(min, value); max = Math.max(max, value); } values.add(value); } private Position createPositionFromVertex(double x, double y, double z) { if (!zPositive) { z = -z; } double[] xyz = transformVertex(x, y, z); return Position.fromDegrees(xyz[1], xyz[0], xyz[2]); } private double[] transformVertex(double... xyz) { if (parameters.getCoordinateTransformation() == null) { return xyz; } parameters.getCoordinateTransformation().TransformPoint(xyz); return xyz; } private void processNodataValue(Matcher matcher) { double[] values = GocadTSurfReader.splitStringToDoubles(matcher.group(1)); if (0 < paintedVariableId && paintedVariableId <= values.length) { noDataValue = (float) values[paintedVariableId - 1]; } } private void processPropertiesLine(Matcher matcher) { String properties = matcher.group(1).trim(); String[] split = properties.split("\\s+"); for (int i = 0; i < split.length; i++) { if (split[i].equalsIgnoreCase(paintedVariableName)) { paintedVariableId = i + 1; break; } } } }