package clientdata.visitors.terrain.layers; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import org.apache.mina.core.buffer.IoBuffer; public class BoundaryPolygon extends BoundaryLayer { final static float eps = 0.000001f; List<Vector2D> verts; int use_water_height; float water_height; float water_shader_size; String water_shader; public boolean useWaterHeight() { return use_water_height != 0; } public float getWaterHeight() { return water_height; } public float getWaterShaderSize() { return water_shader_size; } public String getWaterShader() { return water_shader; } float max_x, max_z, min_x, min_z; public BoundaryPolygon() { type = LayerType.BPOL; verts = new ArrayList<Vector2D>(); } @Override public boolean isContained(float x, float y) { int j; //boolean odd_nodes = false; float x1, x2; int crossings = 0; for ( int i = 0; i < verts.size(); ++i ) { j = (i+1) % verts.size(); if ( verts.get(i).getX() < verts.get(j).getX()) { x1 = (float)verts.get(i).getX(); x2 = (float)verts.get(j).getX(); } else { x1 = (float)verts.get(j).getX(); x2 = (float)verts.get(i).getX(); } /* First check if the ray is possible to cross the line */ if ( x > x1 && x <= x2 && ( y < (float)verts.get(i).getY() || y <= (float)verts.get(j).getY() ) ) { /* Calculate the equation of the line */ float dx = (float)verts.get(j).getX() - (float)verts.get(i).getX(); float dz = (float)verts.get(j).getY() - (float)verts.get(i).getY(); float k; if ( Math.abs(dx) < eps ){ k = Float.POSITIVE_INFINITY; } else { k = dz/dx; } float m = (float)verts.get(i).getY() - k * (float)verts.get(i).getX(); /* Find if the ray crosses the line */ float z2 = k * x + m; if ( y <= z2 ) { //odd_nodes=!odd_nodes; crossings++; } } } if(crossings % 2 == 1) return true; return false; //return odd_nodes; } @Override public float process(float px, float py) { float result; Vector2D last = verts.get(verts.size() - 1); boolean odd_nodes = false; if (px < min_x || px > max_x || py < min_z || py > max_z) return 0.0f; if (verts.size() <= 0) return 0.0f; for (int i = 0; i < verts.size(); i++) { Vector2D point = verts.get(i); if ((point.getY() <= py && py < last.getY()) || (last.getY() <= py && py < point.getY())) if ((py - point.getY()) * (last.getX() - point.getX()) / (last.getY() - point.getY()) + point.getX() > (double)px) odd_nodes = !odd_nodes; last = point; } double feather2, new_feather; if (odd_nodes) { if (feather_amount == 0) return 1.0f; feather2 = Math.pow(feather_amount,2); new_feather = feather2; double diffz, diffx, dist; for (int i = 0; i < verts.size(); ++i) { Vector2D point = verts.get(i); diffz = py - point.getY(); diffx = px - point.getX(); dist = Math.pow(diffz,2) + Math.pow(diffx,2); if ( dist < feather2 ) feather2 = dist; } double ltp_x, ltp_z, ptl_z, ptl_x, diff, new_dist, newX, newZ; last = verts.get(verts.size() - 1); for (int i = 0; i < verts.size(); ++i) { Vector2D point = verts.get(i); ltp_x = last.getX() - point.getX(); ltp_z = last.getY() - point.getY(); ptl_z = point.getY() - last.getY(); ptl_x = point.getX() - last.getX(); diff = ((px - last.getX()) * ptl_x + (py - last.getY()) * ptl_z) / (ltp_z * ptl_z + ltp_x * ltp_x); if ( diff >= 0.0 ) { if ( diff <= 1.0 ) { newX = px - (ptl_x * diff + last.getX()); newZ = py - (ptl_z * diff + last.getY()); new_dist = newZ * newZ + newX * newX; if ( new_dist < feather2 ) { feather2 = new_dist; } } } last = point; } if ( feather2 >= new_feather - 0.00009999999747378752 && feather2 <= new_feather + 0.00009999999747378752 ) result = 1.0f; else result = (float) (Math.sqrt(feather2) / feather_amount); } else { result = 0.0f; } return result; } @Override public void loadData(IoBuffer buffer) throws Exception { int sizeTemp = buffer.getInt(); min_x = Float.MAX_VALUE; max_x = Float.MIN_VALUE; min_z = Float.MAX_VALUE; max_z = Float.MIN_VALUE; for(int j =0; j < sizeTemp; ++j) { float tempX = buffer.getFloat(); float tempZ = buffer.getFloat(); verts.add(new Vector2D(tempX, tempZ)); if(tempX > max_x) { max_x = tempX; } else if(tempX < min_x) { min_x = tempX; } if (tempZ > max_z) { max_z = tempZ; } else if (tempZ < min_z) { min_z = tempZ; } } feather_type = buffer.getInt(); feather_amount = buffer.getFloat(); use_water_height = buffer.getInt(); water_height = buffer.getFloat(); water_shader_size = buffer.getFloat(); water_shader = buffer.getString(Charset.forName("US-ASCII").newDecoder()); } @Override public float getMinX() { return min_x; } @Override public float getMinZ() { return min_z; } @Override public float getMaxX() { return max_x; } @Override public float getMaxZ() { return max_z; } }