Announcement

Collapse
No announcement yet.

New OSM Buildings layer and how to deploy it

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • New OSM Buildings layer and how to deploy it

    Hi folks,

    I'm writing a WorldWindJava layer to integrate the openstreetmap buildings from http://www.osmbuildings.org project.
    I have some questions about the deployement of my layer :

    - Should I fork WorldWindJava and write my layer as org.nasa.worldwind.layers.Earth and commit my changes to master branch (reviewer by WorldWindJava maintainer). That's what I have done for the moment.

    - Should I create an independent project for my layer.

    Any feedback welcome.
    Central Park
    Last edited by sbodmer; 01-13-2017, 10:53 PM.

  • #2
    That looks really great! As for what to do with it, well I encourage you to read the following issues on GitHub:

    https://github.com/NASAWorldWind/WorldWindJava/pull/77

    https://github.com/NASAWorldWind/Wor...Java/issues/81

    The NASA team is a little behind in creating new labels to facilitate the communication of which features we intend to incorporate in the main project, but just be patient, we've got a lot of work going on right now. The community branch would likely be the target for your effort, and the contacts for the leaders of that effort appear in the two issue links above.

    Again, that looks really good, and thanks for your willingness to contribute!
    Zach
    World Wind Team
    https://github.com/NASAWorldWind

    Comment


    • #3
      Wow !! How did you do this ? Is it KML ? There has been attemps in the past to display KML cities but they were suffering from performance , no concerns on this side ?
      Congratulations anyway!

      Comment


      • #4
        No, it's not KML, but GeoJSON data.

        It's quit simple in fact, the www.osmbuildings.org project has the data directly accessible in JSON (for a given tile), so only a wrapper is needed to convert GeoJSON to WW primitives.
        The main problem will be the data source itself, many openstreetmap cities have no full buildings data (height, roof, ...), only major cities have some complete data (New York is an exception, the data are quit complete, so the results is effectively quit nice).
        I also had a "Wow" moment when I saw the result for New York the first time
        ... but faded a bit when I discovered that other cities are quit more flat...

        The performance is still a problem, but for my use case it is definitely usable (1-2 fps for the Central Park screenshot above on Linux with GTX780).
        Last edited by sbodmer; 01-14-2017, 11:31 AM.

        Comment


        • #5
          Ok I know I am a little busy but what is the url for getting the JSON? Yes I have worked with GeoJSON. I want to see how well/fast Android natively can handle this rather than Javascript.

          Regards,
          -Tony

          Comment


          • #6
            The documentation for the json (tile) is
            https://github.com/OSMBuildings/OSMB...docs/server.md
            The tile level is fixed to 15 {z} and the user is "anonymous" {k}

            adanecito Can you comment your result on android if you experiment it, thanks for the feedback.
            Last edited by sbodmer; 01-23-2017, 09:00 PM.

            Comment


            • #7
              Hi sbodmer.
              Absolutely.

              Comment


              • #8
                Well I did not see any documentation on how to call it. It talks about image tiles yet no examples of REST calls and the geoJSON responses. I was hoping to see examples of the REST call so I can see the geoJSON response. Guess I will wait till I see the layer code you are working on. :-) Anyway sounds like they are not ready for users yet.

                I will keep checking.
                -Tony

                Comment


                • #9
                  Well, the documentation explains how to call it (use "anonymous" for {k})

                  --- From osmbuildings.org doc ---
                  Code for OSM Buildings data service ist not public. However, you may use our service for free.
                  Before hitting us with heavy load, please get in touch at support@osmbuildings.org
                  The built in default server URL schema is https://{s}.data.osmbuildings.org/0.2/{k}/tile/{z}/{x}/{y}.json
                  Placeholder and adressing schema is described here: http://wiki.osgeo.org/wiki/Tile_Map_...Tile_Resources
                  {s} in our case stands for a subdomain (a,b,c,d) to extend the number of browser requests per domain.
                  ---

                  Here is a an example for the Geneva (CH) region
                  http://b.data.osmbuildings.org/0.2/a...944/11633.json

                  So, the tricky part is to determine which tile to call (my approach is to get the center of the user viewport in world coordinates and then find the corresponding tile).
                  After calling the osmbuildings URL, a geoJSON is returned for the specified tile.

                  You can find my code on my WorldWind SDK fork
                  https://github.com/sbodmer/WorldWindJava
                  I'm thinking to re-organise my implementaiton to a separate project, so my code should change a bit in a near futur.

                  The class you are looking for is
                  Code:
                  gov.nasa.worldwind.layers.Earth.OSMBuldingsLayer
                  gov.nasa.worldwind.layers.Earth.OSMBuldingsTile
                  gov.nasa.worldwind.render.OSMBuildingsRenderable
                  @adanecito Please continue your investigation, and don't hesitate to ask me some questions about my implementation, I'm so impatient to see an android port ;^)
                  Last edited by sbodmer; 01-25-2017, 09:05 AM.

                  Comment


                  • #10
                    Also the Eiffel Tower in Paris has a very strange shape :-)
                    https://osmbuildings.org/?lat=48.859...tion=0&tilt=30
                    Amazing anyway

                    Comment


                    • #11
                      Click image for larger version  Name:	LaDefense.jpg Views:	1 Size:	39.3 KB ID:	156805



                      Hello sbodmer,

                      I've tried your code and I have to congratulate you once again
                      Indeed it works well with "cylindrical" objets like sky-scrapers, (see attached LaDefense in Paris) not with individal houses with at least 2 slopes roof, not flat one. But this is the beginning, I guess, this is promizing. I had very few problems with screen credit image file to be set, and also colors missing while surfing around cities, like "maroon" or "firebrick",and instaed of adding colors in the static, i searched the web the best way to get colors from text or hexa and it seems that JavaFX is the best candidate nowadays. So I translated the COLORS array to colors that are NOT handled by javaFX yet, and added a private "stringToColor" method at the end of your code, here below. The formatting may differ from the one you use, sorry.
                      Code:
                      package gov.nasa.worldwind.render;
                      
                      import gov.nasa.worldwind.Disposable;
                      import gov.nasa.worldwind.WorldWind;
                      import gov.nasa.worldwind.avlist.AVKey;
                      import gov.nasa.worldwind.avlist.AVList;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONDoc;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONFeature;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONFeatureCollection;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONGeometry;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONGeometryCollection;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONMultiLineString;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONMultiPoint;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONMultiPolygon;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONObject;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONPoint;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONPolygon;
                      import gov.nasa.worldwind.formats.geojson.GeoJSONPositionArray;
                      import gov.nasa.worldwind.geom.Position;
                      import gov.nasa.worldwind.util.Logging;
                      
                      import java.awt.Color;
                      import java.util.ArrayList;
                      import java.util.HashMap;
                      import java.util.Iterator;
                      import java.util.List;
                      import java.util.Map;
                      import java.util.Set;
                      
                      /**
                       * The renderable of the GeoJSONDoc for OSM Buildings
                       *
                       * @author sbodmer
                       */
                      public class OSMBuildingsRenderable implements Renderable, PreRenderable, Disposable {
                          private static final Map<String, String> COLORS = new HashMap<String, String>();
                      
                          private GeoJSONDoc doc = null;
                          /**
                           * Default height of buildings
                           */
                          private double defaultHeight = 10;
                      
                          /**
                           * The list of renderable for this GeoJSON object (PointPlacemarks, ExtrudePoloygon, ...)
                           */
                          private List<Renderable> renderables = new ArrayList<Renderable>();
                      
                          static {
                              COLORS.put("lightbrown", "#ac6b25");
                              COLORS.put("yellowbrown", "#bb9613");
                              COLORS.put("darkbrown", "#654321");
                              COLORS.put("redbrown", "#a52a2a");
                              COLORS.put("cream", "#ffffcc");
                          }
                      
                          /**
                           * If the height is 0, then no building are extruded
                           *
                           * @param doc
                           * @param defaultHeight
                           */
                          public OSMBuildingsRenderable(GeoJSONDoc doc, double defaultHeight) {
                              this.doc = doc;
                              this.defaultHeight = defaultHeight;
                      
                              // --- Prepare the renderable
                              if (doc.getRootObject() instanceof GeoJSONObject) {
                                  GeoJSONObject obj = (GeoJSONObject) doc.getRootObject();
                                  prepare(obj);
                              } else if (doc.getRootObject() instanceof Object[]) {
                                  for (Object o : (Object[]) doc.getRootObject()) {
                                      if (o instanceof GeoJSONObject) {
                                          prepare((GeoJSONObject) o);
                                      }
                                  }
                              } else {
                                  // ---
                              }
                          }
                      
                          @Override
                          public String toString() {
                              return "Contains " + renderables.size() + " elements to render";
                          }
                      
                          // **************************************************************************
                          // *** API
                          // **************************************************************************
                          public void clear() {
                              renderables.clear();
                          }
                      
                          // **************************************************************************
                          // *** Renderable
                          // **************************************************************************
                          @Override
                          public void render(DrawContext dc) {
                              for (Renderable r : renderables) {
                                  r.render(dc);
                              }
                          }
                      
                          @Override
                          public void preRender(DrawContext dc) {
                              for (Renderable r : renderables) {
                                  if (r instanceof PreRenderable)
                                      ((PreRenderable) r).preRender(dc);
                              }
                          }
                      
                          // **************************************************************************
                          // *** Disposable
                          // **************************************************************************
                          @Override
                          public void dispose() {
                              for (Renderable r : renderables) {
                                  if (r instanceof Disposable)
                                      ((Disposable) r).dispose();
                              }
                              renderables.clear();
                          }
                      
                          // **************************************************************************
                          // *** Private
                          // **************************************************************************
                      
                          /**
                           * Create the basic shape for the rendering
                           *
                           * @param object
                           */
                          public void prepare(GeoJSONObject object) {
                              if (object.isGeometry()) {
                                  fill(object.asGeometry(), null);
                              } else if (object.isFeature()) {
                                  GeoJSONFeature f = object.asFeature();
                                  fill(f.getGeometry(), f.getProperties());
                              } else if (object.isFeatureCollection()) {
                                  GeoJSONFeatureCollection c = object.asFeatureCollection();
                                  for (GeoJSONFeature f : c.getFeatures()) {
                                      fill(f.getGeometry(), f.getProperties());
                                  }
                              }
                          }
                      
                          protected void fill(GeoJSONGeometry geom, AVList properties) {
                              if (geom.isPoint()) {
                                  GeoJSONPoint pt = geom.asPoint();
                                  PointPlacemarkAttributes pa = new PointPlacemarkAttributes();
                                  fillRenderablePoint(pt, pt.getPosition(), pa, properties);
                              } else if (geom.isMultiPoint()) {
                                  GeoJSONMultiPoint mp = geom.asMultiPoint();
                                  PointPlacemarkAttributes pa = new PointPlacemarkAttributes();
                                  for (int i = 0; i < mp.getPointCount(); i++) {
                                      fillRenderablePoint(mp.asPoint(), mp.getPosition(i), pa, properties);
                                  }
                              } else if (geom.isLineString()) {
                                  String msg = Logging.getMessage("Geometry rendering of line not supported");
                                  Logging.logger().warning(msg);
                                  // this.addRenderableForLineString(geom.asLineString(), layer, properties);
                      
                              } else if (geom.isMultiLineString()) {
                                  GeoJSONMultiLineString ms = geom.asMultiLineString();
                                  BasicShapeAttributes sa = new BasicShapeAttributes();
                                  fillShapeAttribute(sa, properties);
                                  for (GeoJSONPositionArray coords : ms.getCoordinates()) {
                                      fillRenderablePolyline(geom, coords, sa, properties);
                                  }
                              } else if (geom.isPolygon()) {
                                  GeoJSONPolygon poly = geom.asPolygon();
                                  BasicShapeAttributes sa = new BasicShapeAttributes();
                                  fillShapeAttribute(sa, properties);
                                  // dumpAVList(properties);
                                  fillRenderablePolygon(poly, poly.getExteriorRing(), poly.getInteriorRings(), sa, properties);
                              } else if (geom.isMultiPolygon()) {
                                  GeoJSONMultiPolygon mpoly = geom.asMultiPolygon();
                                  BasicShapeAttributes sa = new BasicShapeAttributes();
                                  fillShapeAttribute(sa, properties);
                                  for (int i = 0; i < mpoly.getPolygonCount(); i++) {
                                      fillRenderablePolygon(mpoly.asPolygon(), mpoly.getExteriorRing(i), mpoly.getInteriorRings(i), sa, properties);
                                  }
                              } else if (geom.isGeometryCollection()) {
                                  GeoJSONGeometryCollection c = geom.asGeometryCollection();
                                  GeoJSONGeometry geos[] = c.getGeometries();
                                  for (int i = 0; i < geos.length; i++) {
                                      fill(geos[i], properties);
                                  }
                              } else {
                                  String msg = Logging.getMessage("Geometry not supported");
                                  Logging.logger().warning(msg);
                              }
                          }
                      
                          /**
                           * Create a PointPlacemark
                           *
                           * @param properties
                           */
                          protected void fillRenderablePoint(GeoJSONPoint owner, Position pos, PointPlacemarkAttributes attrs, AVList properties) {
                              PointPlacemark p = new PointPlacemark(pos);
                              p.setAttributes(attrs);
                              if (pos.getAltitude() != 0) {
                                  p.setAltitudeMode(WorldWind.ABSOLUTE);
                                  p.setLineEnabled(true);
                              } else {
                                  p.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);
                              }
                      
                              if (properties != null)
                                  p.setValue(AVKey.PROPERTIES, properties);
                      
                              renderables.add(p);
                          }
                      
                          /**
                           * Prepare the polygon with color if present, the points are always on the same plane
                           * <p>
                           * If the polygon has an altitude, do not extrude it
                           * <p>
                           * <p>
                           * If the polygon properties has a height use it for extrude
                           * <p>
                           * <p>
                           * If the the default height > 0 , then extrude the polygon if no other height is found
                           * <p>
                           *
                           * @param owner
                           * @param outerBoundary
                           * @param innerBoundaries
                           * @param attrs
                           * @param properties
                           */
                          protected void fillRenderablePolygon(GeoJSONPolygon owner, Iterable<? extends Position> outerBoundary, Iterable<? extends Position>[] innerBoundaries, ShapeAttributes attrs, AVList properties) {
                              if (hasNonzeroAltitude(outerBoundary)) {
                                  // --- It a ploygin with height (not a flat foot print)
                                  Polygon poly = new Polygon(outerBoundary);
                                  poly.setAttributes(attrs);
                                  if (innerBoundaries != null) {
                                      for (Iterable<? extends Position> iter : innerBoundaries) {
                                          poly.addInnerBoundary(iter);
                                      }
                                  }
                      
                                  if (properties != null)
                                      poly.setValue(AVKey.PROPERTIES, properties);
                      
                                  renderables.add(poly);
                              } else if (defaultHeight > 0) {
                                  // --- The polygon should be a volume
                                  double height = 0;
                                  double minHeight = 0;
                                  double levels = 0;
                                  String roofColor = "gray";
                                  String roofShape = "flat";
                                  double roofHeight = 0;
                                  String roofMaterial = "concrete";
                                  String roofOrientation = "along";
                                  String roofDirection = "";
                                  if (properties != null) {
                                      if (properties.getValue("height") != null)
                                          height = (Double) properties.getValue("height");
                                      if (properties.getValue("levels") != null)
                                          levels = (Double) properties.getValue("levels");
                                      if (properties.getValue("minHeight") != null)
                                          minHeight = (Double) properties.getValue("minHeight");
                                      // --- Roof
                                      if (properties.getValue("roofColor") != null)
                                          roofColor = (String) properties.getValue("roofColor");
                                      if (properties.getValue("roofShape") != null)
                                          roofShape = (String) properties.getValue("roofShape");
                                      if (properties.getValue("roofHeight") != null)
                                          roofHeight = (Double) properties.getValue("roofHeight");
                                      if (properties.getValue("roofMaterial") != null)
                                          roofMaterial = (String) properties.getValue("roofMaterial");
                                      if (properties.getValue("roofOrientation") != null)
                                          roofOrientation = (String) properties.getValue("roofOrientation");
                                      if (properties.getValue("roofDirection") != null)
                                          roofDirection = (String) properties.getValue("roofDirection");
                      
                                  }
                                  if (roofColor == null)
                                      roofColor = "gray";
                      
                                  // --- Check if height is correct
                                  if (height <= 0) {
                                      // --- Sometimes level are set, but no height
                                      // --- Consider 1 level to be4 meters
                                      height = (levels == 0 ? defaultHeight : levels * 4);
                                      minHeight = 0;
                                  } else if (minHeight >= height) {
                                      height = minHeight + 1;
                                  }
                                  // --- If levels, try some texture on it
                                  /*
                                   * if (levels > 0){ BufferedImage tex = new BufferedImage(100, (int) height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) tex.getGraphics(); int floor = (int)
                                   * (height/levels); g2.setColor(new Color(0,0,255,128)); for (int i=0;i<levels;i++) { g2.fillRect(10, (floor*i)+1, 80, floor-2); } System.out.println("LEVELS:"+levels);
                                   * attrs.setImageSource(tex); }
                                   */
                                  // ShapeAttributes at = new BasicShapeAttributes();
                                  // attrs.setInteriorMaterial(Material.WHITE);
                                  // at.setOutlineOpacity(0.5);
                                  // attrs.setInteriorOpacity(1);
                                  // at.setOutlineMaterial(Material.GREEN);
                                  // at.setOutlineWidth(2);
                                  // attrs.setDrawOutline(false);
                                  // attrs.setDrawInterior(true);
                                  // attrs.setEnableLighting(true);
                      
                                  // --- Roof cap
                                  ShapeAttributes ra = new BasicShapeAttributes();
                                  ra.setInteriorMaterial(new Material(stringToColor(roofColor)));
                                  ra.setOutlineMaterial(new Material(stringToColor(roofColor)));
                                  ra.setInteriorOpacity(roofMaterial.equals("glass") ? 0.7 : 1);
                                  ra.setDrawInterior(true);
                                  ra.setEnableLighting(true);
                                  ra.setDrawOutline(false);
                                  ra.setEnableAntialiasing(true);
                      
                                  // --- Walls with default cap (flat roof)
                                  ExtrudedPolygon box = new ExtrudedPolygon(height);
                                  box.setAltitudeMode(WorldWind.CONSTANT);
                                  box.setAttributes(attrs);
                                  box.setSideAttributes(attrs);
                                  box.setCapAttributes(ra);
                                  box.setVisible(true);
                                  box.setOuterBoundary(outerBoundary);
                                  box.setBaseDepth(-minHeight); // --- negative value will push the base up instead of below
                                  if (innerBoundaries != null) {
                                      for (Iterable<? extends Position> iter : innerBoundaries) {
                                          box.addInnerBoundary(iter);
                                      }
                                  }
                                  renderables.add(box);
                      
                                  if (roofShape.equals("pyramid") || roofShape.equals("pyramidal")) {
                                      // --- Flat
                                      /*
                                       * Polygon roof = new Polygon(outerBoundary); Position ref = outerBoundary.iterator().next(); Position nref = Position.fromDegrees(ref.getLatitude().degrees,
                                       * ref.getLongitude().degrees, height); roof.setReferencePosition(nref); roof.setAttributes(ra); renderables.add(roof);
                                       */
                      
                                  } else {
                      
                                  }
                      
                                  if (properties != null)
                                      box.setValue(AVKey.PROPERTIES, properties);
                      
                              } else {
                                  SurfacePolygon poly = new SurfacePolygon(attrs, outerBoundary);
                                  if (innerBoundaries != null) {
                                      for (Iterable<? extends Position> iter : innerBoundaries) {
                                          poly.addInnerBoundary(iter);
                                      }
                                  }
                      
                                  if (properties != null)
                                      poly.setValue(AVKey.PROPERTIES, properties);
                      
                                  renderables.add(poly);
                              }
                          }
                      
                          protected void fillRenderablePolyline(GeoJSONGeometry owner, Iterable<? extends Position> positions, ShapeAttributes attrs, AVList properties) {
                              if (hasNonzeroAltitude(positions)) {
                                  Path p = new Path();
                                  p.setPositions(positions);
                                  p.setAltitudeMode(WorldWind.ABSOLUTE);
                                  p.setAttributes(attrs);
                      
                                  if (properties != null)
                                      p.setValue(AVKey.PROPERTIES, properties);
                      
                                  renderables.add(p);
                              } else {
                                  SurfacePolyline sp = new SurfacePolyline(attrs, positions);
                      
                                  if (properties != null)
                                      sp.setValue(AVKey.PROPERTIES, properties);
                      
                                  renderables.add(sp);
                              }
                          }
                      
                          /**
                           * Check if a position has an altitude (!= 0)
                           * <p>
                           *
                           * @param positions
                           *
                           * @return
                           */
                          protected static boolean hasNonzeroAltitude(Iterable<? extends Position> positions) {
                              for (Position pos : positions) {
                                  if (pos.getAltitude() != 0)
                                      return true;
                              }
                              return false;
                          }
                      
                          protected void dumpAVList(AVList av) {
                              if (av == null)
                                  return;
                              Set<Map.Entry<String, Object>> set = av.getEntries();
                              Iterator<Map.Entry<String, Object>> it = set.iterator();
                              while (it.hasNext()) {
                                  Map.Entry<String, Object> e = it.next();
                                  System.out.println("" + e.getKey() + "=" + e.getValue().toString() + " " + e.getValue().getClass().getName());
                              }
                          }
                      
                          /**
                           * Will fill the passed shape attribute with the properties
                           *
                           * <PRE>
                           * "color" will be processed (if none found, WHITE is used)
                           * </PRE>
                           *
                           * @param sa
                           * @param properties
                           */
                          private void fillShapeAttribute(ShapeAttributes sa, AVList properties) {
                              if (properties == null)
                                  return;
                              String v = properties.getStringValue("color");
                              if (v == null)
                                  v = "gray";
                      
                              sa.setInteriorMaterial(new Material(stringToColor(v)));
                              sa.setOutlineMaterial(Material.GRAY);
                              sa.setDrawInterior(true);
                              sa.setDrawOutline(false);
                              String mat = properties.getStringValue("material");
                              if (mat == null)
                                  mat = "concrete";
                              if (mat.equals("glass")) {
                                  sa.setDrawOutline(true);
                              }
                              sa.setEnableLighting(true);
                              sa.setEnableAntialiasing(true);
                      
                              // sa.setOutlineMaterial(new Material(stringToColor(v)));
                          }
                      
                          private Color stringToColor(String value) {
                              if (value == null)
                                  return Color.GRAY;
                      
                              // Clean name for FX
                              value = value.replace(" ", "").replace("-", "").replace("_", "").toLowerCase();
                      
                              // In COLORS not handled by FX ? (yet)
                              String hex = COLORS.get(value);
                              if (hex != null)
                                  return Color.decode(hex);
                      
                              // Get the color using FX (the most complete set)
                              try {
                                  javafx.scene.paint.Color fxColor = javafx.scene.paint.Color.valueOf(value);
                                  if (fxColor == null) {
                                      System.out.println("Color not found:" + value);
                                      return Color.GRAY;
                                  }
                      
                                  return new Color((float) fxColor.getRed(), (float) fxColor.getGreen(), (float) fxColor.getBlue(), (float) fxColor.getOpacity());
                      
                              } catch (Exception e) {
                                  System.out.println("Color not found:" + value);
                                  return Color.GRAY;
                              }
                          }
                      }
                      I had also a color named "multiple" around Berlin, Germany but I don't know what that means.
                      There are also colors like "red;white"... don't know what to do with that.
                      Anyway great stuff.
                      Last edited by frenchy; 02-01-2017, 12:10 PM. Reason: shorter COLORS array, usage of javaFX

                      Comment


                      • #12
                        Nice !!!

                        frenchy I merged your code in mine
                        Can you tell me a bit more about your application from your screenshot ?
                        Is it open source and available somewhere ?
                        I'm looking for a "Reference WorldWind Application" so that I/we can share our layers with the community...
                        There is "EarthSci" but it's based on Eclipse platforme, and... humm... well... I hate Eclipse and I'm looking for
                        something lighter...
                        Are you interested to have a "WorldWindEarth" reference/demo applications ?

                        The OSM buildings spec are quit minimal (only footprints with height and roof shape is defined), so many complexe building cannot be represented with the current OSM specs, so... that's why the Eiffel tower is like this...
                        I'have not yet implemented the roofs shapes.

                        frenchy Can you upload a larger screenshot of your app (use photo objects), I would like to have a better view of your application
                        Last edited by sbodmer; 02-02-2017, 02:52 PM.

                        Comment


                        • #13
                          Hello sbodmer,
                          You will find larger screenshots in my profile page (Media/Goodies). Some pieces are directly took from the WWJ examples, some from the forum, some other have been written by myself. I've also been interested by solar-systems planets (see Media/Planets).
                          I can't give all source code but you'll find pieces in this forum... furthermore, translating the whole Swing to javaFX was not so easy, and it is not really finished.
                          It is all based on Eclipse, I can't understand why you hate it...it is the standard IDE now (with a little left to NetBeans)
                          Cheers and keep up the good work with OSM Buildings!
                          -frenchy
                          Last edited by frenchy; 02-03-2017, 11:02 AM.

                          Comment


                          • #14
                            Hello frenchy

                            Whouaaa !!!

                            WWJYC seems what I'm looking for (the JavaFX seems very nice).
                            Do you plan to release it at one time in the future as open source code ?

                            About Eclipse IDE/platforme not being my cup of tea, it's because it's not based on Swing and the RCP platforme is too complexe for single task (and other troubles...)
                            I'm a NetBeans guy for my main IDE, and I use my own (light weigthed) swing gui framework for my projects.
                            Congratultation for the JavaFX port, I never had the courage to convert my project from Swing gui to FX (is it even possible ?), it's too complexe to be done in a supportable time.

                            So, I'm thinking to start my own (open source) version of WWJYC (which I will call WorldWindEarth )

                            Comment


                            • #15
                              Thanks sbodmer,
                              I will release it for free when I'll get a 900,000 euros full-time "job" during 30 years (that's not much finally) like Francois Fillon's wife as "attaché parlementaire" and his student kids... :-))

                              About the javaFX port, to be clear, i "just" translated the external Swing panels not the core of WW which is already available using WorldWindowGLJCanvas. For sure, it would be interesting to be able to use javaFX built-in graphical objects like Cubes, Cylinders..., also use built-in animation capabilities....but that is another story.

                              Have a nice week-end!

                              Comment

                              Working...
                              X