Loading...
Logo
Processing Forum
Hi,

Sorry if this is a repost, been looking though the forums to see if I could find something that answers my question, but couldn't.

Anyhoo,

I have a flat world map, would like to be able to determine which continent, country the click is in, if its the ocean etc.

I suppose if anyone can post a link to a tutorial on this or have any advice on the best method to achieve this.

I'm a bit anti-library, in that I like to do everything from scratch, I have no time limit and the goal is learning.

Thanks in advance for any help.




Replies(15)



technical FAQ needed....

you can always paint the same map on a hidden canvas (PGraphics pg, same size as your size command in setup()) and give each country a different color (only in the PGraphics which you don't display, make the red value counting up for each country, the other two colors are 0 (when you have less than 255 countries):
Copy code
  1. pg.fill (count,0,0);
).

Then check the mouse on the hidden canvas, something like:
Copy code
  1. void mousePressed() {
  2.     indexCountry=int(red(pg.get(mouseX,mouseY) ));
  3. }
The "indexCountry" gives you the number of the Country where the mouse has been clicked.

See here for a similar approach for the US states

https://forum.processing.org/topic/need-help-with-mouse-over-text-box-display-on-us-map#25080000002266353


Greetings, Chrisir    

Yes, another potential entry for the technical FAQ, I note it, Chrisir. Thanks for the suggestion.
Thanks for the quick reply. Ive looked over that other post and its given me some ideas. Looks like I need to learn how to use Illustrator first..

if i'm not mistaken you can load a svg in processing and make it forget the colors.

Then you can use your own colors with pg.fill as described

You don't need to make the red colors in Illustrator


True, but having some issues getting a  working svg.

 Im using some world maps svg's I've found on wiki media, but having  a bit of trouble.

The first one I've found that fitted the bill seemed to have all the children,  so
Copy code
  1. getChild('us')
would select the node titled 'us' and let me colour it. But the size was all messed up and it had these wierd dots appeared all over it, even though they were not in Illustrator.

So tried another one, but all though in Illustrator it seems to be formatted in the same way, i.e you can hover over each element.
Copy code
  1. GScape.getChildCount();
returns 1.

Messing with the old while loop idea. Ill keep playing with it, sure ill get there in the end.

Im more of a programmer than I am a designer so a lot to take on board and learn.
So.. think I am getting to grips with this svg thing a bit, although can you maybe explain where I am going wrong?

Looking over the svg doc,

Copy code
  1. <g id="positioner" transform="translate(180, 90) scale(1, -1)">
  2. <g id="AFG">
  3. <path d="M74.891 ect ect........ ;"/>
  4. </g>
  5. </g>

  6. PShape positioner = GScape.getChild("positioner");
  7. println(positioner.getChildCount()); // 244 there be me countries!
  8. PShape AFG = positioner.getChild("AFG"); 
  9. shape(AFG 500, 500); // Nada


The map I am using is http://upload.wikimedia.org/wikipedia/commons/thumb/5/51/BlankMap-Equirectangular.svg/1000px-BlankMap-Equirectangular.svg.png by the way.




Apparently I am a spoon and should be ignored, the shape was just to small for me to see, but was being draw fine.
Ok, last thing Chrisir, I promise :/

Copy code
  1.      Map CountryCodeMap = new HashMap();
         PShape positioner = GScape.getChild("positioner"); 
         int countryId = 1;
         scale(10);
         while( countryId < positioner.getChildCount() ) {
             PShape country = positioner.getChild(countryId);
             CountryCodeMap.put(countryId, new Country( countryId, country.getName() ));
             fill(countryId);
             shape(country);
             countryId ++;
         }
         scale(1);

Is this right?

Two things jump out at me as a fail.

1: The fill colour isnt working and they all stay they original colour.

2. The map is rendered upside down...



question 1


Copy code
  1.     // Disable the colors found in the SVG file
  2.     state.disableStyle();

(country in your code)


question 2

what if it comes without the scale ?

or like this

Copy code
  1.     shape(state, 0, 0);

(country in your code)



Ok, so think I am nearly there. Turns out I hadnt read the post to linked to properly, so yes needed to disable the node style first before colouring.

And although I dont understand why, the grapghic / or the shape was being rendered upside down and back to front..

A quick CountryShape.scale(3, -2); sorted that out..

Now. why do the click events only return 0, or very occasionally 17.. Drawing the graphic shows that all the countries have varing shades of red, so unsure whats going on there. Here is the full code.

Copy code
  1. class GeoScape{
      
     PGraphics GeoScapeUnderLay;
     PImage GeoScapeOverLay;
     PShape GeoSvg;
      
     Map CountryHMap = new HashMap();
     
     public GeoScape(){
        GeoSvg = loadShape("images/geo/gscape2.svg");
        GeoScapeOverLay = loadImage("images/geo/geoOverlay.png");
        GeoScapeUnderLay = createGraphics( (displayWidth / 2) + 100, (displayHeight / 2)  );

        generateGeoScape(); 
      }
     
      public void generateGeoScape()
      { 
          PShape positioner = GeoSvg.getChild("positioner");
          int CID = (positioner.getChildCount() - 1);
          GeoScapeUnderLay.beginDraw();
          GeoScapeUnderLay.background(0);
          while(CID != 1){
              PShape CountryShape = positioner.getChild(CID);
              CountryShape.disableStyle();
              CountryHMap.put(CID, new Country(CID, CountryShape.getName()) );
              GeoScapeUnderLay.fill(CID, 0, 0); 
              CountryShape.scale(3, -2);           
              GeoScapeUnderLay.shape(CountryShape, GeoScapeUnderLay.width/2 , GeoScapeUnderLay.height/2);
              CID--;
          }
          println(CountryHMap); // Has all the entries with codes
          GeoScapeUnderLay.endDraw();
      }
     
      public void renderGeoMap(){
          int graphObjCenterX = (displayWidth / 2) - (GeoScapeUnderLay.width /2);
          int graphObjCenterY = (displayHeight / 2) - (GeoScapeUnderLay.height /2);
         
          image(GeoScapeUnderLay, graphObjCenterX, graphObjCenterY );
          //image(GeoScapeOverLay, graphObjCenterX, graphObjCenterY ); 
  2.      }

  3. public class Country{
        public int CID;
        public String CName;
     
        public Country(int ID, String Name){
          CID = ID;
          CName = Name; 
        }
    }
     
     public String getCountry(int CID){
        String countryString = "No Country";
        if(CID != 0){
          Country countryObj = (Country) CountryHMap.get(CID); 
          countryString = countryObj .CName;
        }
        return countryString;
      }
      
    }

      In the main Sketch

Copy code
  1. void mousePressed() { 
      int CID = int(red(geoscape.GeoScapeUnderLay.get(mouseX, mouseY)));
      println(CID); // Only ever 0 or 17
      println(Incursion.geoscape.getCountry(CID));  // Return "No Country as its 0 Or Belguim as thats Id 17"
    }





Hi,

I don't really know...

[Edited]


In this line
Copy code
  1.     GeoScapeUnderLay = createGraphics( (displayWidth / 2) + 100, (displayHeight / 2)  );
the size must be exactly the size and position of your sketch (or your map in the sketch)
Copy code
  1.     GeoScapeUnderLay = createGraphics( width, height );

Also pos of all shapes must be the same between the real map and GeoScapeUnderLay...

??
Turns out you are right my old chumley warner.

Copy code
  1. GeoScapeUnderLay = createGraphics( displayWidth, displayHeight );


The click events where being registered in the corner, opposed to the center where I had the map.

Thats all working now.

I take my hat off to you sir, you are a king amongst men.