Anyone mess with GIS data?

Discussion in 'OT Technology' started by Astro, Dec 12, 2003.

  1. Astro

    Astro Code Monkey

    Joined:
    Mar 18, 2000
    Messages:
    2,047
    Likes Received:
    0
    Location:
    Cleveland Ohio
    So I'm looking to kick up my mapping capabilities by a notch by using GIS data. Basically, if experimenting is successful, I may have a commercial application for it.

    So far I've played with TigerServer (open source - site currently offline). It was easy to install, but seems highly unstable and rather resource intensive (my P100 Linux choked and my Sun e250 hesitates slightly).

    I've been playing with MapServer (open source - site up - don't have the link at the moment). A small pain in the ass if you don't have all the libraries. I managed to get all the libraries installed, but it looks like a small pain in the ass to actually configure it to use useful map data.

    Anybody fiddle with GIS data and mapping servers? Its kind of fun to play with, but haven't figured out all the tricks or the best software to use...
     
  2. SLED

    SLED build an idiot proof device and someone else will

    Joined:
    Sep 20, 2001
    Messages:
    28,118
    Likes Received:
    0
    Location:
    AZ, like a bauce!
    i haven't done the map thing per se... but i have just recently done a bunch of work with gps coordinates, and calculating distances on anything with a longitude latitude coordinate. I'm currently using it for a "store locator" for some side work i'm doing. Basically i have a table with every zip code in the US and it's lon/lat coordinates, and then it will calculate the distance to the closest store location to you. pretty cool stuff actually. The math is a bitch. I'd be curious to know if you have any success with those map servers.. i might have to impliment one :)
     
  3. Astro

    Astro Code Monkey

    Joined:
    Mar 18, 2000
    Messages:
    2,047
    Likes Received:
    0
    Location:
    Cleveland Ohio
    Distance finding is fun (by lat/long or zip): http://www.axtime.com/zip/zip.php

    I have yet to do a "find all locations within X miles of Y zip", but I think I have the mad math skillz, yo, to figure it out - thanks to pre-calc and trig. For the application I'm looking to build, I don't think I'll need to implement a "within range" feature in the first release.

    Whats a lot of fun is plotting coordinates on a map: http://www.axtime.com/zip/usaplot_netoh.php

    Which is part of my goal for bringing up a map server. Here's one running off my Sun server assuming the IP hasn't changed (unlikely) or the mapping server upchucked (biggest reason why I'm looking for another server app):

    [​IMG]
     
    Last edited: Dec 13, 2003
  4. SLED

    SLED build an idiot proof device and someone else will

    Joined:
    Sep 20, 2001
    Messages:
    28,118
    Likes Received:
    0
    Location:
    AZ, like a bauce!
    ahhh within a certain distance shouldn't be too much of a problem. Well, i don't know how you're storing your data, but here is what i implimented for my stuff. It's a compiled C mySQL User Defined Function (should be able to add it to any newer version of mySQL) but here is the code:

    Code:
    
    #ifdef STANDARD
    #include <stdio.h>
    #include <string.h>
    #ifdef __WIN__
    typedef unsigned __int64 ulonglong;	/* Microsofts 64 bit types */
    typedef __int64 longlong;
    #else
    typedef unsigned long long ulonglong;
    typedef long long longlong;
    #endif /*__WIN__*/
    #else
    #include <my_global.h>
    #include <my_sys.h>
    #endif
    #include <mysql.h>
    #include <m_ctype.h>
    #include <m_string.h>		// To get strmov()
    
    #ifdef HAVE_DLOPEN
    
    /* These must be right or mysqld will not find the symbol! */
    
    extern "C" {
    my_bool geodist_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    void geodist_deinit(UDF_INIT *initid);
    double geodist(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
    		   char *error);
    }
    double pi = 3.141592653589792907377;
    double rad(double gr) {return pi * gr / 180.0;}
    
    
    /*
      Simple example of how to get a sequences starting from the first argument
      or 1 if no arguments have been given
    */
    
    my_bool geodist_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
    {
      if (args->arg_count != 4)
      {
        strmov(message,"geodis takes 4 args");
        return 1;
      }
      if( args->arg_type[0] != REAL_RESULT || args->arg_type[1] != REAL_RESULT ||
    	args->arg_type[2] != REAL_RESULT || args->arg_type[3] != REAL_RESULT )
      {
        strcpy(message, "geodist() requires all 4 parameters to be type REAL");
        return 1;
      }
      // set max decimals to 2 because we are returning miles
      initid->decimals = 2;
      return 0;
    }
    
    void geodist_deinit(UDF_INIT *initid)
    {
    }
    
    double geodist(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
    		   char *error)
    {
      double lat1 = 0.0;
      double lon1 = 0.0;
      double lat2 = 0.0;
      double lon2 = 0.0;
    
      lat1 = *((double*) args->args[0]);
      lon1 = *((double*)args->args[1]);
      lat2 = *((double*)args->args[2]);
      lon2 = *((double*)args->args[3]);
    
      return 0.621 * 6371.2 * 2 *
    	atan2( sqrt(fabs(0 + pow(sin(rad(lat2)/2 - rad(lat1)/2),2) +
    	cos(rad(lat1)) * cos(rad(lat2)) * pow(sin(rad(lon2)/2 -
    	rad(lon1)/2),2))),sqrt(fabs(1 - pow(sin(rad(lat2)/2 -
    	rad(lat1)/2),2) + cos(rad(lat1)) * cos(rad(lat2)) *
    	pow(sin(rad(lon2)/2 - rad(lon1)/2),2))));
     
    }
    
    #endif /* HAVE_DLOPEN */
    
    
    
    I actually had a lot of fun figuring this stuff out..

    easiest way to compile is "gcc -shared -o geodist.so -I /usr/local/mysql/include geodist.cpp"

    that will create your .so then copy it to /usr/lib or somewhere that mysql knows about and to add, just make sure you have permissions to write to the mysql database and run this:
    Code:
    create function geodist returns real soname "geodist.so";
    
    Then you can run the function just like any other function. "Select geodist(1.0,2.0,3.0,4.0);" This function takes 4 arguments.. basically 2 pairs of lat/long's and will compute the distance between them (in miles)
     
  5. Astro

    Astro Code Monkey

    Joined:
    Mar 18, 2000
    Messages:
    2,047
    Likes Received:
    0
    Location:
    Cleveland Ohio
    WOW!

    I was able to compile it without a problem and I tossed the file in /usr/lib and ran the MySQL query. Then tested it out with a simple query and presto! MySQL was calculating the distance. Very cool! Thanks SLED!
     
  6. Astro

    Astro Code Monkey

    Joined:
    Mar 18, 2000
    Messages:
    2,047
    Likes Received:
    0
    Location:
    Cleveland Ohio
    For those wondering, SLED's approach works perfectly for Red Hat v6

    SLED (and others):
    For Red Hat v8 I had to use the following line to compile:

    "gcc -shared -o geodist.so -I /usr/local/mysql/include geodist.cpp -lm"

    Notice the "-lm" on the end. This includes the math library. I was getting an error about "sin symbol not found" and the "-lm" seemed to do the trick.

    Where I found the info: http://www.mysql.com/doc/en/C_API_linking_problems.html

    SLED: I'm not sure if this addresses any of the problems you mentioned regarding RH v9. I did get a compile warning saying "using the kernel header in userland program. BAD!"
     
  7. SLED

    SLED build an idiot proof device and someone else will

    Joined:
    Sep 20, 2001
    Messages:
    28,118
    Likes Received:
    0
    Location:
    AZ, like a bauce!
    haha, ya i got the same thing on Redhat 9. I actually went into the mysql file which was including that and commented it out. It didn't seem like it did much for the library, but aparently it does. It compiled fine after that, but when i went to add it to mysql, it bitched about something and then output some weird characters, and took a shit. I just ended up going back to SuSE and all was good. :)
     

Share This Page