private void makeRadialWall(
      DrawContext dc,
      double[] radii,
      double angle,
      double[] altitudes,
      boolean[] terrainConformant,
      int pillars,
      int stacks,
      int orientation,
      Vec4 referenceCenter,
      Geometry dest) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);
    float height = (float) (altitudes[1] - altitudes[0]);

    int count = gb.getRadialWallVertexCount(pillars, stacks);
    int numCoords = 3 * count;
    float[] verts = new float[numCoords];
    float[] norms = new float[numCoords];
    gb.makeRadialWallVertices(
        (float) radii[0], (float) radii[1], height, (float) angle, pillars, stacks, verts);
    this.makeRadialWallTerrainConformant(
        dc, pillars, stacks, verts, altitudes, terrainConformant, referenceCenter);
    gb.makeRadialWallNormals(
        (float) radii[0], (float) radii[1], height, (float) angle, pillars, stacks, norms);

    dest.setVertexData(count, verts);
    dest.setNormalData(count, norms);
  }
  private void makePartialCylinder(
      DrawContext dc,
      double radius,
      double[] altitudes,
      boolean[] terrainConformant,
      int slices,
      int stacks,
      int orientation,
      double start,
      double sweep,
      Vec4 referenceCenter,
      Geometry dest) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);
    float height = (float) (altitudes[1] - altitudes[0]);

    int count = gb.getPartialCylinderVertexCount(slices, stacks);
    int numCoords = 3 * count;
    float[] verts = new float[numCoords];
    float[] norms = new float[numCoords];
    gb.makePartialCylinderVertices(
        (float) radius, height, slices, stacks, (float) start, (float) sweep, verts);
    gb.makePartialCylinderNormals(
        (float) radius, height, slices, stacks, (float) start, (float) sweep, norms);
    this.makePartialCylinderTerrainConformant(
        dc, slices, stacks, verts, altitudes, terrainConformant, referenceCenter);

    dest.setVertexData(count, verts);
    dest.setNormalData(count, norms);
  }
Esempio n. 3
0
  private void makeSectionOutlineIndices(
      int subdivisions,
      int vertexPos,
      int indexPos,
      int[] indices,
      boolean beginEdgeFlag,
      boolean endEdgeFlag) {
    GeometryBuilder gb = this.getGeometryBuilder();
    int count = gb.getSubdivisionPointsVertexCount(subdivisions);

    int index = indexPos;
    int pos, nextPos;

    if (beginEdgeFlag) {
      pos = vertexPos;
      indices[index++] = pos;
      indices[index++] = pos + 1;
    }

    for (int i = 0; i < count - 1; i++) {
      pos = vertexPos + 2 * i;
      nextPos = vertexPos + 2 * (i + 1);
      indices[index++] = pos;
      indices[index++] = nextPos;
      indices[index++] = pos + 1;
      indices[index++] = nextPos + 1;
    }

    if (endEdgeFlag) {
      pos = vertexPos + 2 * (count - 1);
      indices[index++] = pos;
      indices[index] = pos + 1;
    }
  }
Esempio n. 4
0
  protected void makeTessellatedLocations(
      Globe globe, int subdivisions, List<LatLon> locations, List<LatLon> tessellatedLocations) {
    ArrayList<Vec4> points = new ArrayList<Vec4>();
    for (LatLon ll : locations) {
      points.add(globe.computePointFromLocation(ll));
    }

    //noinspection StringEquality
    if (WWMath.computeWindingOrderOfLocations(locations) != AVKey.COUNTER_CLOCKWISE)
      Collections.reverse(locations);

    Vec4 centerPoint = Vec4.computeAveragePoint(points);
    Vec4 surfaceNormal = globe.computeSurfaceNormalAtPoint(centerPoint);

    int numPoints = points.size();
    float[] coords = new float[3 * numPoints];
    for (int i = 0; i < numPoints; i++) {
      points.get(i).toFloatArray(coords, 3 * i, 3);
    }

    GeometryBuilder gb = new GeometryBuilder();
    GeometryBuilder.IndexedTriangleArray tessellatedPoints =
        gb.tessellatePolygon(0, numPoints, coords, surfaceNormal);

    for (int i = 0; i < subdivisions; i++) {
      gb.subdivideIndexedTriangleArray(tessellatedPoints);
    }

    for (int i = 0; i < tessellatedPoints.getVertexCount(); i++) {
      Vec4 v = Vec4.fromFloatArray(tessellatedPoints.getVertices(), 3 * i, 3);
      tessellatedLocations.add(globe.computePositionFromPoint(v));
    }
  }
  @Override
  protected List<Vec4> computeMinimalGeometry(Globe globe, double verticalExaggeration) {
    double[] angles = this.computeAngles();
    // Angles are equal, fall back to building a closed cylinder.
    if (angles == null) return super.computeMinimalGeometry(globe, verticalExaggeration);

    double[] radii = this.getRadii();
    Matrix transform = this.computeTransform(globe, verticalExaggeration);

    GeometryBuilder gb = this.getGeometryBuilder();
    int count = gb.getPartialDiskVertexCount(MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS);
    int numCoords = 3 * count;
    float[] verts = new float[numCoords];
    gb.makePartialDiskVertices(
        (float) radii[0],
        (float) radii[1], // Inner radius, outer radius.
        MINIMAL_GEOMETRY_SLICES,
        MINIMAL_GEOMETRY_LOOPS, // Slices, loops,
        (float) angles[0],
        (float) angles[2], // Start angle, sweep angle.
        verts);

    List<LatLon> locations = new ArrayList<LatLon>();
    for (int i = 0; i < numCoords; i += 3) {
      Vec4 v = new Vec4(verts[i], verts[i + 1], verts[i + 2]);
      v = v.transformBy4(transform);
      locations.add(globe.computePositionFromPoint(v));
    }

    ArrayList<Vec4> points = new ArrayList<Vec4>();
    this.makeExtremePoints(globe, verticalExaggeration, locations, points);

    return points;
  }
Esempio n. 6
0
  private int getSectionOutlineIndexCount(
      int subdivisions, boolean beginEdgeFlag, boolean endEdgeFlag) {
    GeometryBuilder gb = this.getGeometryBuilder();
    int count = 4 * (gb.getSubdivisionPointsVertexCount(subdivisions) - 1);
    if (beginEdgeFlag) count += 2;
    if (endEdgeFlag) count += 2;

    return count;
  }
Esempio n. 7
0
  private void makeEdge(
      DrawContext dc,
      int count,
      float[] locations,
      Boolean[] edgeFlags,
      double[] altitudes,
      boolean[] terrainConformant,
      int subdivisions,
      int orientation,
      Matrix locationTransform,
      Vec4 referenceCenter,
      int fillIndexPos,
      int[] fillIndices,
      int outlineIndexPos,
      int[] outlineIndices,
      int vertexPos,
      float[] vertices,
      float[] normals) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);

    int sectionFillIndexCount = this.getSectionFillIndexCount(subdivisions);
    int sectionVertexCount = this.getSectionVertexCount(subdivisions);

    for (int i = 0; i < count - 1; i++) {
      boolean beginEdgeFlag = edgeFlags[i];
      boolean endEdgeFlag = edgeFlags[i + 1];

      this.makeSectionFillIndices(subdivisions, vertexPos, fillIndexPos, fillIndices);
      this.makeSectionOutlineIndices(
          subdivisions, vertexPos, outlineIndexPos, outlineIndices, beginEdgeFlag, endEdgeFlag);
      this.makeSectionVertices(
          dc,
          i,
          locations,
          altitudes,
          terrainConformant,
          subdivisions,
          locationTransform,
          referenceCenter,
          vertexPos,
          vertices);
      gb.makeIndexedTriangleArrayNormals(
          fillIndexPos,
          sectionFillIndexCount,
          fillIndices,
          vertexPos,
          sectionVertexCount,
          vertices,
          normals);

      fillIndexPos += sectionFillIndexCount;
      outlineIndexPos += this.getSectionOutlineIndexCount(subdivisions, beginEdgeFlag, endEdgeFlag);
      vertexPos += sectionVertexCount;
    }
  }
  private void makePartialDiskIndices(int slices, int loops, int orientation, Geometry dest) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);

    int mode = gb.getPartialDiskDrawMode();
    int count = gb.getPartialDiskIndexCount(slices, loops);
    int[] indices = new int[count];
    gb.makePartialDiskIndices(slices, loops, indices);

    dest.setElementData(mode, count, indices);
  }
  private void makeRadialWallIndices(int pillars, int stacks, int orientation, Geometry dest) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);

    int mode = gb.getRadialWallDrawMode();
    int count = gb.getRadialWallIndexCount(pillars, stacks);
    int[] indices = new int[count];
    gb.makeRadialWallIndices(pillars, stacks, indices);

    dest.setElementData(mode, count, indices);
  }
Esempio n. 10
0
  private void makeCap(
      DrawContext dc,
      GeometryBuilder.IndexedTriangleArray ita,
      double altitude,
      boolean terrainConformant,
      int orientation,
      Matrix locationTransform,
      Vec4 referenceCenter,
      int indexPos,
      int[] indices,
      int vertexPos,
      float[] vertices,
      float[] normals) {
    GeometryBuilder gb = this.getGeometryBuilder();
    Globe globe = dc.getGlobe();

    int indexCount = ita.getIndexCount();
    int vertexCount = ita.getVertexCount();
    int[] locationIndices = ita.getIndices();
    float[] locationVerts = ita.getVertices();

    this.copyIndexArray(
        indexCount,
        (orientation == GeometryBuilder.INSIDE),
        locationIndices,
        vertexPos,
        indexPos,
        indices);

    for (int i = 0; i < vertexCount; i++) {
      int index = 3 * i;
      Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]);
      vec = vec.transformBy4(locationTransform);

      Position pos = globe.computePositionFromPoint(vec);
      vec =
          this.computePointFromPosition(
              dc, pos.getLatitude(), pos.getLongitude(), altitude, terrainConformant);

      index = 3 * (vertexPos + i);
      vertices[index] = (float) (vec.x - referenceCenter.x);
      vertices[index + 1] = (float) (vec.y - referenceCenter.y);
      vertices[index + 2] = (float) (vec.z - referenceCenter.z);
    }

    gb.makeIndexedTriangleArrayNormals(
        indexPos, indexCount, indices, vertexPos, vertexCount, vertices, normals);
  }
Esempio n. 11
0
  private void makeSectionVertices(
      DrawContext dc,
      int locationPos,
      float[] locations,
      double[] altitude,
      boolean[] terrainConformant,
      int subdivisions,
      Matrix locationTransform,
      Vec4 referenceCenter,
      int vertexPos,
      float[] vertices) {
    GeometryBuilder gb = this.getGeometryBuilder();
    int numPoints = gb.getSubdivisionPointsVertexCount(subdivisions);

    Globe globe = dc.getGlobe();
    int index1 = 3 * locationPos;
    int index2 = 3 * (locationPos + 1);

    float[] locationVerts = new float[3 * numPoints];
    gb.makeSubdivisionPoints(
        locations[index1],
        locations[index1 + 1],
        locations[index1 + 2],
        locations[index2],
        locations[index2 + 1],
        locations[index2 + 2],
        subdivisions,
        locationVerts);

    for (int i = 0; i < numPoints; i++) {
      int index = 3 * i;
      Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]);
      vec = vec.transformBy4(locationTransform);
      Position pos = globe.computePositionFromPoint(vec);

      for (int j = 0; j < 2; j++) {
        vec =
            this.computePointFromPosition(
                dc, pos.getLatitude(), pos.getLongitude(), altitude[j], terrainConformant[j]);

        index = 2 * i + j;
        index = 3 * (vertexPos + index);
        vertices[index] = (float) (vec.x - referenceCenter.x);
        vertices[index + 1] = (float) (vec.y - referenceCenter.y);
        vertices[index + 2] = (float) (vec.z - referenceCenter.z);
      }
    }
  }
 private static boolean polygonToLine(
     Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
   if (geom instanceof Polygon && LineString.class == targetType) {
     Polygon polygon = (Polygon) geom;
     result.add(
         geomBuilder.safeCreateGeometry(
             LineString.class, polygon.getExteriorRing().getCoordinates()));
     int i = 0;
     while (i < polygon.getNumInteriorRing()) {
       result.add(
           geomBuilder.safeCreateGeometry(
               LineString.class, polygon.getInteriorRingN(i).getCoordinates()));
       i++;
     }
     return true;
   }
   return false;
 }
Esempio n. 13
0
  private void makeSectionFillIndices(
      int subdivisions, int vertexPos, int indexPos, int[] indices) {
    GeometryBuilder gb = this.getGeometryBuilder();
    int count = gb.getSubdivisionPointsVertexCount(subdivisions);

    int index = indexPos;
    int pos, nextPos;
    for (int i = 0; i < count - 1; i++) {
      pos = vertexPos + 2 * i;
      nextPos = vertexPos + 2 * (i + 1);
      indices[index++] = pos + 1;
      indices[index++] = pos;
      indices[index++] = nextPos + 1;
      indices[index++] = nextPos + 1;
      indices[index++] = pos;
      indices[index++] = nextPos;
    }
  }
 private static boolean simpleToMultiPolygon(
     Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
   if (!(geom instanceof Polygon)
       && !(geom instanceof GeometryCollection)
       && MultiPolygon.class == targetType) {
     result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates()));
     return true;
   }
   return false;
 }
 private static boolean collectionToMultiPolygon(
     Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
   if (!(geom instanceof Polygon)
       && geom instanceof GeometryCollection
       && MultiPolygon.class == targetType) {
     for (int i = 0; i < geom.getNumGeometries(); i++) {
       result.add(
           geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates()));
     }
     return true;
   }
   return false;
 }
  public void testPrimFactCRS() throws UnsupportedOperationException, FactoryException {
    CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;
    GeometryBuilder builder = new GeometryBuilder(crs);

    CoordinateReferenceSystem crs2 = CRS.parseWKT(crs.toWKT());
    GeometryBuilder builder2 = new GeometryBuilder(crs2);

    // create a list of connected positions
    List<Position> dps = new ArrayList<Position>();
    dps.add(builder.createDirectPosition(new double[] {20, 10}));
    dps.add(builder.createDirectPosition(new double[] {40, 10}));
    dps.add(builder.createDirectPosition(new double[] {50, 40}));
    dps.add(builder.createDirectPosition(new double[] {30, 50}));
    dps.add(builder.createDirectPosition(new double[] {10, 30}));
    dps.add(builder.createDirectPosition(new double[] {20, 10}));

    // create linestring from directpositions
    LineString line = builder.createLineString(dps);

    // create curvesegments from line
    ArrayList<CurveSegment> segs = new ArrayList<CurveSegment>();
    segs.add(line);

    // Create list of OrientableCurves that make up the surface
    OrientableCurve curve = builder.createCurve(segs);
    List<OrientableCurve> orientableCurves = new ArrayList<OrientableCurve>();
    orientableCurves.add(curve);

    // create the interior ring and a list of empty interior rings (holes)
    Ring extRing = builder2.createRing(orientableCurves);
    List<Ring> intRings = new ArrayList<Ring>();

    // create the surfaceboundary from the rings
    SurfaceBoundary sb = builder2.createSurfaceBoundary(extRing, intRings);

    // create the surface
    Surface surface = builder2.createSurface(sb);
  }
  private void makePartialDisk(
      DrawContext dc,
      double[] radii,
      double altitude,
      boolean terrainConformant,
      int slices,
      int loops,
      int orientation,
      double start,
      double sweep,
      Vec4 referenceCenter,
      Geometry dest) {
    GeometryBuilder gb = this.getGeometryBuilder();
    gb.setOrientation(orientation);

    int count = gb.getPartialDiskIndexCount(slices, loops);
    int numCoords = 3 * count;
    float[] verts = new float[numCoords];
    float[] norms = new float[numCoords];
    gb.makePartialDiskVertices(
        (float) radii[0], (float) radii[1], slices, loops, (float) start, (float) sweep, verts);
    this.makePartialDiskTerrainConformant(
        dc, numCoords, verts, altitude, terrainConformant, referenceCenter);
    gb.makePartialDiskVertexNormals(
        (float) radii[0],
        (float) radii[1],
        slices,
        loops,
        (float) start,
        (float) sweep,
        verts,
        norms);

    dest.setVertexData(count, verts);
    dest.setNormalData(count, norms);
  }
 private static boolean collectionToMultiLine(
     Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
   if (!(geom instanceof Polygon)
       && !(geom instanceof MultiPolygon)
       && (geom instanceof GeometryCollection)
       && MultiLineString.class == targetType) {
     LineString[] geoms = new LineString[geom.getNumGeometries()];
     for (int i = 0; i < geom.getNumGeometries(); i++) {
       geoms[i] =
           geomBuilder.safeCreateGeometry(LineString.class, geom.getGeometryN(i).getCoordinates());
     }
     result.add(geomBuilder.factory.createMultiLineString(geoms));
     return true;
   }
   return false;
 }
  private static boolean toLinearRing(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(targetType == LinearRing.class)) return false;
    ArrayList<Geometry> tmp = new ArrayList<Geometry>();
    if (!simpleToLine(geom, LineString.class, tmp)) {
      if (!collectionToLine(geom, LineString.class, tmp)) {
        if (!polygonToLine(geom, LineString.class, tmp)) {
          if (!multiPolygonToLine(geom, LineString.class, tmp)) {
            return false;
          }
        }
      }
    }

    for (Geometry geometry : tmp) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geometry.getCoordinates()));
    }
    return true;
  }
  /**
   * Create a new Features from the provided coordinates and of the type indicated by geomType
   *
   * @param coordCRS The crs of the coordinates provided
   * @param destinationCRS The desired crs of the geometry
   * @param type the feature type of the object created
   * @param coordinates the coordinates that will be used to create the new feature
   * @param geomType the type of geometry that will be created
   * @return A new features.
   * @throws Exception
   */
  public static <T extends Geometry> SimpleFeature createFeature(
      CoordinateReferenceSystem coordCRS,
      CoordinateReferenceSystem destinationCRS,
      SimpleFeatureType type,
      Coordinate[] coordinates,
      Class<T> geomType)
      throws Exception {

    transform(coordCRS, destinationCRS, coordinates);
    Object[] attrs = new Object[type.getAttributeCount()];
    for (int i = 0; i < attrs.length; i++) {
      attrs[i] = setDefaultValue(type.getDescriptor(i));
    }
    final SimpleFeature newFeature = SimpleFeatureBuilder.build(type, attrs, null);
    // Class geomType = type.getDefaultGeometry().getType();

    T geom = GeometryBuilder.create().safeCreateGeometry(geomType, coordinates);
    newFeature.setDefaultGeometry(geom);

    return newFeature;
  }
Esempio n. 21
0
 private int getSectionFillIndexCount(int subdivisions) {
   GeometryBuilder gb = this.getGeometryBuilder();
   return 6 * (gb.getSubdivisionPointsVertexCount(subdivisions) - 1);
 }
Esempio n. 22
0
 private int getSectionVertexCount(int subdivisions) {
   GeometryBuilder gb = this.getGeometryBuilder();
   return 2 * gb.getSubdivisionPointsVertexCount(subdivisions);
 }
/**
 * A utility class for playing with features.
 *
 * @author jeichar
 */
public class FeatureUtils {

  /**
   * Create a new Features from the provided coordinates and of the type indicated by geomType
   *
   * @param coordCRS The crs of the coordinates provided
   * @param destinationCRS The desired crs of the geometry
   * @param type the feature type of the object created
   * @param coordinates the coordinates that will be used to create the new feature
   * @param geomType the type of geometry that will be created
   * @return A new features.
   * @throws Exception
   */
  public static <T extends Geometry> SimpleFeature createFeature(
      CoordinateReferenceSystem coordCRS,
      CoordinateReferenceSystem destinationCRS,
      SimpleFeatureType type,
      Coordinate[] coordinates,
      Class<T> geomType)
      throws Exception {

    transform(coordCRS, destinationCRS, coordinates);
    Object[] attrs = new Object[type.getAttributeCount()];
    for (int i = 0; i < attrs.length; i++) {
      attrs[i] = setDefaultValue(type.getDescriptor(i));
    }
    final SimpleFeature newFeature = SimpleFeatureBuilder.build(type, attrs, null);
    // Class geomType = type.getDefaultGeometry().getType();

    T geom = GeometryBuilder.create().safeCreateGeometry(geomType, coordinates);
    newFeature.setDefaultGeometry(geom);

    return newFeature;
  }

  /**
   * @param object
   * @param object2
   */
  private static Object setDefaultValue(AttributeDescriptor type) {
    if (type.getDefaultValue() != null) return type.getDefaultValue();
    if (Boolean.class.isAssignableFrom(type.getType().getBinding())
        || boolean.class.isAssignableFrom(type.getType().getBinding()))
      return Boolean.valueOf(false);
    if (String.class.isAssignableFrom(type.getType().getBinding())) return ""; // $NON-NLS-1$
    if (Integer.class.isAssignableFrom(type.getType().getBinding())) return Integer.valueOf(0);
    if (Double.class.isAssignableFrom(type.getType().getBinding())) return Double.valueOf(0);
    if (Float.class.isAssignableFrom(type.getType().getBinding())) return Float.valueOf(0);
    if (CodeList.class.isAssignableFrom(type.getType().getBinding())) {
      return type.getDefaultValue();
    }
    return null;
  }

  /**
   * Transforms coordinates into the layer CRS if nessecary
   *
   * @throws Exception
   */
  private static void transform(
      CoordinateReferenceSystem coordCRS,
      CoordinateReferenceSystem destinationCRS,
      Coordinate[] coordinates)
      throws Exception {
    if (coordCRS == null || destinationCRS == null) return;
    MathTransform mt = CRS.findMathTransform(coordCRS, destinationCRS, true);
    if (mt == null || mt.isIdentity()) return;
    double[] coords = new double[coordinates.length * 2];
    for (int i = 0; i < coordinates.length; i++) {
      coords[i * 2] = coordinates[i].x;
      coords[i * 2 + 1] = coordinates[i].y;
    }
    mt.transform(coords, 0, coords, 0, coordinates.length);
    for (int i = 0; i < coordinates.length; i++) {
      coordinates[i].x = coords[i * 2];
      coordinates[i].y = coords[i * 2 + 1];
    }
  }

  /**
   * Returns 0 if the features are the same. 1 if the attributes are the same but have different
   * featureIDs and -1 if attributes are different or are of different featureTypes.
   *
   * @param feature1
   * @param feature2
   * @return
   */
  public static int same(SimpleFeature feature1, SimpleFeature feature2) {
    if (DataUtilities.compare(feature1.getFeatureType(), feature2.getFeatureType()) != 0) {
      return -1;
    }
    for (int i = 0; i < feature1.getAttributeCount(); i++) {
      if (feature1.getAttribute(i) == null) {
        if (feature2.getAttribute(i) != null) return -1;
        else continue;
      }
      if (feature1.getAttribute(i) instanceof Geometry) {
        Geometry geom1 = (Geometry) feature1.getAttribute(i);
        if (feature2.getAttribute(i) instanceof Geometry) {
          Geometry geom2 = (Geometry) feature2.getAttribute(i);
          if (geom1.equalsExact(geom2)) continue;
          else return -1;
        } else return -1;
      }
      if (!feature1.getAttribute(i).equals(feature2.getAttribute(i))) return -1;
    }

    return feature1.getID().equals(feature2.getID()) ? 0 : 1;
  }

  public static Map<String, String> createAttributeMapping(
      SimpleFeatureType sourceSchema, SimpleFeatureType targetSchema) {
    Map<String, String> queryAttributes = new HashMap<String, String>();
    performDirectMapping(sourceSchema, targetSchema, queryAttributes);
    mapGeometryAttributes(sourceSchema, targetSchema, queryAttributes);
    return queryAttributes;
  }

  /** Maps the default geometry attribute regardless of whether they are the same type. */
  @SuppressWarnings("unchecked")
  private static void mapGeometryAttributes(
      SimpleFeatureType sourceSchema,
      SimpleFeatureType targetSchema,
      Map<String, String> queryAttributes) {
    // Now we'll match the geometry on type only. I don't care if it has the same type name.
    GeometryDescriptor defaultGeometry = targetSchema.getGeometryDescriptor();
    if (defaultGeometry == null) {
      return;
    } else if (!queryAttributes.containsKey(defaultGeometry.getName())) {
      // first check source's default geom and see if it matches
      Class<?> binding = sourceSchema.getGeometryDescriptor().getType().getBinding();
      if (defaultGeometry.getType().getBinding().isAssignableFrom(binding)) {
        queryAttributes.put(
            defaultGeometry.getName().getLocalPart(),
            sourceSchema.getGeometryDescriptor().getName().getLocalPart());
      } else {
        // we have to look through all the source attributes looking for a geometry that
        // matches.
        boolean found = false;
        for (int i = 0; i < sourceSchema.getAttributeCount(); i++) {
          AttributeDescriptor source = sourceSchema.getDescriptor(i);
          if (defaultGeometry
              .getType()
              .getBinding()
              .isAssignableFrom(source.getType().getBinding())) {
            queryAttributes.put(
                defaultGeometry.getName().getLocalPart(), source.getName().getLocalPart());
            found = true;
            break;
          }
        }
        // ok so we're going to have to do some transformations. Match default geometries
        // then.
        if (!found) {
          queryAttributes.put(
              defaultGeometry.getName().getLocalPart(),
              sourceSchema.getGeometryDescriptor().getName().getLocalPart());
        }
      }
    }
  }

  /** Maps attributes with the same name and same types to each other. */
  @SuppressWarnings("unchecked")
  private static void performDirectMapping(
      SimpleFeatureType sourceSchema,
      SimpleFeatureType targetSchema,
      Map<String, String> queryAttributes) {
    for (int i = 0; i < sourceSchema.getAttributeCount(); i++) {
      AttributeDescriptor source = sourceSchema.getDescriptor(i);
      for (int j = 0; j < targetSchema.getAttributeCount(); j++) {
        AttributeDescriptor target = targetSchema.getDescriptor(j);

        // don't worry about case of attribute name
        if (target.getName().getLocalPart().equalsIgnoreCase(source.getName().getLocalPart())
            && target.getType().getBinding().isAssignableFrom(source.getType().getBinding())) {
          queryAttributes.put(target.getName().getLocalPart(), source.getName().getLocalPart());
        }
      }
    }
  }

  private static GeometryBuilder geomBuilder = GeometryBuilder.create();

  /**
   * Adapts a collection of features to a FeatureCollection
   *
   * @param collection
   * @return
   */
  public static FeatureCollection<SimpleFeatureType, SimpleFeature> toFeatureCollection(
      final Collection<SimpleFeature> collection, SimpleFeatureType type) {
    return new AdaptorFeatureCollection("collection", type) {
      @Override
      protected void closeIterator(Iterator arg0) {}

      @Override
      protected Iterator openIterator() {
        return collection.iterator();
      }

      @Override
      public int size() {
        return collection.size();
      }
    };
  }

  public static Collection<SimpleFeature> copyFeature(
      final SimpleFeature source,
      final SimpleFeatureType destinationSchema,
      final Map<String, String> attributeMap,
      final MathTransform mt) {

    return new AbstractCollection<SimpleFeature>() {
      public Iterator<SimpleFeature> iterator() {
        final Map<String, Iterator<? extends Geometry>> geometries =
            new HashMap<String, Iterator<? extends Geometry>>();
        final Object[] attributes =
            copyAttributes(destinationSchema, source, geometries, attributeMap, mt);

        return new Iterator<SimpleFeature>() {
          SimpleFeature next, template;

          public boolean hasNext() {
            if (template == null) {
              try {
                template = next = SimpleFeatureBuilder.build(destinationSchema, attributes, null);

              } catch (Exception e) {
                // try then next one then
                CorePlugin.log("", e); // $NON-NLS-1$
              }
              return true;
            }
            if (geometries.isEmpty()) return false;

            while (next == null && !geometries.isEmpty()) {
              try {
                next = SimpleFeatureBuilder.copy(template);
                Set<Map.Entry<String, Iterator<? extends Geometry>>> entries =
                    geometries.entrySet();
                for (Iterator<Map.Entry<String, Iterator<? extends Geometry>>> iter =
                        entries.iterator();
                    iter.hasNext(); ) {
                  Map.Entry<String, Iterator<? extends Geometry>> entry = iter.next();
                  Geometry geom = entry.getValue().next();
                  next.setAttribute(entry.getKey(), transformGeom(geom, mt));
                  if (!entry.getValue().hasNext()) iter.remove();
                }
                return true;

              } catch (Exception e) {
                // try then next one then
                CorePlugin.log("", e); // $NON-NLS-1$
              }
            }
            return false;
          }

          public SimpleFeature next() {
            if (next == null)
              throw new IndexOutOfBoundsException("No more elements in iterator."); // $NON-NLS-1$
            SimpleFeature result = next;
            next = null;
            return result;
          }

          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }

      public int size() {
        int size = 0;
        for (Iterator<SimpleFeature> iter = iterator(); iter.hasNext(); iter.next()) size++;
        return size;
      }
    };
  }

  private static Object[] copyAttributes(
      SimpleFeatureType destSchema,
      SimpleFeature source,
      Map<String, Iterator<? extends Geometry>> geometries,
      Map<String, String> attributeMap,
      MathTransform mt) {
    Object[] attributes = new Object[destSchema.getAttributeCount()];
    for (int i = 0; i < attributes.length; i++) {
      String sourceAttributeName = destSchema.getDescriptor(i).getName().getLocalPart();
      String name = attributeMap.get(sourceAttributeName);
      if (name != null) attributes[i] = source.getAttribute(name);
      else {
        attributes[i] = destSchema.getDescriptor(i).getDefaultValue();
      }
      if (attributes[i] instanceof Geometry) {
        Class<? extends Geometry> geomType =
            (Class<? extends Geometry>) destSchema.getDescriptor(i).getType().getBinding();
        if (!geomType.isAssignableFrom(attributes[i].getClass())) {
          Collection<? extends Geometry> geom =
              createCompatibleGeometry((Geometry) attributes[i], geomType);
          Iterator<? extends Geometry> giter = geom.iterator();
          attributes[i] = giter.next();
          if (giter.hasNext()) geometries.put(sourceAttributeName, giter);
        }
        attributes[i] = transformGeom((Geometry) attributes[i], mt);
      }
    }
    return attributes;
  }

  private static Geometry transformGeom(Geometry geom, MathTransform mt) {
    if (mt != null) {
      try {
        return JTS.transform(geom, mt);
      } catch (TransformException e) {
        CorePlugin.log("", e); // $NON-NLS-1$
        return geom;
      }
    }
    return geom;
  }

  private static Collection<? extends Geometry> createCompatibleGeometry(
      Geometry geom, Class<? extends Geometry> targetType) {
    Collection<Geometry> result = new ArrayList<Geometry>();
    if (nonCollectionToPoint(geom, targetType, result)) return result;
    else if (collectionToPoint(geom, targetType, result)) return result;
    else if (nonCollectionToMultiPoint(geom, targetType, result)) return result;
    else if (collectionToMultiPoint(geom, targetType, result)) return result;
    else if (simpleToLine(geom, targetType, result)) return result;
    else if (collectionToLine(geom, targetType, result)) return result;
    else if (simpleToMultiLine(geom, targetType, result)) return result;
    else if (collectionToMultiLine(geom, targetType, result)) return result;
    else if (polygonToMultiLine(geom, targetType, result)) return result;
    else if (polygonToLine(geom, targetType, result)) return result;
    else if (multiPolygonToLine(geom, targetType, result)) return result;
    else if (multiPolygonToMultiLine(geom, targetType, result)) return result;
    else if (simpleToPolygon(geom, targetType, result)) return result;
    else if (collectionToPolygon(geom, targetType, result)) return result;
    else if (multiPolygonToPolygon(geom, targetType, result)) return result;
    else if (simpleToMultiPolygon(geom, targetType, result)) return result;
    else if (collectionToMultiPolygon(geom, targetType, result)) return result;
    else if (polygonToMultiPolygon(geom, targetType, result)) return result;
    else if (toLinearRing(geom, targetType, result)) return result;
    throw new IllegalArgumentException(
        "do not know how transform from "
            + geom.getClass().getName()
            + " to "
            + targetType.getName()); // $NON-NLS-1$ //$NON-NLS-2$
  }

  /**
   * return true if Geometry is a point and targetType is a point. Result will be populated with the
   * new point
   */
  private static boolean nonCollectionToPoint(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof GeometryCollection) && Point.class == targetType) {
      result.add(geom.getCentroid());
      return true;
    }
    return false;
  }

  private static boolean collectionToPoint(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof GeometryCollection && Point.class == targetType) {
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        result.add(geom.getGeometryN(i).getCentroid());
      }
      return true;
    }
    return false;
  }

  private static boolean collectionToMultiPoint(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof GeometryCollection && MultiPoint.class == targetType) {
      Point[] points = new Point[geom.getNumGeometries()];
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        points[i] = geom.getGeometryN(i).getCentroid();
      }
      result.add(geomBuilder.factory.createMultiPoint(points));
      return true;
    }
    return false;
  }

  private static boolean nonCollectionToMultiPoint(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof GeometryCollection) && MultiPoint.class == targetType) {
      result.add(geomBuilder.factory.createMultiPoint(geom.getCentroid().getCoordinates()));
      return true;
    }
    return false;
  }

  private static boolean simpleToLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof GeometryCollection)
        && LineString.class == targetType) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates()));
      return true;
    }
    return false;
  }

  private static boolean collectionToLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof MultiPolygon)
        && (geom instanceof GeometryCollection)
        && LineString.class == targetType) {
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        result.add(
            geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates()));
      }
      return true;
    }
    return false;
  }

  private static boolean simpleToMultiLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof GeometryCollection)
        && MultiLineString.class == targetType) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates()));
      return true;
    }
    return false;
  }

  private static boolean collectionToMultiLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof MultiPolygon)
        && (geom instanceof GeometryCollection)
        && MultiLineString.class == targetType) {
      LineString[] geoms = new LineString[geom.getNumGeometries()];
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        geoms[i] =
            geomBuilder.safeCreateGeometry(LineString.class, geom.getGeometryN(i).getCoordinates());
      }
      result.add(geomBuilder.factory.createMultiLineString(geoms));
      return true;
    }
    return false;
  }

  private static boolean simpleToPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof GeometryCollection)
        && Polygon.class == targetType) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates()));
      return true;
    }
    return false;
  }

  private static boolean collectionToPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof MultiPolygon)
        && geom instanceof GeometryCollection
        && Polygon.class == targetType) {
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        result.add(
            geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates()));
      }
      return true;
    }
    return false;
  }

  private static boolean polygonToLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof Polygon && LineString.class == targetType) {
      Polygon polygon = (Polygon) geom;
      result.add(
          geomBuilder.safeCreateGeometry(
              LineString.class, polygon.getExteriorRing().getCoordinates()));
      int i = 0;
      while (i < polygon.getNumInteriorRing()) {
        result.add(
            geomBuilder.safeCreateGeometry(
                LineString.class, polygon.getInteriorRingN(i).getCoordinates()));
        i++;
      }
      return true;
    }
    return false;
  }

  private static boolean polygonToMultiLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof Polygon && MultiLineString.class == targetType) {
      ArrayList<Geometry> tmp = new ArrayList<Geometry>();
      if (!polygonToLine(geom, LineString.class, tmp))
        throw new RuntimeException(
            "Huh?  multi polygons should only have polygons in them"); //$NON-NLS-1$
      result.add(geomBuilder.factory.createMultiLineString(tmp.toArray(new LineString[0])));
      return true;
    }
    return false;
  }

  private static boolean multiPolygonToLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof MultiPolygon && LineString.class == targetType) {
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        if (!polygonToLine(geom.getGeometryN(i), targetType, result))
          throw new RuntimeException(
              "Huh?  multi polygons should only have polygons in them"); //$NON-NLS-1$
      }
      return true;
    }
    return false;
  }

  private static boolean multiPolygonToMultiLine(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof MultiPolygon && MultiLineString.class == targetType) {

      for (int i = 0; i < geom.getNumGeometries(); i++) {
        if (!polygonToMultiLine(geom.getGeometryN(i), targetType, result))
          throw new RuntimeException(
              "Huh?  multi polygons should only have polygons in them, found a "
                  + geom.getGeometryN(i)); // $NON-NLS-1$
      }

      return true;
    }
    return false;
  }

  private static boolean multiPolygonToPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof MultiPolygon && Polygon.class == targetType) {
      for (int j = 0; j < geom.getNumGeometries(); j++) {
        result.add(geom.getGeometryN(j));
      }

      return true;
    }
    return false;
  }

  private static boolean simpleToMultiPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && !(geom instanceof GeometryCollection)
        && MultiPolygon.class == targetType) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geom.getCoordinates()));
      return true;
    }
    return false;
  }

  private static boolean collectionToMultiPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(geom instanceof Polygon)
        && geom instanceof GeometryCollection
        && MultiPolygon.class == targetType) {
      for (int i = 0; i < geom.getNumGeometries(); i++) {
        result.add(
            geomBuilder.safeCreateGeometry(targetType, geom.getGeometryN(i).getCoordinates()));
      }
      return true;
    }
    return false;
  }

  private static boolean polygonToMultiPolygon(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (geom instanceof Polygon && MultiPolygon.class == targetType) {
      result.add(geomBuilder.factory.createMultiPolygon(new Polygon[] {(Polygon) geom}));
      return true;
    }
    return false;
  }

  private static boolean toLinearRing(
      Geometry geom, Class<? extends Geometry> targetType, Collection<Geometry> result) {
    if (!(targetType == LinearRing.class)) return false;
    ArrayList<Geometry> tmp = new ArrayList<Geometry>();
    if (!simpleToLine(geom, LineString.class, tmp)) {
      if (!collectionToLine(geom, LineString.class, tmp)) {
        if (!polygonToLine(geom, LineString.class, tmp)) {
          if (!multiPolygonToLine(geom, LineString.class, tmp)) {
            return false;
          }
        }
      }
    }

    for (Geometry geometry : tmp) {
      result.add(geomBuilder.safeCreateGeometry(targetType, geometry.getCoordinates()));
    }
    return true;
  }

  public static Set<Identifier> stringToId(FilterFactory fac, String fid) {
    return stringToId(fac, Collections.singleton(fid));
  }

  public static Set<Identifier> stringToId(FilterFactory fac, Collection<String> fid) {
    Set<Identifier> ids = new HashSet<Identifier>();
    for (String string : fid) {
      ids.add(fac.featureId(string));
    }
    return ids;
  }

  /**
   * Convert a string to a Id filter
   *
   * @param fid the feature id
   * @return
   */
  @SuppressWarnings("unchecked")
  public static Filter id(String fid) {
    FilterFactory factory = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
    Set<Identifier> id = stringToId(factory, fid);
    Id filter = factory.id(id);
    return filter;
  }
}
Esempio n. 24
0
  private void makePolygon(
      DrawContext dc,
      List<LatLon> locations,
      List<Boolean> edgeFlags,
      double[] altitudes,
      boolean[] terrainConformant,
      boolean enableCaps,
      int subdivisions,
      Vec4 referenceCenter,
      PolygonGeometry dest) {
    if (locations.size() == 0) return;

    GeometryBuilder gb = this.getGeometryBuilder();

    Vec4[] polyPoints = new Vec4[locations.size() + 1];
    Boolean[] polyEdgeFlags = new Boolean[locations.size() + 1];
    Matrix[] polyTransform = new Matrix[1];
    int polyCount =
        this.computeCartesianPolygon(
            dc.getGlobe(), locations, edgeFlags, polyPoints, polyEdgeFlags, polyTransform);

    // Compute the winding order of the planar cartesian points. If the order is not
    // counter-clockwise, then
    // reverse the locations and points ordering.
    int winding = gb.computePolygonWindingOrder2(0, polyCount, polyPoints);
    if (winding != GeometryBuilder.COUNTER_CLOCKWISE) {
      gb.reversePoints(0, polyCount, polyPoints);
      gb.reversePoints(0, polyCount, polyEdgeFlags);
    }

    float[] polyVertices = new float[3 * polyCount];
    this.makePolygonVertices(polyCount, polyPoints, polyVertices);

    int fillDrawMode = GL.GL_TRIANGLES;
    int outlineDrawMode = GL.GL_LINES;

    int fillIndexCount = 0;
    int outlineIndexCount = 0;
    int vertexCount = 0;

    GeometryBuilder.IndexedTriangleArray ita = null;

    fillIndexCount += this.getEdgeFillIndexCount(polyCount, subdivisions);
    outlineIndexCount += this.getEdgeOutlineIndexCount(polyCount, subdivisions, polyEdgeFlags);
    vertexCount += this.getEdgeVertexCount(polyCount, subdivisions);

    if (enableCaps) {
      ita = gb.tessellatePolygon2(0, polyCount, polyVertices);
      for (int i = 0; i < subdivisions; i++) {
        gb.subdivideIndexedTriangleArray(ita);
      }

      fillIndexCount += ita.getIndexCount();
      vertexCount += ita.getVertexCount();
      // Bottom cap isn't drawn if airspace is collapsed.
      if (!this.isAirspaceCollapsed()) {
        fillIndexCount += ita.getIndexCount();
        vertexCount += ita.getVertexCount();
      }
    }

    int[] fillIndices = new int[fillIndexCount];
    int[] outlineIndices = new int[outlineIndexCount];
    float[] vertices = new float[3 * vertexCount];
    float[] normals = new float[3 * vertexCount];

    int fillIndexPos = 0;
    int outlineIndexPos = 0;
    int vertexPos = 0;

    this.makeEdge(
        dc,
        polyCount,
        polyVertices,
        polyEdgeFlags,
        altitudes,
        terrainConformant,
        subdivisions,
        GeometryBuilder.OUTSIDE,
        polyTransform[0],
        referenceCenter,
        fillIndexPos,
        fillIndices,
        outlineIndexPos,
        outlineIndices,
        vertexPos,
        vertices,
        normals);
    fillIndexPos += this.getEdgeFillIndexCount(polyCount, subdivisions);
    outlineIndexPos += this.getEdgeOutlineIndexCount(polyCount, subdivisions, polyEdgeFlags);
    vertexPos += this.getEdgeVertexCount(polyCount, subdivisions);

    if (enableCaps) {
      this.makeCap(
          dc,
          ita,
          altitudes[1],
          terrainConformant[1],
          GeometryBuilder.OUTSIDE,
          polyTransform[0],
          referenceCenter,
          fillIndexPos,
          fillIndices,
          vertexPos,
          vertices,
          normals);
      fillIndexPos += ita.getIndexCount();
      vertexPos += ita.getVertexCount();
      // Bottom cap isn't drawn if airspace is collapsed.
      if (!this.isAirspaceCollapsed()) {
        this.makeCap(
            dc,
            ita,
            altitudes[0],
            terrainConformant[0],
            GeometryBuilder.INSIDE,
            polyTransform[0],
            referenceCenter,
            fillIndexPos,
            fillIndices,
            vertexPos,
            vertices,
            normals);
        fillIndexPos += ita.getIndexCount();
        vertexPos += ita.getVertexCount();
      }
    }

    dest.getFillIndexGeometry().setElementData(fillDrawMode, fillIndexCount, fillIndices);
    dest.getOutlineIndexGeometry()
        .setElementData(outlineDrawMode, outlineIndexCount, outlineIndices);
    dest.getVertexGeometry().setVertexData(vertexCount, vertices);
    dest.getVertexGeometry().setNormalData(vertexCount, normals);
  }