Source of map tiles / Routing problem

Topics: General
Nov 14, 2011 at 8:56 PM

Hi radioman... its me... again... :p

I have two questions (may you can help me): first -- I contacted google, asking for a way to add elements to maps (new streets, and some POIs). They respond saying that northamerica, europe and developed countries are attended by Tele Atlas, so, this company makes maps and routing data. For southamerica, all of this data are generated via "Google Map Maker" for users itself. I logged to GMM, added some streets missing in my city map, and a couple of POIs, and was accepted. That was two weeks ago. But, i see that still dont appear in my application nor the new steets and POIs. If a log again in GMM, the changes are made. My question is: Gmap.net uses different sources/servers for google map tiles? i dont know how works this.

-- second: I updated my gmap.net from 1.5.5.5 (april 2011) to 1.6.0.0 (last hot build). Routing is workings in the same way. Here (in venezuela maps) generates erratic routes, and (if i have... lets say.. 700 latlng points in a list) the routing are painful slow. I observed you replaced GetRouteBetweenPoints and GetWalkingRouteBetweenPoints for a unique GetRoute. One of the parameteres are WalkingMode. If i pass "false" for walkingmode, the route shows many inconsistencies, but, if i pass "true", the route improves. I can do anything to get a proper route? i missing something?

If you like, i can post a bitmap showing the routes that generate gmap.net.

Thanks a million for your time and support. Priceless.

 

Coordinator
Nov 15, 2011 at 6:54 AM

hey ;} well i think you see old tiles from the cache, you can clear it by calling: GMaps.Instance.PrimaryCache.DeleteOlderThan(DateTime.Now, GMapProviders.GoogleMap.DbId);

Nov 15, 2011 at 12:57 PM

Im back Radioman...

I tried GMaps.Instance.PrimaryCache.DeleteOlderThan(DateTime.Now, GMapProviders.GoogleMap.DbId), nothing.

I tried MapControl.Manager.Mode =AccessMode.ServerOnly, nothing.

I installed my application in a brand-new machine, just unboxed, never touched, and the tiles are the same of the dev pc.

Still obtaining tiles without the new POIs and streets. But, i logged in http://www.google.com/mapmaker?hl=es  and the changes are there.  O_o

I.E.: I added a new street cross at 10.267765, -67.58678. The modification appears in GMM, but isn't loaded in Gmap.net.

More ideas?

Thanks RM

Coordinator
Nov 15, 2011 at 1:11 PM

tiles are the same as http://maps.google.com/ if you see different view, you use different source and need update url request or maybe google doesn't update tiles instantly.. i don't know

Nov 15, 2011 at 1:20 PM

I just look in http://maps.google.com, the street cross appears at given location. :'(

update url request? how can i do that?

Coordinator
Nov 15, 2011 at 1:32 PM

can you tell me the coordinates?

Nov 15, 2011 at 1:37 PM

10.267765, -67.58678

thats are the coords

Coordinator
Nov 15, 2011 at 2:30 PM
Edited Nov 16, 2011 at 10:18 AM

control version:
 http://mt0.google.com/vt/lyrs=m@163000000&hl=en&x=81856&y=123554&z=18&s=Ga

 google version:
http://mt0.google.com/vt/lyrs=m@163317509&hl=en&x=81856&y=123554&z=18&s=Ga

test version:
http://mt0.google.com/vt/lyrs=m@163999999&hl=en&x=81856&y=123554&z=18&s=Ga

..it seems, adding 999999 instead 000000 after number 163 uses latest data

Nov 15, 2011 at 2:37 PM

Oh My!

I think even this is the source of problem on my routing issue. The control are taking very older routing data, and affects in consequence the generation of routes. I will wait then.

Kudos for you, radio!

Coordinator
Nov 16, 2011 at 10:22 AM

..do you remember on what day you made the changes, maybe these numbers encode the day? And can you try make other changes, the number should change or increase if i'm right

Nov 16, 2011 at 12:48 PM
Edited Nov 16, 2011 at 3:08 PM

Hi Radioman...

I checked MapMaker, and the modifications was made in 03 November 2011 at 16:04. You need to make more modifications? let me know.

Thanks RM!

P.S.: I replaced the 163000000 with 163999999 (3 ocurrences in project), rebuilded entire solution, but no luck obtaining the lastest data  :'(

Nov 18, 2011 at 8:59 PM

Hi radio... any update respect of map version? any advice how can i accomplish the control use a newer version?

Sorry.

 

Coordinator
Nov 18, 2011 at 9:03 PM

well just increase the version number, i don't know what they mean and what system they use, so i'm not changing it right now

Nov 18, 2011 at 9:06 PM

I find in the whole control project the value "163000000" and replaced with "163999999" (3 ocurrences in project), but no luck. the demo shows the old data. I deleted all dlls before rebuilded entire project... i missing something?

Coordinator
Nov 18, 2011 at 9:11 PM

turn off automatic version update

Nov 18, 2011 at 9:16 PM
Edited Nov 18, 2011 at 9:17 PM

Oki doki. I will try that. Sorry for disturbing you.

Just as a comment, i already added a GeoFence routine to my project. its quite simple, and maybe is a good idea to add to your control. Since you already have the polygons, one function "PointIsInsidePolygon" can be interesting. If you like i post the function.

Kudos!

Coordinator
Nov 18, 2011 at 9:24 PM

definitely, good idea

Nov 18, 2011 at 9:33 PM

public bool PointsIntoPolygon(List<PointLatLng> Polypuntos, PointLatLng punto)
{
 if (Polypuntos.Count == 0) {
  return false;
 }
 List<PointLatLng> retorno = new List<PointLatLng>();
 Polypuntos.Add(Polypuntos(0));

 int x = 0;
 int valor = 0;
 x = 0;
 valor = 0;
 while (x + 1 < Polypuntos.Count) {
  if (IsOnRigth(Polypuntos(x), Polypuntos(x + 1), punto)) {
   valor += 1;
  }
  x += 1;
 }

 //si es impar entonces esta dentro de punto.
 if ((valor % 2) != 0) {
  return true;
 }
 return false;
}


private Boolean IsOnRigth(PointLatLng PolyPointA, PointLatLng PolyPointB, PointLatLng point)
{
 //x = Long
 //y = Lat
 double M = 0;
 double LngInFunction = 0;
 //Si el punto esta entre la Lat de los dos puntos
 if ((PolyPointA.lat >= point.lat && PolyPointB.lat <= point.lat) || (PolyPointB.lat >= point.lat && PolyPointA.lat <= point.lat)) {
  M = (PolyPointA.lat - PolyPointB.lat) / (PolyPointA.lng - PolyPointB.lng);
  LngInFunction = ((point.lat - PolyPointA.lat) / M) + PolyPointA.lng;
  //si esta a la derecha, sumo uno, sino no hago nada.
  if (LngInFunction <= point.lng) {
   return true;
  }
 }
 return false;
}

 

I hope this helps. Just call PointIntoPolygon and pass two parameters. The first is a List of PointLatLng, filled with the points of the polygon, the second parameter is the point to compare, in PointLatLng format, too. See'ya later Radio! thanks 4 all the help!

Nov 19, 2011 at 4:29 PM
Edited Nov 19, 2011 at 5:08 PM

Its me again, Radio.

I didnt find the "automatic version update" in VS. I turned off the "increment revision number with each publication" checkbox in the publish tab of project properties (all that i find), but still i dont have nothing. (is the same as you told me?)

Thanks.

Bernardo Salazar

Venezuela

Coordinator
Nov 19, 2011 at 4:43 PM

"automatic version update", i mean automatic google/bing version number update, you can assign it yourself and disable the 'update':

GMapProviders.GoogleMap.Version = "m@164000000";
GMapProviders.GoogleMap.TryCorrectVersion = false; 

Nov 19, 2011 at 5:10 PM

Hehehe... i recognize, im still a newbie.

VB Code:

                GMapProviders.GoogleMap.Version = "m@164999999"
                GMapProviders.GoogleMap.TryCorrectVersion = False
                Main.MapControl.MapProvider = MapProviders.GoogleMapProvider.Instance
                MiniMapControl.MapProvider = MapProviders.GoogleMapProvider.Instance

I got it. Shows the last data. Works fine in steet "GoogleMap" view, but dont work properly in Hybrid. I can see the last data only at 18 level zoom, and the screen is composed by half "satellite" tiles, and the other half with street "googlemap" tiles...

Nov 19, 2011 at 5:15 PM
Edited Nov 19, 2011 at 5:17 PM

Look this printscreen

https://skydrive.live.com/redir.aspx?cid=c44ce38e2baa217b&resid=C44CE38E2BAA217B!585

The last street data appear only at 18 level zoom. if a change zoom to 17, shows old data. but at 18 zoom, the tiles are composed in a strange way as you can see in the image posted

Coordinator
Nov 19, 2011 at 5:21 PM

o.O tried clear cache before experimenting? or try ServerOnly mode

Nov 19, 2011 at 5:28 PM
Edited Nov 19, 2011 at 5:36 PM

cleared cache via  GMaps.Instance.PrimaryCache.DeleteOlderThan(DateTime.Now, GMapProviders.GoogleMap.DbId)

tried also MapControl.Manager.Mode = AccessMode.ServerOnly, nothing....

Another side effect (a good one), is that the loading of tiles was getting sooo slow when i used "m@163000000", but when i changed to m@164999999 the load are really fast. (google dudes are doing something to getting slow the control?)

 

Coordinator
Nov 19, 2011 at 5:36 PM

i guess only the latest data is cached in their servers, old versions are removed

Nov 19, 2011 at 5:39 PM

hummm... maybe...

Meanwhile, i will start to dig in the control, looking for the source of half/half tiles thing. Maybe with my small knowledge i can resolve. I write again if i found something.

Greetings from Venezuela to all Lituanians!

Nov 19, 2011 at 6:51 PM

Ok... i figured out. Just i missing to get GmapProviders.<MapType>.Version according the type of map.

                GMapProviders.GoogleMap.Version = "m@164999999"
                GMapProviders.GoogleMap.TryCorrectVersion = False

                GMapProviders.GoogleHybridMap.Version = "h@164999999"
                GMapProviders.GoogleHybridMap.TryCorrectVersion = False

                GMapProviders.GoogleTerrainMap.Version = "t@127,r@164999999"
                GMapProviders.GoogleTerrainMap.TryCorrectVersion = False

                GMapProviders.GoogleSatelliteMap.Version = "99"                    <---- this dont have a letter suffix (m:map, h:hybrid, t:terrain)
                GMapProviders.GoogleSatelliteMap.TryCorrectVersion = False

Now working all like a charm. A zillion of thanks Radio!

Coordinator
Nov 19, 2011 at 6:59 PM
Edited Nov 19, 2011 at 7:00 PM

cheers ;}

p.s. you can make code smaller by removing GMapProviders.[GoogleHybridMap/GoogleTerrainMap/GoogleTerrainMap].TryCorrectVersion, because they use the same base class, setting it once is enough and version for satellite is ok

Coordinator
Nov 25, 2011 at 5:51 PM

p.s. PointsIntoPolygon doesn't work correctly ;/

Nov 25, 2011 at 6:01 PM

O_o

My code is writed in VB, i take it and converted via telerik's VB to C converter, and pasted. My app code is this:

    Public Function IsIntoPolygon(Polypuntos As List(Of PointLatLng), punto As PointLatLng) As Boolean
        If Polypuntos.Count = 0 Then
            Return False
        End If
        Dim retorno As New List(Of PointLatLng)()
        Polypuntos.Add(Polypuntos(0))

        Dim x As Integer = 0
        Dim valor As Integer = 0
        x = 0
        valor = 0
        While x + 1 < Polypuntos.Count
            If IsOnRigth(Polypuntos(x), Polypuntos(x + 1), punto) Then
                valor += 1
            End If
            x += 1
        End While

        'si es impar entonces esta dentro de punto.
        If (valor Mod 2) <> 0 Then
            Return True
        End If
        Return False
    End Function

    Private Function IsOnRigth(PolyPointA As PointLatLng, PolyPointB As PointLatLng, point As PointLatLng) As [Boolean]
        'x = Long, y = Lat
        Dim M As Double = 0
        Dim LngInFunction As Double = 0
        'Si el punto esta entre la Lat de los dos puntos
        If (PolyPointA.Lat >= point.Lat AndAlso PolyPointB.Lat <= point.Lat) OrElse (PolyPointB.Lat >= point.Lat AndAlso PolyPointA.Lat <= point.Lat) Then
            M = (PolyPointA.Lat - PolyPointB.Lat) / (PolyPointA.Lng - PolyPointB.Lng)
            LngInFunction = ((point.Lat - PolyPointA.Lat) / M) + PolyPointA.Lng
            'si esta a la derecha, sumo uno, sino no hago nada.
            If LngInFunction <= point.Lng Then
                Return True
            End If
        End If
        Return False
    End Function

 

I adapted this functions from the C example found in http://en.googlemaps.subgurim.net/Galeria-codigo/code-2221.aspx

Currently, until i see, its working here. (returns true or false if a PointLatLng is inside a List Of PointLatLng). Are returning an error in your project?

Coordinator
Nov 25, 2011 at 6:22 PM

i've just commited code, function return true even point isn't in the polygon, try move mouse around demo area and you see...

Nov 25, 2011 at 6:30 PM

First i have a List of Pointlatlng, and populate with the points that composes the polygon.

I have a timer, every 30 seconds i consult each marker.position in layer.markers, then i call IsIntoPolygon(List of Points, marker.position), and this returns true or false.

Are you invoking function from a MouseHover event?

Nov 25, 2011 at 6:33 PM

i downloading the changeset. let me see..

Coordinator
Nov 25, 2011 at 6:34 PM

function fixed, and Polypuntos.Add(Polypuntos(0)) isn't very good idea, each time you add starting point to your list

Nov 25, 2011 at 6:37 PM

I dont know why the original code (the subgurim guy) do that. I imagine that is emulating the polygon function that comes in sql2008 (when you add a polygon with the new datatype "geography", you need to "close" the polygon adding again the first point)... i guess...

Coordinator
Nov 25, 2011 at 6:43 PM

anyway it works, i'll add mouse events and cursor changes later, thanks

Nov 25, 2011 at 6:45 PM

No problem Radio. My pleasure. Greetings from Venezuela.

Mar 23, 2012 at 10:49 AM

// Still error exists. so I replaced IsInside() in GmapPolygon.cs as follows and tested with various polygons serveral times successfully.

public bool IsInside(PointLatLng p)
      {
          bool result = false;
          int j = Points.Count - 1;
          for (int i = 0; i < Points.Count; i++)
          {
              if (Points[i].Lat < p.Lat && Points[j].Lat >= p.Lat || Points[j].Lat < p.Lat && Points[i].Lat >= p.Lat)
              {
                  if (Points[i].Lng + (p.Lat - Points[i].Lat) / (Points[j].Lat - Points[i].Lat) * (Points[j].Lng - Points[i].Lng) < p.Lng)
                  {
                      result = !result;
                  }
              }
              j = i;
          }
          return result;
      }
May 22, 2012 at 11:15 AM

The current IsInside is indeed broken.

An exampel: In Demo.WindowsForms.MainForm I hardcoded RegeneratePolygon to use these points:

List<PointLatLng> polygonPoints = new List<PointLatLng>();
polygonPoints.Add(new PointLatLng { Lat = 51.583043275846457, Lng = 1.385650634765625 });
polygonPoints.Add(new PointLatLng { Lat = 51.605224573352459, Lng = 1.347198486328125 });
polygonPoints.Add(new PointLatLng { Lat = 51.668296682663851, Lng = 1.452941894531250 });
polygonPoints.Add(new PointLatLng { Lat = 51.704055353325900, Lng = 1.498260498046875 });
polygonPoints.Add(new PointLatLng { Lat = 51.761040492729521, Lng = 1.560058593750000 });
polygonPoints.Add(new PointLatLng { Lat = 51.752539809336511, Lng = 1.630096435546875 });
polygonPoints.Add(new PointLatLng { Lat = 51.701502099204141, Lng = 1.663055419921875 });
polygonPoints.Add(new PointLatLng { Lat = 51.655518883310300, Lng = 1.664428710937500 });
polygonPoints.Add(new PointLatLng { Lat = 51.568534262690960, Lng = 1.566925048828125 });

Zoom in on the polygon and move the mouse around it. On the eastern side it will trigger OnPolygonEnter in a number of locations.

Testing with kodraco's method worked.

Aug 9, 2012 at 11:35 AM

ping? It would be really nice to have a reliable IsInside function. I have tested kodraco's method and it does not show the same bugs as the current code.

Coordinator
Aug 9, 2012 at 12:03 PM

fixed

Aug 9, 2012 at 5:09 PM

Sorry, but the proposed algorithm for IsInside does not work if the polygon contains points that have the same latitude (e.g. case of a square)

As it is, location of point p will not be tested with respect to polygon vertices having same lat.

 

Note- the problem also existed in IsOnRight function.

Unfortunately, I do not have at once a solution in mind.

 

 

 

Aug 9, 2012 at 5:27 PM
Edited Aug 9, 2012 at 5:30 PM

Hello

The good algorithm to chevk if a point is inside a polygon is

1- Test if the point is in the outside rectangle of the polygon

2- If yes check the count of intersection of a virtual line crossing your point  and the polygon segment

If the count is odd the point is outside the polygon

The approch of berniesf seems to be good
Here is mine in cSharp (with some optimisation)
 
NB : I try to use the Code Snipset but it seems to not work (or I don't know how to use it) I
I will try something manually
<code>

    // ********************************************************************************************
    // Verification si le segment p1,p2 est sequant avec la demi droite horizontale px,->(infini)

    static int isRightCrossing(PointF p1, PointF p2, PointF px)
    {
      double X;
      ///
      #region Equation
      bool isVertical = false;
      double Ea;
      double Eb;
      Ea = (double)(p1.X - p2.X);
      if (Ea == 0)
      {
        Eb = p1.X;
        isVertical = true;          // evite division par zero
      }
      else
      {
        Ea = (double)(p1.Y - p2.Y) / Ea;
        Eb = p1.Y - (p1.X * Ea);
      }
      #endregion
      ///
      if (isVertical)
      {
        if (px.X <= Eb)
        {
          return 1;
        }
        return 0;
      }
      X = (px.Y - Eb) / Ea;
      if (X >= px.X)
      {
        return 1;             // sequant
      }
      return 0;               // pas sequant
    }

    // ********************************************************************************************
    // Verification si le point p est interne ou externe au polygone

    static public int isPointInPol(PointF p, PointF[] Pts)
    {
      // on considere un segment S d'equation Y=p(y) et d'origine p(x,y)
      // pour chaque segment sp (Pts[n],Pts[n+1]) du polygone, on verifie si le segment S
      // est séquant avec le segment sp
      // on compte les segments sequants
      // si Pair ou zero : point est externe
      // si impair       : point est interne


      int step = 0;
      int Obase = 0;
      int oneUp = 0;
      int oneDown = 0;
      int inter = 0;
      int nbPts = Pts.Length;


      // Si non le point est forcément en dessous du polygone
      // Si oui le point doit se projeter entre ce point du polygone et le précédent


      for (step = Obase; step < nbPts; step++)
      {
        oneUp = 0;                         // on suppose tous les points du polygone en dessous
        for (; step < nbPts; step++)       // recherche si un Y du Pol est > ou egal au y du point
        {
          if (Pts[step].Y >= p.Y)
          {
            oneUp = 1;
            break;
          }
        }
        if (oneUp == 0) break;
        if ((step > 0) && (step >= Obase))
        {
          inter += isRightCrossing(Pts[step - 1], Pts[step], p);
        }
        step++;
        oneDown = 0;
        for (; step < nbPts; step++)
        {
          if (Pts[step].Y <= p.Y)
          {
            oneDown = 1;
            break;
          }
        }
        if (oneDown == 0) break;
        if ((step > 0) && (step >= Obase))
        {
          inter += isRightCrossing(Pts[step - 1], Pts[step], p);
        }
      }
      return (inter & 1);
    }

 </code>