Package org.osm2world.core.world.modules

Source Code of org.osm2world.core.world.modules.GolfModule$Fairway

package org.osm2world.core.world.modules;

import static java.lang.Math.PI;
import static java.util.Arrays.asList;
import static org.osm2world.core.math.VectorXZ.fromAngle;
import static org.osm2world.core.target.common.material.NamedTexCoordFunction.*;
import static org.osm2world.core.target.common.material.TexCoordUtil.*;
import static org.osm2world.core.world.modules.common.WorldModuleGeometryUtil.createTriangleStripBetween;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.osm2world.core.map_data.data.MapArea;
import org.osm2world.core.map_data.data.MapElement;
import org.osm2world.core.map_data.data.MapNode;
import org.osm2world.core.map_data.data.overlaps.MapOverlap;
import org.osm2world.core.map_elevation.data.EleConnectorGroup;
import org.osm2world.core.map_elevation.data.GroundState;
import org.osm2world.core.math.LineSegmentXZ;
import org.osm2world.core.math.PolygonXYZ;
import org.osm2world.core.math.SimplePolygonXZ;
import org.osm2world.core.math.TriangleXYZ;
import org.osm2world.core.math.TriangleXZ;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;
import org.osm2world.core.math.algorithms.JTSTriangulationUtil;
import org.osm2world.core.math.algorithms.Poly2TriTriangulationUtil;
import org.osm2world.core.target.RenderableToAllTargets;
import org.osm2world.core.target.Target;
import org.osm2world.core.target.common.material.ImmutableMaterial;
import org.osm2world.core.target.common.material.Material;
import org.osm2world.core.target.common.material.Material.Lighting;
import org.osm2world.core.target.common.material.Materials;
import org.osm2world.core.util.MinMaxUtil;
import org.osm2world.core.util.exception.TriangulationException;
import org.osm2world.core.world.data.AbstractAreaWorldObject;
import org.osm2world.core.world.data.TerrainBoundaryWorldObject;
import org.osm2world.core.world.modules.SurfaceAreaModule.SurfaceArea;
import org.osm2world.core.world.modules.common.AbstractModule;

import com.google.common.base.Function;

/**
* adds golf courses to the map
*/
public class GolfModule extends AbstractModule {
 
  private static final int HOLE_CIRCLE_VERTICES = 8;
  private static final double HOLE_RADIUS = 0.108 / 2;
  private static final double HOLE_DEPTH = 0.102;
 
  @Override
  public void applyToArea(MapArea area) {
   
    if (!area.getTags().containsKey("golf")) return;
   
    if (area.getTags().contains("golf", "tee")) {
      area.addRepresentation(new Tee(area));
    } else if (area.getTags().contains("golf", "fairway")) {
      area.addRepresentation(new Fairway(area));
    } else if (area.getTags().contains("golf", "green")) {
      area.addRepresentation(new Green(area));
    }
   
  }
 
  private static class Tee extends SurfaceArea {

    private Tee(MapArea area) {
     
      super(area, area.getTags().containsKey("surface")
          ? area.getTags().getValue("surface")
          : "grass");
     
    }
   
  }
 
  private static class Fairway extends SurfaceArea {

    private Fairway(MapArea area) {
     
      super(area, area.getTags().containsKey("surface")
          ? area.getTags().getValue("surface")
          : "grass");
     
    }
   
  }
 
  private static class Green extends AbstractAreaWorldObject
      implements RenderableToAllTargets, TerrainBoundaryWorldObject {
   
    private final VectorXZ pinPosition;
    private final SimplePolygonXZ pinHoleLoop;
    private final EleConnectorGroup pinConnectors;
   
    private Green(MapArea area) {
     
      super(area);
     
      /* check whether a pin has been explicitly mapped */
     
      VectorXZ explicitPinPosition = null;
     
      for (MapOverlap<?, ?> overlap : area.getOverlaps()) {
       
        MapElement other = overlap.getOther(area);
       
        if (other.getTags().contains("golf","pin")
            && other instanceof MapNode) {
         
          explicitPinPosition = ((MapNode)other).getPos();
         
          break;
         
        }
       
      }
     
      /* place an implicit pin if none has been mapped */
     
      if (explicitPinPosition != null) {
       
        pinPosition = explicitPinPosition;
       
      } else {
       
        pinPosition = area.getOuterPolygon().getCenter();
       
      }
       
      /* create circle around the hole */
       
      List<VectorXZ> holeRing = new ArrayList<VectorXZ>(HOLE_CIRCLE_VERTICES);
     
      for (int i = 0; i < HOLE_CIRCLE_VERTICES; i++) {
        VectorXZ direction = fromAngle(2 * PI * ((double)i / HOLE_CIRCLE_VERTICES));
        VectorXZ vertex = pinPosition.add(direction.mult(HOLE_RADIUS));
        holeRing.add(vertex);
      }
     
      holeRing.add(holeRing.get(0));
     
      pinHoleLoop = new SimplePolygonXZ(holeRing);
     
      pinConnectors = new EleConnectorGroup();
      pinConnectors.addConnectorsFor(pinHoleLoop.getVertexCollection(), area, GroundState.ON);
     
    }
   
    @Override
    public GroundState getGroundState() {
      return GroundState.ON;
    }
   
    @Override
    public EleConnectorGroup getEleConnectors() {
     
      EleConnectorGroup eleConnectors = super.getEleConnectors();
     
      if (pinConnectors != null) {
        eleConnectors.addAll(pinConnectors);
      }
     
      return eleConnectors;
     
    }
   
    @Override
    public void renderTo(Target<?> target) {
     
      /* render green surface */
     
      String surfaceValue = area.getTags().getValue("surface");
     
      Material material = Materials.GRASS;
     
      if (surfaceValue != null && !"grass".equals(surfaceValue)) {
        material = Materials.getSurfaceMaterial(surfaceValue, material);
      }

      Collection<TriangleXZ> trianglesXZ = getGreenTriangulation();
      Collection<TriangleXYZ> triangles = getEleConnectors().getTriangulationXYZ(trianglesXZ);
     
      target.drawTriangles(material, triangles,
          triangleTexCoordLists(triangles , material, GLOBAL_X_Z));
     
      /* render pin */
         
      PolygonXYZ upperHoleRing = pinConnectors.getPosXYZ(pinHoleLoop);
       
      drawPin(target, pinPosition, upperHoleRing.getVertexLoop());
     
    }
   
    private List<TriangleXZ> getGreenTriangulation() {
     
      List<SimplePolygonXZ> holes = area.getPolygon().getHoles();
     
      holes.add(pinHoleLoop);
     
      try {
       
        return Poly2TriTriangulationUtil.triangulate(
          area.getPolygon().getOuter(),
          holes,
          Collections.<LineSegmentXZ>emptyList(),
          Collections.<VectorXZ>emptyList());
       
      } catch (TriangulationException e) {
       
        System.err.println("Poly2Tri exception for " + this + ":");
        e.printStackTrace();
        System.err.println("... falling back to JTS triangulation.");
       
        return JTSTriangulationUtil.triangulate(
            area.getPolygon().getOuter(),
            holes,
            Collections.<LineSegmentXZ>emptyList(),
            Collections.<VectorXZ>emptyList());
       
      }
     
    }

    private static void drawPin(Target<?> target,
        VectorXZ pos, List<VectorXYZ> upperHoleRing) {
     
      double minHoleEle = MinMaxUtil.<VectorXYZ>min(upperHoleRing,
          new Function<VectorXYZ, Double>() {
        @Override public Double apply(VectorXYZ v) {
          return v.y;
        }
      }).y;
     
      double holeBottomEle = minHoleEle - HOLE_DEPTH;
           
      /* draw hole */
     
      List<VectorXYZ> lowerHoleRing = new ArrayList<VectorXYZ>();
      for (VectorXYZ v : upperHoleRing) {
        lowerHoleRing.add(v.y(holeBottomEle));
      }
                 
      List<VectorXYZ> vs = createTriangleStripBetween(
          upperHoleRing, lowerHoleRing);
     
      Material groundMaterial = Materials.EARTH.makeSmooth();
     
      target.drawTriangleStrip(groundMaterial, vs,
          texCoordLists(vs, groundMaterial, STRIP_WALL));
     
      target.drawConvexPolygon(groundMaterial, lowerHoleRing,
          texCoordLists(vs, groundMaterial, GLOBAL_X_Z));
     
      /* draw flag */
     
      target.drawColumn(Materials.PLASTIC_GREY.makeSmooth(), null,
          pos.xyz(holeBottomEle), 1.5, 0.007, 0.007, false, true);
     
      ImmutableMaterial flagcloth = new ImmutableMaterial(Lighting.SMOOTH, Color.YELLOW);
     
      List<VectorXYZ> flagVertices = asList(
          new VectorXYZ(pos.x, 1.5, pos.z),
          new VectorXYZ(pos.x, 1.2, pos.z),
          new VectorXYZ(pos.x + 0.4, 1.5, pos.z),
          new VectorXYZ(pos.x + 0.4, 1.2, pos.z));
     
      target.drawTriangleStrip(flagcloth, flagVertices,
          texCoordLists(flagVertices, flagcloth, STRIP_WALL));
     
    }
   
  }
 
}
TOP

Related Classes of org.osm2world.core.world.modules.GolfModule$Fairway

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.